?
文章發布于公號【數智物語】 (ID:decision_engine),關注公號不錯過每一篇干貨。
?
?
?
轉自 | 法納斯特(公眾號ID:walker398)
作者 | 小F
?
決策樹呈樹形結構,是一種基本的回歸和分類方法。
?
決策樹模型的優點在于可讀性強、分類速度快。
?
下面通過從「譯學館」搬運的兩個視頻,來簡單了解下決策樹。
?
?
?
最后來實戰一波,建立一個簡單的決策樹模型。
?
01決策樹算法
?
本次主要涉及兩類決策樹,Quinlan系列決策樹和CART決策樹。
?
前者涉及的算法包括ID3算法、C4.5算法及C5.0算法,后者則是CART算法。
?
前者一系列算法的步驟總體可以概括為建樹和剪樹。
?
在建樹步驟中,首先選擇最有解釋力度的變量,接著對每個變量選擇最優的分割點進行剪樹。
?
剪樹,去掉決策樹中噪音或異常數據,在損失一定預測精度的情況下,能夠控制決策樹的復雜度,提高其泛化能力。
?
在剪樹步驟中,分為前剪枝和后剪枝。
?
前剪枝用于控制樹的生成規模,常用方法有控制決策樹最大深度、控制樹中父結點和子結點的最少樣本量或比例。
?
后剪枝用于刪除沒有意義的分組,常用方法有計算結點中目標變量預測精度或誤差、綜合考慮誤差與復雜度進行剪樹。
?
此外在ID3算法中,使用信息增益挑選最有解釋力度的變量。
?
其中信息增益為信息熵減去條件熵得到,增益越大,則變量的影響越大。
?
C4.5算法則是使用信息增益率作為變量篩選的指標。
?
CART算法可用于分類或數值預測,使用基尼系數(gini)作為選擇最優分割變量的指標。
?
02Python實現
?
對一份汽車違約貸款數據集進行讀取數據、數據清洗。(數據來源于《python數據科學:技術詳解與商業實踐》一書)
?
import?os
import?pydotplus
import?numpy?as?np
import?pandas?as?pd
import?sklearn.tree?as?tree
import?matplotlib.pyplot?as?plt
from?IPython.display?import?Image
import?sklearn.metrics?as?metrics
from?sklearn.tree?import?DecisionTreeClassifier
from?sklearn.model_selection?import?train_test_split,?ParameterGrid,?GridSearchCV
#?消除pandas輸出省略號情況
pd.set_option('display.max_columns',?None)
#?設置顯示寬度為1000,這樣就不會在IDE中換行了
pd.set_option('display.width',?1000)
#?讀取數據,skipinitialspace:忽略分隔符后的空白
accepts?=?pd.read_csv('accepts.csv',?skipinitialspace=True)
#?dropna:對缺失的數據進行刪除
accepts?=?accepts.dropna(axis=0,?how='any')
#?因變量,是否違約
target?=?accepts['bad_ind']
#?自變量
data?=?accepts.ix[:,?'bankruptcy_ind':'used_ind']
#?業務處理,loan_amt:貸款金額,tot_income:月均收入
data['lti_temp']?=?data['loan_amt']?/?data['tot_income']
data['lti_temp']?=?data['lti_temp'].map(lambda?x:?10?if?x?>=?10?else?x)
#?刪除貸款金額列
del?data['loan_amt']
#?替換曾經破產標識列
data['bankruptcy_ind']?=?data['bankruptcy_ind'].replace({'N':?0,?'Y':?1})
?
接下來使用scikit-learn將數據集劃分為訓練集和測試集。
?
#?使用scikit-learn將數據集劃分為訓練集和測試集
train_data,?test_data,?train_target,?test_target?=?train_test_split(data,?target,?test_size=0.2,?train_size=0.8,?random_state=1234)
?
初始化一個決策樹模型,使用訓練集進行訓練。
?
采用基尼系數作為樹的生長依據,樹的最大深度為3,每一類標簽的權重一樣。
?
#?初始化一個決策樹模型
clf?=?DecisionTreeClassifier(criterion='gini',?max_depth=3,?class_weight=None,?random_state=1234)
#?輸出決策樹模型信息
print(clf.fit(train_data,?train_target))
?
輸出的模型信息如下。
?
?
對生成的決策樹模型進行評估。
?
#?輸出決策樹模型的決策類評估指標
print(metrics.classification_report(test_target,?clf.predict(test_data)))
#?對不同的因變量進行權重設置
clf.set_params(**{'class_weight':?{0:?1,?1:?3}})
clf.fit(train_data,?train_target)
#?輸出決策樹模型的決策類評估指標
print(metrics.classification_report(test_target,?clf.predict(test_data)))
#?輸出決策樹模型的變量重要性排序
print(list(zip(data.columns,?clf.feature_importances_)))
?
輸出如下。
?
?
可以看出對因變量標簽進行權重設置后,模型對違約用戶的f1-score(精確率和召回率的調和平均數)提高了,為0.46。
?
違約用戶被識別的靈敏度也從0.24提高到了0.46。
?
此外決策樹模型的變量重要性排序為「FICO打分」、「信用卡授權額度」、「貸款金額/建議售價*100」。
?
通過安裝graphviz和相應的插件,便能實現決策樹的可視化輸出,具體安裝過程不細說。
?
#?設置graphviz路徑
os.environ["PATH"]?+=?os.pathsep?+?'C:/Program?Files?(x86)/Graphviz2.38/bin/'
#?決策樹的可視化
dot_data?=?tree.export_graphviz(clf,?out_file=None,?feature_names=data.columns,?class_names=['0',?'1'],?filled=True)
graph?=?pydotplus.graph_from_dot_data(dot_data)
Image(graph.create_png())
#?將決策樹模型輸出為圖片
graph.write_png(r'pang.png')
#?將決策樹模型輸出為PDF
graph.write_pdf('tree.pdf')
?
可視化結果如下。
?
?
可以看見決策樹根節點以fico_score <= 683.5為分割標準。
?
全體樣本的基尼系數為0.483,在3284個樣本中,被預測變量為0的有2671個,為1的有1839個。
?
使用scikit-learn提供的參數搜索進行調優(GridSearchCV)。
?
#?設置樹的最大深度
max_depth?=?[None,?]
#?設置樹的最大葉節點數
max_leaf_nodes?=?np.arange(5,?10,?1)
#?設置樹的類標簽權重
class_weight?=?[{0:?1,?1:?2},?{0:?1,?1:?3}]
#?設置參數網格
param_grid?=?{'max_depth':?max_depth,
??????????????'max_leaf_nodes':?max_leaf_nodes,
??????????????'class_weight':?class_weight}
#?對參數組合進行建模和效果驗證
clf_cv?=?GridSearchCV(estimator=clf,
??????????????????????param_grid=param_grid,
??????????????????????cv=5,
??????????????????????scoring='roc_auc')
#?輸出網格搜索的決策樹模型信息
print(clf_cv.fit(train_data,?train_target))
?
輸出網格搜索的決策樹模型信息。
?
?
使用得到的“最優”模型對測試集進行評估。
?
#?輸出優化后的決策樹模型的決策類評估指標
print(metrics.classification_report(test_target,?clf_cv.predict(test_data)))
#?輸出優化后的決策樹模型的參數組合
print(clf_cv.best_params_)
?
輸出結果。
?
?
計算模型在不同閾值下的靈敏度和特異度指標,繪制ROC曲線。
?
#?使用模型進行預測
train_est?=?clf_cv.predict(train_data)
train_est_p?=?clf_cv.predict_proba(train_data)[:,?1]
test_est?=?clf_cv.predict(test_data)
test_est_p?=?clf_cv.predict_proba(test_data)[:,?1]
#?繪制ROC曲線
fpr_test,?tpr_test,?th_test?=?metrics.roc_curve(test_target,?test_est_p)
fpr_train,?tpr_train,?th_train?=?metrics.roc_curve(train_target,?train_est_p)
plt.figure(figsize=[3,?3])
plt.plot(fpr_test,?tpr_test,?'b--')
plt.plot(fpr_train,?tpr_train,?'r-')
plt.title('ROC?curve')
plt.show()
#?計算AUC值
print(metrics.roc_auc_score(test_target,?test_est_p))
?
ROC曲線圖如下,其中訓練集的ROC曲線(實線)與測試集的ROC曲線(虛線)很接近,說明模型沒有過擬合。
?
?
模型的ROC曲線下面積為0.7358,模型效果一般。
?
推薦閱讀:
?
?
?
星標我,每天多一點智慧
?