決策樹演算法的Python實現—基於金融場景實操
決策樹是最經常使用的資料探勘演算法,本次分享jacky帶你深入淺出,走進決策樹的世界
基本概念
決策樹(Decision Tree)
- 它通過對訓練樣本的學習,並建立分類規則,然後依據分類規則,對新樣本資料進行分類預測,屬於有監督學習。
優點
1)決策樹易於理解和實現
- 使用者不需要了解很多的背景知識,通過決策樹就能夠直觀形象的瞭解分類規則;
2)決策樹能夠同時處理數值型和非數值型資料
- 在相對短的時間內,能夠對大型資料做出可行且效果良好的結果;
邏輯-類比找物件
決策樹分類的思想類似於找物件,例如一個女孩的母親要給這個女孩介紹男朋友,於是母女倆有了下面的對話:
女兒問:“多大年齡了”;母親答:“26”
女兒接著問:“長得帥不帥?”;母親答:“挺帥的。”
女兒問:“收入高不?”;母親答:“不算很高,中等情況”
女兒問:“是公務員嗎?”;母親答:“是,在財政局上班”
最後,女兒做出決定說:“那好,我去見見!”
這個女孩的決策過程就是典型的分類樹決策:
在來看一個金融場景下的舉例:客戶向銀行貸款的時候,銀行對使用者的貸款資格做一個評估的流程:
首先銀行工作人員詢問客戶是否有房產,如何回答有,則判斷客戶可以償還貸款,如果沒有則進入第二層的屬性判斷詢問,是否結婚,如何已婚,兩個人可以負擔的起貸款,則判斷為可以償還,否則進入第三層的屬性判斷詢問,月薪是否超過五千,如果滿足,則判斷為可以償還,否則給出不能償還貸款的結論。
看完上面兩個例子,我們可以看出,決策樹是非常實用的,下面我們就進入正式案例的講解;
案例實操
下面以金融場景舉例:
情景鋪墊
使用者在購買網際網路金融產品的過程“類似於”理財,對於P2P平臺來說,嚴格來說,這個過程稱之為撮合。
使用者金融平臺上充值購買相應期限和約定利率的金融產品,產品到期後,使用者有兩種選擇一個是提現(贖回),另一個就是復投。
對於使用者到期贖回的理解是比較簡單的,比如你在2018年1月1日買了6個月10萬定存金融產品,那麼在2018年7月1日的時候,你可以選擇連本帶息全部贖回,當然你也可以在到期日選擇在平臺還款時,繼續投資,這個過程就是復投。
下面,在嚴謹一點歸納復投的定義就是:
針對按月等額本息還款的使用者,還款或,使用者自己再投,這個過程就是復投。
需解決的問題
作為金融平臺來說,為了把控風險,保證資金的流動性,都一定要提前預測(預判)未來一段時間內的使用者充值和提現金額。
那麼,準確預測使用者到期是否復投,對於我們金融從業者和管理人員來說,就是特別重要了。
那麼,我們可以提出我們亟需解決的問題:
- 使用者到期是否復投,我們改怎樣預判?
一個初步模型的建立
場景:預測使用者是否復投
注:以下源資料模擬真實資料編撰
(一)選擇特徵變數-featureDate
1. 資料來源抓取
import pandas
data = pandas.read_csv('file:///Users/apple/Desktop/jacky_reinvest.csv',encoding='GBK')
print(data)
jacky註解(1):上面這份資料來源其實是經過預處理(或者說是經過初步的資料清理的),我們拿到資料來源的第一步一定是做資料清理的,資料科學與傳統的統計科學,在實操中,區別最大的可能就是資料清理了,本文的資料來源只用於學習舉例用,所以資料還是比較規整的,但在實際工作中,一定不要忘了資料清洗這一步。
jacky註解(2): 初始心裡預期這列是一個產品概念,就是使用者在購買定存金融產品的時候,可以預先設定是否需要復投,當然這只是一個預設定,在使用者購買到贖回這個過程中,我們都可以隨時變更。復投模式是一個過去式,也是最終的復投結果,所以下面我們會把這列當作目標變數來處理。
2. 啞變數處理(虛擬變數轉化)
需處理的特徵變數有:
金融產品
初始心裡預期
客戶類別
#呼叫Map方法進行可比較大小虛擬變數的轉換
productDict={'12個月定存':4,'6個月定存':3,'3個月定存':2,'1個月定存':1}
data['產品Map']=data['金融產品'].map(productDict)
#呼叫get_dummyColumns方法進行不可比較大小虛擬變數的轉換
dummyColumns = ['初始心裡預期','客戶類別',]
for column in dummyColumns:
data[column]= data[column].astype('category')
dummiesData=pandas.get_dummies(
data,
columns=dummyColumns,prefix=dummyColumns
,prefix_sep='_',dummy_na=False,drop_first=False)
#挑選可以建模的變數 featureData
fData = dummiesData[[
'購買金額','產品Map','初始心裡預期_復投','客戶類別_VIP使用者'
]]
jacky註解(3):關於啞變數更詳細的說明,可以參照我《特徵工程三部曲》這篇文章,啞變數處理要處理的就是離散變數,購買金額的列,因為都是連續型資料,所以就談不上虛擬變數處理的。
jacky註解(4):離散變數分為有比較關係的離散變數和無比較關係的離散變數,所以需要用map方法和get_dummyColumns方法分別處理;
(二)選擇目標變數-targerDate
#設定目標變數 targetData
tData = dummiesData['復投模式']
- jacky註解(5):目標變數是我們分析問題的目標和結果,從目標變數既定的歷史資料中,我們可以”餵養”資料,繼而訓練資料,最終達到洞察預測資料的目的。
(三)決策樹問題的求解與建模
#生成決策樹
from sklearn.tree import DecisionTreeClassifier
#設定最大葉子數為5
dtModel = DecisionTreeClassifier(max_leaf_nodes=5)
- jacky註解(6):生成決策樹並設定最大葉子樹為5,使⽤sklearn的DecisionTreeClassifer類進⾏行決策樹問題的求解與建模,關於最大葉子樹,可以在看過圖形化之後,在反過來理解這部分,就簡單的多了,在這裡我們可以先理解為是一個很常用的引數即可。
(四)10折交叉驗證
#模型檢驗-交叉驗證法
from sklearn.model_selection import cross_val_score
cross_val_score(
dtModel,
fData,tData,cv=10
)
- jacky註解(7):從控制檯的輸出可以看出,每次驗證的評分都超過0.9,是一個非常不錯的模型,可以用於實踐;
(五)模型訓練
#訓練模型
dtModel=dtModel.fit(fData,tData)
控制檯結果輸出:
(六)模型視覺化
決策樹的繪圖方法:
sklearn.tree.export_graphviz(… …)
dtModel:決策樹模型
out_file:圖形資料的輸出路徑
class_names:目標屬性的名稱,一般用於中文化
feature_names:特徵屬性的名稱,一般用於種文化
filled= True :是否使用顏色填充
rounded=True:邊框是否採用圓角邊框
special_characters: 是否有特殊字元
#模型視覺化
import pydotplus
from sklearn.externals.six import StringIO #生成StringIO物件
from sklearn.tree import export_graphviz
dot_data = StringIO() #把檔案暫時寫在記憶體的物件中
export_graphviz(
dtModel,
out_file=dot_data,
class_names=['復投','不復投'],
feature_names=['購買金額','產品Map','初始心裡預期_不復投','客戶類別_VIP使用者'],
filled=True,rounded=True,special_characters=True
)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_png('shujudata.png')
jacky註解(8):需要提前安裝graphviz軟體
jacky註解(9):最大葉子樹,一般設定為8個,因為葉子數太多,決策樹的結構越複雜,太複雜的結構就會導致訓練過度的問題,因此,在決策樹演算法中,設定合適葉子數是非常重要的。
jacky註解(10):gini值越接近於0,那麼結果就越顯而易見,如果越接近於1,那麼結果就越難判定;
完整程式碼展示
#---author:朱元祿---
import pandas
data = pandas.read_csv('file:///Users/apple/Desktop/jacky_reinvest.csv',encoding='GBK')
#呼叫Map方法進行可比較大小虛擬變數的轉換
productDict={'12個月定存':4,'6個月定存':3,'3個月定存':2,'1個月定存':1}
data['產品Map']=data['金融產品'].map(productDict)
#呼叫get_dummyColumns方法進行可比較大小虛擬變數的轉換
dummyColumns = ['初始心裡預期','客戶類別',]
for column in dummyColumns:
data[column]= data[column].astype('category')
dummiesData=pandas.get_dummies(
data,
columns=dummyColumns,prefix=dummyColumns
,prefix_sep='_',dummy_na=False,drop_first=False)
#挑選可以建模的變數 featureData
fData = dummiesData[[
'購買金額','產品Map','初始心裡預期_復投','客戶類別_VIP使用者'
]]
#設定目標變數 targetData
tData = dummiesData['復投模式']
#生成決策樹
from sklearn.tree import DecisionTreeClassifier
#設定最大葉子數為8
dtModel = DecisionTreeClassifier(max_leaf_nodes=8)
'''
#模型檢驗-交叉驗證法
from sklearn.model_selection import cross_val_score
cross_val_score(
dtModel,
fData,tData,cv=10
)
'''
#訓練模型
dtModel=dtModel.fit(fData,tData)
#模型視覺化
import pydotplus
from sklearn.externals.six import StringIO #生成StringIO物件
from sklearn.tree import export_graphviz
dot_data = StringIO() #把檔案暫時寫在記憶體的物件中
export_graphviz(
dtModel,
out_file=dot_data,
class_names=['復投','不復投'],
feature_names=['購買金額','產品Map','初始心裡預期_不復投','客戶類別_VIP使用者'],
filled=True,rounded=True,special_characters=True
)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_png('shujudata.png')