use*_*827 16 python scikit-learn
我正在使用scikit额外的树分类器:
model = ExtraTreesClassifier(n_estimators=10000, n_jobs=-1, random_state=0)
Run Code Online (Sandbox Code Playgroud)
一旦模型被拟合并用于预测类,我想找出每个特征对特定类预测的贡献.我如何在scikit中学习呢?是否可以使用额外的树分类器或我是否需要使用其他模型?
Ulf*_*lak 15
今天对ML的了解比我2.5年前更加了解,我现在说这种方法只适用于高度线性的决策问题.如果你不小心将它应用于非线性问题,你将遇到麻烦.
示例:想象一个功能,既没有非常大的值也没有非常小的值预测类,但是在某个中间间隔中的值确实如此.这可能是饮水以预测脱水.但是水的摄入可能与盐的摄入相互作用,因为多吃盐可以增加水的摄入量.现在,您可以在两个非线性要素之间进行交互.决策边界蜿蜒在您的特征空间周围,以模拟这种非线性,并仅询问其中一个特征影响脱水风险的程度根本无知.这不是正确的问题.
替代方案:您可以提出的另一个更有意义的问题是:如果我没有这些信息(如果我遗漏了这个功能),我对给定标签的预测会受到多大影响?要做到这一点,您只需省略一项功能,训练模型并查看每个班级的精确度和召回率.它仍然告知特征重要性,但它没有对线性进行假设.
以下是旧答案.
我在前一段时间里遇到了类似的问题并在Cross Validated上发布了相同的问题.简短的回答是没有实现sklearn所有你想要的东西.
但是,您要实现的目标非常简单,可以通过将每个类的每个特征拆分的平均标准化平均值与相应的model._feature_importances数组元素相乘来完成.您可以编写一个简单的函数来标准化数据集,计算跨类预测的每个特征拆分的平均值,并与model._feature_importances数组进行元素相乘.绝对结果值越大,特征对其预测类越重要,更好的是,符号将告诉您它是重要的小值还是大值.
这是一个超级简单的实现,它采用数据矩阵X,预测列表Y和一系列要素重要性,并输出描述每个要素对每个类的重要性的JSON.
def class_feature_importance(X, Y, feature_importances):
N, M = X.shape
X = scale(X)
out = {}
for c in set(Y):
out[c] = dict(
zip(range(N), np.mean(X[Y==c, :], axis=0)*feature_importances)
)
return out
Run Code Online (Sandbox Code Playgroud)
例:
import numpy as np
import json
from sklearn.preprocessing import scale
X = np.array([[ 2, 2, 2, 0, 3, -1],
[ 2, 1, 2, -1, 2, 1],
[ 0, -3, 0, 1, -2, 0],
[-1, -1, 1, 1, -1, -1],
[-1, 0, 0, 2, -3, 1],
[ 2, 2, 2, 0, 3, 0]], dtype=float)
Y = np.array([0, 0, 1, 1, 1, 0])
feature_importances = np.array([0.1, 0.2, 0.3, 0.2, 0.1, 0.1])
#feature_importances = model._feature_importances
result = class_feature_importance(X, Y, feature_importances)
print json.dumps(result,indent=4)
{
"0": {
"0": 0.097014250014533204,
"1": 0.16932975630904751,
"2": 0.27854300726557774,
"3": -0.17407765595569782,
"4": 0.0961523947640823,
"5": 0.0
},
"1": {
"0": -0.097014250014533177,
"1": -0.16932975630904754,
"2": -0.27854300726557779,
"3": 0.17407765595569782,
"4": -0.0961523947640823,
"5": 0.0
}
}
Run Code Online (Sandbox Code Playgroud)
第一级键result是类标签,第二级键是列索引,即特征索引.回想一下,大的绝对值对应于重要性,并且符号告诉您它是小的(可能是负的)还是重要的大值.
这篇论文 “Why Should I Trust You?”: Explaining the Predictions of Any Classifier是在这个问题之后9天提交的,提供了一个通用解决这个问题的算法!:-)
简而言之,它被称为“本地可解释模型不可知解释”的 LIME,它通过围绕您想要理解的预测拟合一个更简单的本地模型来工作。
更重要的是,他们制作了一个 python 实现(https://github.com/marcotcr/lime),其中包含有关如何将它与 sklearn 一起使用的非常详细的示例。例如,这个是关于文本数据的两类随机森林问题,而这个是关于连续和分类特征的。它们都可以通过 github 上的 README 找到。
作者在 2016 年在这个领域非常有成效,所以如果你喜欢阅读论文,这里是一个初学者:
这是从文档修改
from sklearn import datasets
from sklearn.ensemble import ExtraTreesClassifier
iris = datasets.load_iris() #sample data
X, y = iris.data, iris.target
model = ExtraTreesClassifier(n_estimators=10000, n_jobs=-1, random_state=0)
model.fit_transform(X,y) # fit the dataset to your model
Run Code Online (Sandbox Code Playgroud)
我想feature_importances_你正在寻找:
In [13]: model.feature_importances_
Out[13]: array([ 0.09523045, 0.05767901, 0.40150422, 0.44558631])
Run Code Online (Sandbox Code Playgroud)
编辑
也许我误解了第一次(赏金前),对不起,这可能更符合您的要求.有一个叫做python的库treeinterpreter可以产生我认为你正在寻找的信息.你必须使用基本DecisionTreeClassifer(或回归).在此博客文章中,您可以在每个实例的预测中离散地访问要素贡献:
from sklearn import datasets
from sklearn.cross_validation import train_test_split
from sklearn.tree import DecisionTreeClassifier
from treeinterpreter import treeinterpreter as ti
iris = datasets.load_iris() #sample data
X, y = iris.data, iris.target
#split into training and test
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.33, random_state=0)
# fit the model on the training set
model = DecisionTreeClassifier(random_state=0)
model.fit(X_train,y_train)
Run Code Online (Sandbox Code Playgroud)
X_test为了说明的目的,我将迭代每个示例,这几乎完全模仿上面的博客文章:
for test_sample in range(len(X_test)):
prediction, bias, contributions = ti.predict(model, X_test[test_sample].reshape(1,4))
print "Class Prediction", prediction
print "Bias (trainset prior)", bias
# now extract contributions for each instance
for c, feature in zip(contributions[0], iris.feature_names):
print feature, c
print '\n'
Run Code Online (Sandbox Code Playgroud)
循环的第一次迭代产生:
Class Prediction [[ 0. 0. 1.]]
Bias (trainset prior) [[ 0.34 0.31 0.35]]
sepal length (cm) [ 0. 0. 0.]
sepal width (cm) [ 0. 0. 0.]
petal length (cm) [ 0. -0.43939394 0.43939394]
petal width (cm) [-0.34 0.12939394 0.21060606]
Run Code Online (Sandbox Code Playgroud)
解释这个输出,似乎花瓣长度和花瓣宽度是预测第三类(对于第一个样本)最重要的贡献者.希望这可以帮助.