从分类器中检索训练特征名称列表
Posted
技术标签:
【中文标题】从分类器中检索训练特征名称列表【英文标题】:Retrieve list of training features names from classifier 【发布时间】:2017-03-21 23:36:01 【问题描述】:在使用fit
方法训练分类器后,有没有办法检索用于训练分类器的特征名称列表?我想在应用到看不见的数据之前获得这些信息。
用于训练的数据是 pandas DataFrame
,在我的例子中,分类器是 RandomForestClassifier
。
【问题讨论】:
我遇到了同样的问题。这对我来说是一个大问题,因为特征序列可以在我的预处理中置换。当我预处理我的预测数据以使用模型进行预测时,我不再有办法知道我在哪里训练的特征序列是什么。我只保留pkl。我当然也可以存储一个列表,但这似乎是一个糟糕的方法。 【参考方案1】:您无需知道为培训选择了哪些功能。只需确保在预测步骤中为拟合分类器提供您在学习阶段使用的相同特征。
随机森林分类器只会使用它进行分割的特征。这些将与第一阶段所学的相同。其他的将不予考虑。
如果您的测试数据的形状与训练数据不同,即使测试数据也一样会抛出错误包含用于分割决策树的所有特征。
此外,由于随机森林为您的决策树(在 sklearn
中称为 estimators
)随机选择特征,所有特征都可能至少使用一次。
不过,如果你想知道使用的特征,你可以在你的分类器上调用属性n_features_
和feature_importances_
一旦安装。
您可以查看here,了解如何检索您使用的最重要功能的名称。
【讨论】:
您建议的解决方案仅返回功能的数量而不是它们的名称。我知道在预测阶段,不需要提供名称,只需提供相同的功能即可。但是,就我而言,我事先不知道选择的训练特征是什么(以及列顺序,如果这很重要)。 我正在创建一个以分类器为参数的函数。为了不对我可能事先不知道的变量列表进行硬编码,或者避免拼写错误或只是输入无穷无尽的变量列表,最好将其存储在分类器本身中。 谢谢,我明白了,但这无助于从分类器获取特征名称。如果我以与其他人不同的方式执行数据处理,则数据框中的列/特征的顺序和索引可能会有所不同。除非我错过了你的意思......这就是为什么我真的想要来自分类器本身而不是来自训练或应用程序数据的特征名称。 @user6903745 - 已经有几年了,但我想知道您是否找到了令人满意的解决方案。我完全和你在一起;如果预测崩溃,对象本身应该有足够的信息。有时我认为青少年设计了这部分代码,因为他们习惯于拥有美好的记忆力。 “哦,当然,我知道那个密码在哪里!”它归结为sklearn
依赖于文件中列的位置,这根本不是一个好习惯。
@MichaelTuchman 我通常存储功能名称列表,我觉得这还算满意。如果我有更多时间和更清晰的用例,我可能会用一些额外的信息 MTC 创建我自己的自定义分类器类。【参考方案2】:
根据文档和以前的经验,无法获得至少在一次拆分中考虑的功能列表。
您是否担心不想将所有功能都用于预测,而只使用实际用于训练的功能?在这种情况下,我建议在拟合后列出feature_importances_
,并消除似乎不相关的功能。然后训练一个只有相关特征的新模型,并将这些特征也用于预测。
【讨论】:
一个担忧是未来的另一个程序员可能会提供预测对象无法处理的数据集。假设原始代码不可用,模型对象应该能够吐出与计算相关的所有参数是一个基本的期望。简而言之,对象应该是不言自明的。【参考方案3】:我有一个可行但不是很优雅的解决方案。这是一个没有现有解决方案的旧帖子,所以我想没有任何解决方案。
创建并拟合您的模型。例如
model = GradientBoostingRegressor(**params)
model.fit(X_train, y_train)
然后您可以添加一个属性,即“feature_names”,因为您在训练时就知道它们
model.feature_names = list(X_train.columns.values)
我通常会将模型放入二进制文件中以传递它,但您可以忽略它
joblib.dump(model, filename)
loaded_model = joblib.load(filename)
然后您可以从模型中获取特征名称,以便在预测时使用它们
f_names = loaded_model.feature_names
loaded_model.predict(X_pred[f_names])
【讨论】:
相反,我觉得这个解决方案很优雅,我发现的所有其他解决方案都需要两页代码来提取名称列表。想到一件事,不应该是没有 .values 的 """X_train.columns""" 吗? 也采用了这种方法 :),值得注意的是,这在 XGBoost 之类的模型中有一些先例,这些模型将标签写入属性“feature_names”。 @FlyingTurtle 你是对的,list(df.columns.values) 返回相同的结果 list(df.columns),OP 可能只是觉得从 index --> np.array --> list 转换更舒服,但可以直接来自索引 --> 列表。【参考方案4】:您可以从经过训练的 XGBOOST 模型中提取特征名称,如下所示:
model.get_booster().feature_names
【讨论】:
以上是关于从分类器中检索训练特征名称列表的主要内容,如果未能解决你的问题,请参考以下文章