用Scikit-learn线性回归预测配送时间时,如何处理新司机ID类别?
处理线性回归中未知分类类别的简便方案
针对你遇到的训练集外出现新driver_id的问题,给你几个更简便的落地方案,都是基于Scikit-learn能快速实现的:
方案1:目标编码(带平滑)替代类别编码
放弃把driver_id当分类变量做One-Hot或哑编码,改用目标编码:
- 训练阶段:对每个已知
driver_id,计算该司机所有订单的final_time均值,作为这个司机的编码值;为了避免过拟合(比如某个司机只有1单),加入平滑逻辑:# 手动实现平滑目标编码的示例 global_mean = df_train['final_time'].mean() m = df_train.groupby('driver_id')['final_time'].count().mean() # 平滑参数,取平均配送量 df_train['driver_encoded'] = df_train.groupby('driver_id')['final_time'].transform( lambda x: (len(x)*x.mean() + m*global_mean)/(len(x)+m) ) - 预测阶段:遇到新
driver_id,直接用全局final_time均值作为编码值即可。
这种方法把类别转换成了连续特征,线性回归可以直接拟合,完全不需要额外的二元变量或交互项,新司机的处理逻辑也很自然。如果不想自己写,也可以用category_encoders库的TargetEncoder,配置好平滑参数就行。
方案2:直接用司机的统计特征替代driver_id
彻底抛弃driver_id这个分类字段,提取和司机表现相关的统计特征喂给模型:
- 司机的平均配送耗时(训练集司机用自身均值,新司机用全局均值)
- 司机的总配送量(新司机如果有历史配送量就用,没有就用训练集司机的平均配送量)
- (如果有数据的话)司机的平均配送距离、超时率等
线性回归对连续特征的拟合很友好,新司机的特征直接用全局统计值填充,模型可以直接预测,完全不存在未知类别的问题,这也是最省心的方案。
方案3:带“未知”类别的One-Hot编码(简单但效果有限)
如果你坚持要用类别编码,可以在预处理阶段做如下操作:
- 训练时,把所有
driver_id做One-Hot编码,同时手动添加一个“unknown”类别(即使训练集里没有这个类别的样本); - 预测时,把所有训练集外的新
driver_id替换成“unknown”,再做One-Hot编码。
不过要注意:因为训练集里没有“unknown”的样本,模型学到的这个类别的系数会是0,相当于新司机的这部分效应被忽略,模型只能靠其他特征预测。Scikit-learn的OneHotEncoder可以设置handle_unknown='ignore',效果类似——预测时遇到未知类别,对应的One-Hot特征全为0,不用手动处理“unknown”类别,但本质一样,适合对司机效应要求不高的场景。
对比你的初始思路,上面的方案都不需要处理复杂的交互项,逻辑更简洁,也更容易在Scikit-learn中实现。
内容的提问来源于stack exchange,提问作者skiador
相关产品推荐
相关产品推荐

