作者:沂水寒城,CSDN博客專家,個人研究方向:機器學習、深度學習、NLP、CV
Blog: http://yishuihancheng.blog.csdn.net
機器學習、深度學習往往給人一種黑盒的感覺,也就是它所表現出來的可解釋性程度不高或者是很低,這就給學習使用帶來了影響,如果能夠對於機器學習的結果進行更好的解釋那將會是很棒的。
今天基於微軟開源的可解釋機器學習框架interpret進行簡單的學習實踐,主要是想上手我剛剛配置好的jupyter環境來跑一波代碼,下面先給出來GitHub地址。
https:
使用基本的要求是python版本需要在3.5以上,在這裡我正好使用的是3.6和kernel來進行實驗的。
interpret的安裝很簡單,命令如下:
pip install numpy scipy pyscaffold
pip install -U interpret
安裝方法雖然簡單,但是安裝的過程我個人覺得是比較漫長的,可能是我本地很多依賴的包版本比較低的緣故吧,在安裝的過程中有10幾個包都被卸載然後重新安裝了新的版本了。
安裝結束後我們就開始進行簡單的實踐,以波士頓房價數據為例:
首先對數據集進行簡單的探索可視化:
結果如下:
我們可以從summary的下拉框中選擇不同的屬性進行展示:
比如:這裡我們選擇第一個,結果如下:
接下來導入回歸模型:
查看一下全局可解釋性:
同樣可以在下拉框中選擇不同的信息進行查看,這裡同樣以第一個為例進行說明如下:
接下來查看一下局部的解釋性:
我個人覺得這裡還是很重要的,能夠很清晰地基於預測值和真實值的對比來分析不同特徵屬性的重要性程度。
這裡執行代碼後結果顯示如下:
我們通過下拉框來選擇不同的信息去展示,同樣展示第一個:
接下來簡單對比一些三種模型:
結果如下:
在回歸模型中,我們知道R2表示的是判定係數,在我前面的博文裡面對於回歸模型的四大評價指標都有介紹,感興趣可以去看看,相關的代碼實現都有的,這裡簡單來說就是判定係數越高表明回歸模型的擬合程度越好,模型的性能就越好。從判定係數來看:EBM模型的性能要優於線性回歸模型和回歸樹模型。
簡單的一次實踐,第一次使用jupyter還是有很多的不適應的,希望後面會變順暢吧!
上面簡單選取了三個回歸模型來進行了實驗以及結果可視化展示與分析,相信對於interpret已經有了基本的了解了,接下來我們進行一個完整的實驗,基於UCI提供的一個工資水平的分類數據集進行。我先貼出來完整的demo.ipynb的腳本內容,因為是剛開始使用這個web交互式編程環境,不像是之前直接寫的.py腳本那樣,具體實現如下:
{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"<!-- http://127.0.0.1:7525/328969744/ -->\n",
"<iframe src=\"http://127.0.0.1:7525/328969744/\" width=100% height=800 frameBorder=\"0\"></iframe>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!usr/bin/env python\n",
"#encoding:utf-8\n",
"from __future__ import division\n",
"\n",
"'''\n",
"__Author__:沂水寒城\n",
"功能: 可解釋機器學習庫 interpret 實踐使用\n",
"'''\n",
"\n",
"\n",
"import pandas as pd\n",
"from sklearn.datasets import load_boston\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.tree import DecisionTreeClassifier\n",
"from sklearn.neural_network import MLPClassifier\n",
"from sklearn.ensemble import RandomForestClassifier,GradientBoostingClassifier\n",
"from sklearn.decomposition import PCA\n",
"from sklearn.pipeline import Pipeline\n",
"from interpret import show\n",
"from interpret.perf import ROC\n",
"from interpret.data import Marginal\n",
"\n",
"\n",
"\n",
"def dataSplit(dataset,label,ratio=0.3):\n",
" '''\n",
" 數據集分割訓練集、測試集合\n",
" '''\n",
" try:\n",
" X_train,X_test,y_train,y_test=train_test_split(dataset,label,test_size=ratio)\n",
" except:\n",
" dataset,label=np.array(dataset),np.array(label)\n",
" X_train,X_test,y_train,y_test=train_test_split(dataset,label,test_size=ratio)\n",
" return X_train,X_test,y_train,y_test\n",
"\n",
" \n",
"#加載本地的數據集 \n",
"df = pd.read_csv('adult.csv')\n",
"df.columns = [ \"Age\", \"WorkClass\", \"fnlwgt\", \"Education\", \"EducationNum\",\n",
" \"MaritalStatus\", \"Occupation\", \"Relationship\", \"Race\", \"Gender\",\n",
" \"CapitalGain\", \"CapitalLoss\", \"HoursPerWeek\", \"NativeCountry\", \"Income\"\n",
" ]\n",
"\n",
"#定義特徵列範圍\n",
"train_cols = df.columns[0:-1]\n",
"#指定標籤列\n",
"label = df.columns[-1]\n",
"X = df[train_cols]\n",
"\n",
"#對分類標籤做簡化的二值化處理,轉化為:0、1分類\n",
"y = df[label].apply(lambda x: 0 if x == \" <=50K\" else 1) \n",
"\n",
"#categorical特徵數值化處理\n",
"X_enc = pd.get_dummies(X, prefix_sep='.')\n",
"feature_names = list(X_enc.columns)\n",
"#訓練集、測試集分隔\n",
"X_train, X_test, y_train, y_test = dataSplit(X_enc,y,ratio=0.3)\n",
"\n",
"#數據集探索\n",
"marginal = Marginal().explain_data(X_train, y_train, name = 'Train Data')\n",
"show(marginal)\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"RF Model Training Finished!!!\n",
"GBDT Model Training Finished!!!\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"f:\\python36\\lib\\site-packages\\sklearn\\linear_model\\logistic.py:433: FutureWarning:\n",
"\n",
"Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n",
"\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"LR Model Training Finished!!!\n",
"DT Model Training Finished!!!\n",
"MLP Model Training Finished!!!\n"
]
}
],
"source": [
"#PCA數據特徵降維+模型訓練【基於隨機森林模型】\n",
"pca = PCA()\n",
"rf = RandomForestClassifier(n_estimators=50)\n",
"RF = Pipeline([('pca', pca), ('rf', rf)])\n",
"RF.fit(X_train, y_train)\n",
"print('RF Model Training Finished!!!')\n",
"\n",
"\n",
"#PCA數據特徵降維+模型訓練【基於梯度提升決策樹模型】\n",
"pca = PCA()\n",
"gbdt = GradientBoostingClassifier(n_estimators=50)\n",
"GBDT = Pipeline([('pca', pca), ('gbdt', gbdt)])\n",
"GBDT.fit(X_train, y_train)\n",
"print('GBDT Model Training Finished!!!')\n",
"\n",
"\n",
"#PCA數據特徵降維+模型訓練【基於邏輯回歸模型】\n",
"pca = PCA()\n",
"lr = LogisticRegression()\n",
"LR = Pipeline([('pca', pca), ('lr', lr)])\n",
"LR.fit(X_train, y_train)\n",
"print('LR Model Training Finished!!!') \n",
"\n",
"\n",
"#PCA數據特徵降維+模型訓練【基於決策樹模型】\n",
"pca = PCA()\n",
"dt = DecisionTreeClassifier()\n",
"DT = Pipeline([('pca', pca), ('dt', dt)])\n",
"DT.fit(X_train, y_train)\n",
"print('DT Model Training Finished!!!') \n",
"\n",
"\n",
"#PCA數據特徵降維+模型訓練【基於多層感知器神經網絡模型】\n",
"pca = PCA()\n",
"mlp = MLPClassifier()\n",
"MLP = Pipeline([('pca', pca), ('mlp', mlp)])\n",
"MLP.fit(X_train, y_train)\n",
"print('MLP Model Training Finished!!!') "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<!-- http://127.0.0.1:7525/91332056/ -->\n",
"<iframe src=\"http://127.0.0.1:7525/91332056/\" width=100% height=800 frameBorder=\"0\"></iframe>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#隨機森林模型性能\n",
"RF_perf = ROC(RF.predict_proba).explain_perf(X_test, y_test, name='RF')\n",
"show(RF_perf)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<!-- http://127.0.0.1:7525/416994248/ -->\n",
"<iframe src=\"http://127.0.0.1:7525/416994248/\" width=100% height=800 frameBorder=\"0\"></iframe>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#梯度提升決策樹模型性能\n",
"GBDT_perf = ROC(GBDT.predict_proba).explain_perf(X_test, y_test, name='GBDT')\n",
"show(GBDT_perf)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<!-- http://127.0.0.1:7525/416993408/ -->\n",
"<iframe src=\"http://127.0.0.1:7525/416993408/\" width=100% height=800 frameBorder=\"0\"></iframe>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#邏輯回歸模型性能\n",
"LR_perf = ROC(LR.predict_proba).explain_perf(X_test, y_test, name='LR')\n",
"show(LR_perf)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<!-- http://127.0.0.1:7525/340319648/ -->\n",
"<iframe src=\"http://127.0.0.1:7525/340319648/\" width=100% height=800 frameBorder=\"0\"></iframe>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#決策樹模型性能\n",
"DT_perf = ROC(DT.predict_proba).explain_perf(X_test, y_test, name='DT')\n",
"show(DT_perf)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<!-- http://127.0.0.1:7525/339351704/ -->\n",
"<iframe src=\"http://127.0.0.1:7525/339351704/\" width=100% height=800 frameBorder=\"0\"></iframe>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#多層感知器神經網絡模型性能\n",
"MLP_perf = ROC(MLP.predict_proba).explain_perf(X_test, y_test, name='MLP')\n",
"show(MLP_perf)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "python36",
"language": "python",
"name": "python36"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
怎麼說呢,直接來看可讀性不高甚至是很差的,所以我就不去基於上述的文本形式的代碼進行講解說明了,感興趣的可以直接複製過去運行的,接下來還是針對每一段代碼塊來進行解釋說明:
首先是我們的數據部分:
主要包括數據集的加載,類別標籤的的0、1二值化轉化處理,以及訓練集和測試集劃分處理。完成上述工作之後我們對原始的數據集進行了探索,繪製圖像數據如下:
展示第一個屬性特徵的詳細信息如下:
完成了數據集的處理與探索之後,接下來需要構建和訓練模型:
可以看到:我上面一共選擇了五種模型分別是:隨機森林模型、梯度提升決策樹模型、邏輯回歸模型、決策樹模型和多層感知機神經網絡模型。該階段的輸出如下:
之後,完成了模型的訓練後就可以對各個模型的分類性能做一個評估了,在分類領域中,較為常用的指標主要包括:精確率、召回率、準確率和F1值。在數據曲線方面主要用到的有:ROC曲線【AUC值】和PR曲線。今天我們採用的是ROC曲線【AUC值】來衡量各個模型的性能,AUC值就是ROC曲線與X軸之間的面積大小,結果如下:
隨機森林模型:
梯度提升決策樹模型:
邏輯回歸模型:
決策樹模型:
多層感知器神經網絡模型:
正是因為ROC曲線無法直接用於比較大小,才使用AUC值來間接地比對,從上述五種分類模型的AUC值來看:GBDT模型的性能最好,這個也比較符合我平時的實踐,一般來說:在同等的參數配置下GBDT模型的性能相對來說都是很出色的,但是時間消耗來說也是比較大的,因為模型是串行設計和計算的。
贊 賞 作 者
Python中文社區作為一個去中心化的全球技術社區,以成為全球20萬Python中文開發者的精神部落為願景,目前覆蓋各大主流媒體和協作平臺,與阿里、騰訊、百度、微軟、亞馬遜、開源中國、CSDN等業界知名公司和技術社區建立了廣泛的聯繫,擁有來自十多個國家和地區數萬名登記會員,會員來自以工信部、清華大學、北京大學、北京郵電大學、中國人民銀行、中科院、中金、華為、BAT、谷歌、微軟等為代表的政府機關、科研單位、金融機構以及海內外知名公司,全平臺近20萬開發者關注。
▼ 點擊成為社區註冊會員 「在看」一下,一起PY