Scikit-learn 分类器具有依赖于训练特征的自定义记分器
Posted
技术标签:
【中文标题】Scikit-learn 分类器具有依赖于训练特征的自定义记分器【英文标题】:Scikit-learn classifier with custom scorer dependent on a training feature 【发布时间】:2018-08-21 03:49:33 【问题描述】:我正在尝试使用 自定义记分器 训练 RandomForestClassifier,其输出需要依赖于其中一项功能。
X 数据集包含 18 个特征:
y 是通常的 0 和 1 数组:
带有自定义记分器的 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 自定义分数将是它们和特征的组合。
我的问题是,鉴于其标准签名接受 y_true 和 y_pred,我如何将该功能传递给 custom_scorer_function?
我知道它接受额外的 **kwargs,但以这种方式传递整个特征数组并不能解决问题,因为该函数是为每一对 y_true 和 y_pred 调用的 值(需要提取与它们对应的单个特征值才能使其正常工作,我不确定是否可以这样做)。
我已尝试扩充 y_true 数组,将该功能打包并在 custom_scorer_function 中解包(第一列是实际标签,第二列是特征值我需要计算自定义分数):
但是这样做违反了分类器对具有一维标签数组的要求并触发以下错误。
ValueError:未知标签类型:'连续多输出'
非常感谢任何帮助。
谢谢。
【问题讨论】:
我不知道你为什么要通过特征...你可以使用权重或特征重要性来影响分数..\ 问题是score根据y_true和y_pred的值使用了我想通过的特征值,即根据y_true = y_pred = 0, y_true =的情况会有4个潜在的score值0 和 y_pred = 1 等等.... 您应该首先发布您的代码,其次,您可以将功能定义为全局变量并在 custom_score 函数中访问它们 正如@Eliethesaiyan 所说,只需在自定义记分器中引用我们的全局特征数据即可。特征的顺序和标签应该匹配, @Eliethesaiyan 一旦定义了自定义记分器函数,要传递给 GridSearchCV 的自定义记分器对象一般创建为: custom_scorer = make_scorer(custom_scorer_function, greater_is_better=True, extra_arg1=..., extra_arg2= ... 等等)具有自定义记分器函数签名,然后是: def custom_scorer_function(y_true, y_pred, extra_arg1, extra_arg2, ...) 那么您将如何将索引“i”作为“extra arg”传递给它呢? 【参考方案1】:你可以做这样的事情(注意你没有给出真正的代码,所以这是准系统)
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)
...
【讨论】:
这不会解决它。根据您的代码,实际上,在每个训练步骤(记分器的每次调用)中,您将有一个“标量”y、一个“标量”y_pred 和一个“数组”a_feature。正如我所说,只有当您想要的自定义分数取决于 a_feature 的全局统计信息(例如 (y - y_pred) * max(a_feature))时,这才有效。您将如何从“在每个训练步骤”中选择实际对应于“标量”y 和“标量”y_pred 的值? @ClaudioN 在调用记分员时,y
和 y_pred
不是数组吗?
不!这正是问题所在。自定义记分器在后台调用,并且在每一步处理几个标量值(Y-true 和 y_pred)。我还需要传递从 X[:, 10] 中获取的与那些标量相对应的标量值,即 X[row, 10] 其中行是索引,使得 y_true = y[row]。
抱歉,我对记分员的理解是他们获取了完整的训练/测试数据,因此试图找出记分员的来源。当您的自定义记分器只做print(y)
和print(y_pred)
时,您会得到什么?
@ClaudioN,我也面临同样的问题,基本上,Gridsearch有交叉验证选项(默认为cv 3),当它适合(X,Y)时,你怎么能访问X的一些功能并且您不知道当前折叠的索引?以上是关于Scikit-learn 分类器具有依赖于训练特征的自定义记分器的主要内容,如果未能解决你的问题,请参考以下文章
使用 scikit-learn 训练数据时,SVM 多类分类停止
在 scikit-learn 中拟合分类器之前进行特征缩放的必要性