G. *_*cia 3 python machine-learning scikit-learn xgboost shap
我使用 shap 库来实现 ML 可解释性,以更好地理解 k 均值分割算法集群。简而言之,我制作了一些博客,使用 k-means 对它们进行聚类,然后将聚类作为标签,并使用 xgboost 来尝试预测它们。我有 5 个簇,所以这是一个单标签多类分类问题。
import numpy as np
from sklearn.datasets import make_blobs
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import xgboost as xgb
import shap
X, y = make_blobs(n_samples=500, centers=5, n_features=5, random_state=0)
data = pd.DataFrame(np.concatenate((X, y.reshape(500,1)), axis=1), columns=['var_1', 'var_2', 'var_3', 'var_4', 'var_5', 'cluster_id'])
data['cluster_id'] = data['cluster_id'].astype(int).astype(str)
scaler = StandardScaler()
scaled_features = scaler.fit_transform(data.iloc[:,:-1])
kmeans = KMeans(n_clusters=5, **kmeans_kwargs)
kmeans.fit(scaled_features)
data['predicted_cluster_id'] = kmeans.labels_.astype(int).astype(str)
clf = xgb.XGBClassifier()
clf.fit(scaled_data.iloc[:,:-1], scaled_data['predicted_cluster_id'])
shap.initjs()
explainer = shap.TreeExplainer(clf)
shap_values = explainer.shap_values(scaled_data.iloc[0,:-1].values.reshape(1,-1))
shap.force_plot(explainer.expected_value[0], shap_values[0], link='logit') # repeat changing 0 for i in range(0, 5)
Run Code Online (Sandbox Code Playgroud)
上面的图片是有意义的,因为类别是“3”。但为什么这个base_value不应该是1/5呢?不久前我问了自己一个类似的问题,但这次我已经设置了 link='logit'。
link="logit"似乎不适合多类,因为它只适合二进制输出。这就是为什么您看不到概率总和为 1 的原因。
让我们简化您的代码:
\nimport numpy as np\nfrom sklearn.datasets import make_blobs\nimport pandas as pd\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.cluster import KMeans \nimport xgboost as xgb\nimport shap\nfrom scipy.special import softmax, logit, expit\nnp.random.seed(42)\n\nX, y_true = make_blobs(n_samples=500, centers=5, n_features=3, random_state=0)\nscaler = StandardScaler()\nX_scaled = scaler.fit_transform(X)\nkmeans = KMeans(n_clusters=5)\ny_predicted = kmeans.fit_predict(X_scaled, )\n\nclf = xgb.XGBClassifier()\nclf.fit(X_scaled, y_predicted)\nshap.initjs()\nRun Code Online (Sandbox Code Playgroud)\n然后,您在以下内容中看到的预期值:
\nexplainer = shap.TreeExplainer(clf)\nexplainer.expected_value\narray([0.67111245, 0.60223354, 0.53357694, 0.50821152, 0.50145331])\nRun Code Online (Sandbox Code Playgroud)\n是原始空间中的基本分数。
\n多类原始分数可以通过以下方式转换为概率softmax:
softmax(explainer.expected_value)\narray([0.22229282, 0.20749694, 0.19372895, 0.18887673, 0.18760457])\nRun Code Online (Sandbox Code Playgroud)\nshap.force_plot(..., link="logit")对于多类没有意义,并且似乎不可能从原始切换到概率并仍然保持可加性(因为 softmax(x+y) \xe2\x89\xa0 softmax(x) + softmax(y))。
如果您希望在概率空间中分析数据,请尝试KernelExplainer:
from shap import KernelExplainer\nmasker = shap.maskers.Independent(X_scaled, 100)\nke = KernelExplainer(clf.predict_proba, data=masker.data)\nke.expected_value\n# array([0.18976762, 0.1900516 , 0.20042894, 0.19995041, 0.21980143])\nshap_values=ke.shap_values(masker.data)\nshap.force_plot(ke.expected_value[0], shap_values[0][0])\nRun Code Online (Sandbox Code Playgroud)\n\n或概要图:
\nfrom shap import Explanation\nshap.waterfall_plot(Explanation(shap_values[0][0],ke.expected_value[0]))\nRun Code Online (Sandbox Code Playgroud)\n\n现在,它们是概率空间中的形状值的累加,并且与第 0 个数据点的基本概率(见上文)和预测概率很好地对齐:
\nclf.predict_proba(masker.data[0].reshape(1,-1))\narray([[2.2844513e-04, 8.1287889e-04, 6.5225776e-04, 9.9737883e-01,\n 9.2762709e-04]], dtype=float32)\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4822 次 |
| 最近记录: |