River 是当前唯一活跃、API 稳定、文档完整的在线学习框架,取代已停止维护且不兼容新 Python/NumPy 版本的 Creme;其核心为单样本增量更新 learn_one(),需手动处理数据映射、缺失值、类别编码及概念漂移检测,并注意序列化、线程安全与指标监控等部署细节。

在线学习模型更新不是“训练完再加载”,而是模型必须能接收单条或小批量新数据、实时调整参数——Creme 已停止维护,River 是当前唯一活跃、API 稳定、文档完整的选择。
为什么不能继续用 Creme
Creme 从 2022 年起不再发布新版本,其 pip install creme 安装的已是最终版(v0.9.0),不兼容 Python 3.11+,且与 NumPy 1.24+ 存在 dtype 冲突,运行时大概率报错 AttributeError: 'numpy.ndarray' object has no attribute 'tolist'。社区已明确迁移至 River,所有新特性(如多输出、在线特征选择、分布式流评估)只在 River 中实现。
用 River 实现单样本增量更新(Classifier)
River 的核心设计是“一个实例一个 learn_one()”,不需要 batch、不需要 fit() 循环封装。常见错误是误把整个数据集传给 learn_one(),导致类型错误。
-
learn_one()只接受单个x(字典,如{'age': 32, 'income': 58000})和单个y(标量或字符串) - 分类器需先初始化,例如
river.tree.HoeffdingTreeClassifier()或轻量级river.linear_model.LogisticRegression() - 预测用
predict_one(),返回值类型与训练时y类型一致;概率用predict_proba_one()
示例:
立即学习“Python免费学习笔记(深入)”;
from river import tree
model = tree.HoeffdingTreeClassifier()
<p>x = {'sepal_length': 5.1, 'sepal_width': 3.5, 'petal_length': 1.4, 'petal_width': 0.2}
y = 'setosa'</p><p>model = model.learn_one(x, y) # 返回更新后的 model(支持链式调用)
y_pred = model.predict_one(x) # → 'setosa'
处理真实流数据时的关键配置点
真实场景中,数据不是理想字典,常来自 CSV 行、Kafka 消息或传感器 JSON。River 不自动解析,必须手动映射。容易忽略的三点:
- 缺失值:River 大部分模型原生支持
None或float('nan'),但需确保传入前未被 pandas 自动转成np.nan(会触发 TypeError) - 类别型特征:必须显式用
river.preprocessing.OneHotEncoder或river.feature_extraction.TargetEncoder包裹,不能直接丢字符串字段 - 概念漂移检测:若业务中标签分布会变(如欺诈模式演化),必须搭配
river.drift.ADWIN或river.drift.KSWIN主动重置模型,而非依赖模型自适应
典型组合:
from river import preprocessing, linear_model, drift
model = (
preprocessing.OneHotEncoder() |
linear_model.LogisticRegression()
)
drift_detector = drift.ADWIN(delta=0.002)
<p>for x, y in stream.iter_csv('live_transactions.csv', y='is_fraud'):
y_pred = model.predict_one(x)
model = model.learn_one(x, y)</p><pre class="brush:php;toolbar:false;">if not drift_detector.update(y_pred == y): # 准确率突降
model = model.revert() # 回退上一状态,或全新初始化
性能与部署注意事项
River 模型是纯 Python 实现,无 C 扩展,单核吞吐约 1–5 万样本/秒(视模型复杂度),足够多数边缘或 API 场景。但要注意:
- 模型对象本身可 pickle,但推荐用
river.utils.load_json/dump_json序列化,更轻量、跨版本兼容性更好 - 多线程不安全:同一模型实例不能被多个线程并发调用
learn_one();高并发需加锁,或为每个 worker 分配独立模型副本 - 内存不会自动释放旧节点:树类模型(如 Hoeffding Tree)持续增长,需定期用
model.forget()清理历史统计(仅部分模型支持)
最易被忽略的是:River 默认不做任何日志或指标上报,所有评估(准确率、F1、延迟)必须手动累积计算——没有内置的 evaluate_stream() 那种“开箱即用”监控,得自己搭。


















