我一直在尝试在scikit-learn中使用加权样本,同时训练随机森林分类器。当我将样本权重直接传递给分类器时,它工作得很好,例如 RandomForestClassifier().fit(X,y,sample_weight=weights)
,但是当我尝试网格搜索为分类器找到更好的超参数时,我遇到了一堵墙:
若要在使用 grid 参数时传递权重,用法为:
grid_search = GridSearchCV(RandomForestClassifier(), params, n_jobs=-1,
fit_params={"sample_weight"=weights})
问题是交叉验证器不知道样本权重,因此不会将它们与实际数据一起重新采样,因此调用grid_search.fit(X,y)
失败:交叉验证器创建 X 和 y 的子集,sub_X和sub_y,最终使用 classifier.fit(sub_X, sub_y, sample_weight=weights)
调用分类器,但现在权重尚未重新采样,因此抛出异常。
目前,我已经通过在训练分类器之前对高权重样本进行过度采样来解决此问题,但这是一个临时解决方法。关于如何进行的任何建议?
我的名声太少,所以我不能评论@xenocyon。我正在使用 sklearn 0.18.1,并且在代码中使用管道。对我有用的解决方案是:
fit_params={'classifier__sample_weight': w}
其中w
是权重向量,classifier
是管道中的步骤名称。
编辑:我从下面看到的分数似乎不太正确。这可能是因为,如上所述,即使使用权重进行拟合,它们也可能不会用于评分。
现在看来这个问题已经解决了。我正在运行 sklearn 版本 0.15.2。我的代码看起来像这样:
model = SGDRegressor()
parameters = {'alpha':[0.01, 0.001, 0.0001]}
cv = GridSearchCV(model, parameters, fit_params={'sample_weight': weights})
cv.fit(X, y)
希望对您有所帮助(您和其他看到这篇文章的人)。
我建议编写自己的交叉验证参数选择,因为它在python中只有10-15行代码(特别是使用scikit-learn的kfold对象),而过采样可能是一个很大的瓶颈。