使用自定义得分器的Scikit-learn分类器,该得分器依赖于训练特征

3
我正在尝试使用自定义评分器训练一个RandomForestClassifier,其输出需要取决于其中一个特征。
X数据集包含18个特征:X dataset y是通常的0和1数组:y_true RandomForestClassifier与自定义评分器在GridSearchCV实例中使用: GridSearchCV(classifier, param_grid=[...], scoring=custom_scorer).
通过Scikit-learn函数make_scorer定义自定义评分器: custom_scorer = make_scorer(custom_scorer_function, greater_is_better=True).
如果custom_scorer_function仅依赖于y_true和y_pred,则该框架非常直观。但在我的情况下,我需要定义一个得分器,它使用X数据集中的18个特征之一,即根据y_pred和y_true的值,定制分数将是它们和该特征的组合。
我的问题是,如何将特征传递到custom_scorer_function中,考虑到它的标准签名只接受y_true和y_pred?
我知道它接受额外的**kwargs,但是以这种方式传递整个特征数组并不能解决问题,因为对于每个y_true和y_pred值对,都会调用此函数(需要提取与它们相对应的单个特征值才能使其正常工作,我不确定是否可以完成)。
我尝试增强y_true数组,将该特征打包到其中,并在custom_scorer_function中解包它(第一列是实际标签,第二列是需要计算定制分数的特征值):y_true_augmented。但这样做违反了分类器对1D标签数组的要求,并触发了以下错误:ValueError: Unknown label type: 'continuous-multioutput'。非常感谢您的任何帮助。谢谢。

1
我不确定为什么你想传递它的特征...你可以使用权重或特征重要性来影响分数。 - Eliethesaiyan
1
你应该先发布你的代码,其次,你可以将特征定义为全局变量,并在custom_score函数中访问它们。 - Eliethesaiyan
@Eliethesaiyan,@Ken Syme 将特征数据作为全局变量传递是行不通的。实际上,custom_scorer函数的一般签名如下:def custom_scorer(y_true, y_pred, **kwargs)。在训练期间,每个训练步骤都会使用y_true和y_pred(每个标量)调用此函数以生成得分值。 如果我将我的特征数据(假设为X [:,10])作为额外参数传递到custom_scorer函数中,则在每个训练步骤中都会将其视为数组。如果您的自定义分数类似于(y_true-y_pred)* max(X [:,10]),那么这将起作用,但这不是我想要的。 - ClaudioN
1
一旦定义了自定义评分器函数,通常会创建自定义评分器对象以传递给GridSearchCV:custom_scorer = make_scorer(custom_scorer_function, greater_is_better=True, extra_arg1=..., extra_arg2=... and so on)其中自定义评分器函数的签名如下:def custom_scorer_function(y_true, y_pred, extra_arg1, extra_arg2, ...)那么你要如何将索引“i”作为“额外参数”传递给它呢? - ClaudioN
@ClaudioN,你解决了这个问题吗?在Gridsearch的自定义评分函数中访问当前折叠的索引? - Yasmin
显示剩余4条评论
1个回答

0
你可以像这样做(注意,你没有提供真正的代码,所以这只是基本框架)。
X = [...]
y = [...]

def custom_scorer_function(y, y_pred, **kwargs):
   a_feature = X[:,1]
   # now have y, y_pred and the feature you want

custom_scorer = make_scorer(custom_scorer_function, greater_is_better=True)
...

1
这并不能解决问题。根据你的代码,在每个训练步骤(每次评分器的调用)中,你将有一个“标量”y,一个“标量”y_pred和一个“数组”a_feature。只有当你想要的自定义得分,如我所说,依赖于a_feature的全局统计信息时(例如(y - y_pred) * max(a_feature)),这才能起作用。你将如何在“每个训练步骤”中选择与“标量”y和“标量”y_pred实际对应的a_feature值? - ClaudioN
@ClaudioN 在调用评分器时,yy_pred不也是数组吗? - Ken Syme
不!这正是问题所在。自定义评分器在幕后被调用,每一步都要处理几个标量值(Y-true 和 y_pred)。我需要将对应于这些标量的 X[:, 10] 中的标量值也传递给它,即 X[row, 10],其中 row 是索引,使得 y_true = y[row]。 - ClaudioN
我做到了。虽然出现了错误(显然不是真正的得分器),但我确实在控制台中打印了两个数组,所以你可能是正确的!谢谢提醒。然后,我将特征数组作为 **kwargs 的一部分传递给自定义评分函数,并且GridSearchCV似乎顺利进行。然而,当我使用gs.score(testX, testY)计算分数时,得到了非常奇怪的值,其中gs是GridSearchCV对象,testX和testY表示测试数据集。不确定得分器是否按预期运行,但肯定是向前迈进了一步! - ClaudioN
3
@ClaudioN,我遇到了同样的问题。基本上,Gridsearch有交叉验证选项(默认为cv=3)。当它拟合(X,Y)时,如果你不知道当前fold的索引,如何访问X的一些特征? - Yasmin
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接