含datetime64类型特征的不平衡数据集SMOTE过采样报错及平衡方案咨询
含datetime64类型特征的不平衡数据集SMOTE过采样报错及平衡方案咨询
嘿,这个问题我碰到过不少,咱们一步步来拆解解决~
首先说报错的原因:SMOTE这类过采样算法是基于样本间距离计算的(比如欧氏距离),它只能处理纯数值型的特征。而你的datetime64类型本质是时间格式数据,没办法直接参与距离运算,所以才会出现“dtype无法提升”的类型不兼容错误。
解决SMOTE报错的核心步骤:把datetime特征转成数值型
你需要先对datetime列做特征工程,把它转换成算法能识别的数值特征,常见的处理方式有这些:
- 提取时间分量:拆分出年、月、日、时、分、秒这些单独的数值列
- 计算时间差:比如和某个基准时间(比如数据集的最早时间)的天数/秒数差,得到一个连续数值
- 提取周期性特征:比如星期几(1-7)、一年中的第几周,或者工作日/周末的二分类标记
给你个具体的代码示例(假设你的datetime列叫timestamp):
import pandas as pd # 提取时间分量 X_dep_train['year'] = X_dep_train['timestamp'].dt.year X_dep_train['month'] = X_dep_train['timestamp'].dt.month X_dep_train['day'] = X_dep_train['timestamp'].dt.day X_dep_train['hour'] = X_dep_train['timestamp'].dt.hour # 计算与基准时间的天数差 start_date = X_dep_train['timestamp'].min() # 用数据集最早时间当基准 X_dep_train['days_since_start'] = (X_dep_train['timestamp'] - start_date).dt.days # 删除原datetime列,保留转换后的数值特征 X_dep_train = X_dep_train.drop('timestamp', axis=1)
处理完之后,所有特征都是数值型,再运行你的SMOTE代码就不会报错了:
from imblearn.over_sampling import SMOTE sm = SMOTE(random_state = 42, sampling_strategy = 1.0) X_dep_train, y_dep_train = sm.fit_resample(X_dep_train, y_dep_train)
关于测试集平衡的重要提醒
千万注意:不要对测试集做任何过采样/欠采样操作!测试集的作用是模拟真实场景的数据分布,如果你修改了它的分布,模型的评估结果会完全失真,不能反映真实性能。正确的流程是:只对训练集做SMOTE处理,测试集保持原始状态,用处理后的训练集训练模型,再用原始测试集评估。
其他可选的不平衡数据处理方案
如果你不想折腾datetime特征的转换,也可以考虑这些替代方案:
- 欠采样:直接对多数类样本进行随机删除,但可能会丢失部分信息
- 基于规则的过采样:比如直接复制少数类样本,但容易导致模型过拟合
- 使用对不平衡数据鲁棒的模型:比如XGBoost、LightGBM这类树模型,它们本身对不平衡数据有较好的适应性,可以通过调整
scale_pos_weight(XGBoost)或class_weight参数来优化,不需要特意做采样
备注:内容来源于stack exchange,提问作者Fernando Araiza
相关产品推荐
相关产品推荐

