【開箱即用】利用sklearn創(chuàng)建決策樹(cart)密幔,可視化訓(xùn)練結(jié)果(樹)

標(biāo)簽:代碼實(shí)戰(zhàn)楔脯,經(jīng)過(guò)驗(yàn)證,sklearn.tree可視化老玛,機(jī)器學(xué)習(xí)淤年,決策樹,cart蜡豹,開箱即用
利用sklearn.treeimport DecisionTreeClassifier創(chuàng)建數(shù)據(jù)的決策樹,并可視化結(jié)果
[TOC]

前提

python包:pydotplus溉苛、numpy镜廉、sklearn∮拚剑可通過(guò)pip install安裝娇唯。
Graphviz,安裝參見(jiàn)“可視化樹”一節(jié)

TODO:實(shí)例化

from sklearn.treeimport DecisionTreeClassifier
dt = DecisionTreeClassifier(criterion='gini',# 分類用基尼寂玲,回歸用'entropy'
                            splitter='best',# 結(jié)點(diǎn)分裂方式塔插,'best' 與'random'
                            min_samples_leaf=20,# 葉子節(jié)點(diǎn)包含的最少樣本數(shù)
                            random_state=2020,# 隨機(jī)策略
                            class_weight='balanced',# balanced根據(jù)樣本數(shù)量自動(dòng)調(diào)整權(quán)重
                            presort=True,# 數(shù)據(jù)集小用True,否則用false拓哟,可以提高速度
                            )

參數(shù)可以參考:http://www.reibang.com/p/f0f41ad72e5f
其他cart相關(guān)http://d0evi1.com/sklearn/cart/

TODO: 訓(xùn)練數(shù)據(jù)準(zhǔn)備與訓(xùn)練/生成決策樹

  • 訓(xùn)練數(shù)據(jù)要求
    --feature是numpy.array想许,數(shù)據(jù)類型為numpy.float64,第i行是第i條數(shù)據(jù),第j列是對(duì)應(yīng)數(shù)據(jù)的第j個(gè)特征
    --label是numpy.array流纹,數(shù)據(jù)類型為numpy.int16糜烹,只有一列,第i行是第i條數(shù)據(jù)漱凝。若想使用float的label疮蹦,參見(jiàn)本節(jié)尾部的”真實(shí)輸出y是float應(yīng)該怎么改“
    # # 加載文件示例
    # # loadDataSet和相應(yīng)數(shù)據(jù)參見(jiàn)https://github.com/Jack-Cherish/Machine-Learning
    # train_filename = 'cart_train.txt'
    # train_Data = loadDataSet(train_filename)  # 前幾列是參數(shù),最后一列是目標(biāo)
    # train_Mat = np.mat(train_Data)
    # feature = train_Mat[:, list(range(train_Mat.shape[1] - 1))]
    # label = train_Mat[:, -1].astype(np.int16)  # float轉(zhuǎn)int
    # 使用隨機(jī)數(shù)做演示
    feature = np.random.rand(100, 4) # 100行 4列茸炒,0-1的隨機(jī)浮點(diǎn)數(shù)
    label = np.random.randint(0, 3, size=(100, 1))# [0,3)的隨機(jī)整數(shù)愕乎,100行 1列

    # TODO:訓(xùn)練
    dt = dt.fit(feature, label)
  • 真實(shí)輸出y是float應(yīng)該怎么改
    當(dāng)前代碼中真實(shí)輸出要求int類型,即訓(xùn)練時(shí)的y必須是int類型壁公,因?yàn)閷?shí)例化時(shí)criterion用的是'gini'感论,如果是float,修改兩處代碼贮尖,一處是示例化時(shí)的criterion笛粘,一處是訓(xùn)練數(shù)據(jù)中不調(diào)用astype(np.int16)
  • 異常: ValueError: Unknown label type: 'continuous'
    大概率是因?yàn)槭褂昧嘶嵯禂?shù)但y卻是float類型的,如果數(shù)據(jù)的y本就是float湿硝,則調(diào)整實(shí)例化的criterion為'entropy'薪前;如果y本是int,注意要轉(zhuǎn)換為int

TODO:可視化樹

from sklearn.treeimport export_graphviz
from sklearn.externals.siximport StringIO
import pydotplus
import os
# 配置Graphviz的dot的地址挽牢。可能配置好環(huán)境變量之后重啟os酌毡,就不需要這部分了话原。
path_graphviz ="D:/software/graphviz/Graphviz2.44.1/bin"  # replace by your Graphviz bin path
os.environ["PATH"] += os.pathsep + path_graphviz
# 轉(zhuǎn)換格式,從而保存本地
dot_data = StringIO()
dot_data = export_graphviz(dt,out_file=None)
graph = pydotplus.graph_from_dot_data(dot_data)
# graph = pydotplus.graph_from_dot_data(dot_data.getvalue())# 見(jiàn)到這個(gè)寫法线衫,但是我本地嘗試是失敗的
# graph.write_pdf("tmp/tree.pdf")
graph.write_jpg("tmp/tree.jpg")
print('Visible tree plot saved.')

之后可以查看"tmp/tree.jpg"


tree.jpg

【exception】pydotplus.graphviz.InvocationException: GraphViz's executables not found

  1. 確定graphviz已安裝凿可。
    注意不是pip安裝的python包,而是官網(wǎng)下載資源后按官網(wǎng)說(shuō)明來(lái)安裝的程序
  2. 檢查代碼中是否path_graphviz配置有誤授账。
    注意"D:/software/graphviz"是安裝時(shí)選擇的安裝路徑枯跑,"D:/software/graphviz/Graphviz2.44.1"是graphviz的安裝目錄,它有"bin","include","lib","share"四個(gè)文件夾白热, "D:/software/graphviz/Graphviz2.44.1/bin"才是我們要配的路徑地址敛助。
    參考:https://blog.csdn.net/weixin_36407399/article/details/87890230

【exception】Format: "jpg" not recognized. Use one of:

Use one of:后面是空的,說(shuō)明需要cmd執(zhí)行一下dot -c屋确。
“dot -c“ means: Configure plugins (Writes $prefix/lib/graphviz/config with available plugin information. Needs write privilege.)
如果是linux系統(tǒng)纳击,可能需要root權(quán)限sudo dot -c
如果沒(méi)有配環(huán)境變量续扔,就是D:\software\graphviz\Graphviz2.44.1\bin\dot.exe -c
參考:https://blog.csdn.net/qq_43166422/article/details/105540575

TODO:預(yù)測(cè)

    pre=dt.predict(feature)
    #TODO:評(píng)估
    print(estimate(label.T.tolist()[0],pre.T.tolist())) # 參數(shù)必須是一維數(shù)組

評(píng)估結(jié)果(由于訓(xùn)練數(shù)據(jù)是隨機(jī)生成的,所以這里只是格式參考)

混淆矩陣:
  true\pre         0         1         2
         0        14         3        19        36
         1         4        14        14        32
         2         5         4        23        32
                  23        21        56
report:
              precision    recall  f1-score   support

           0       0.61      0.39      0.47        36
           1       0.67      0.44      0.53        32
           2       0.41      0.72      0.52        32

   micro avg       0.51      0.51      0.51       100
   macro avg       0.56      0.52      0.51       100
weighted avg       0.56      0.51      0.51       100

評(píng)估函數(shù)

import numpy
from sklearn.metrics import classification_report

def estimate(true_label:[], predict_label:[],confu_row_prefix='\t',confu_coltitle_sep='\t'):
    '''輸入true_label和predict_label 輸出評(píng)估結(jié)果'''
    # TODO: 函數(shù)進(jìn)入條件
    assert type(true_label)==type([]) 
    assert type(predict_label)==type([])
    assert len(true_label) == len(predict_label)
    # TODO:初始化混淆矩陣
    class_k=set(true_label)
    class_k=list(class_k)
    class_num = len(class_k)
    assert class_num>=1
    confu = numpy.zeros([class_num, class_num])  # confu[實(shí)際][預(yù)測(cè)]
    k_v={class_k[i]:i for i in range(class_num)}

    # TODO:遍歷每一行統(tǒng)計(jì)準(zhǔn)確率
    for ix in range(0, len(true_label)):  # 遍歷訓(xùn)練集的每行
        confu[k_v[true_label[ix]]][k_v[predict_label[ix]]] += 1  # confu[實(shí)際][預(yù)測(cè)]
    # TODO:混淆矩陣打印字符串
    string='混淆矩陣:\n%10s'%'true\pre'
    sum_col=numpy.sum(confu,axis=0)#按列相加
    sum_row=numpy.sum(confu,axis=1)#按行相加
    # title
    for i in range(class_num):
        string+='%10s'%(class_k[i])
    string+='\n'
    # data
    for i in range(class_num):
        string+='%10s'%(class_k[i])
        for j in range(class_num):
            string+='%10s'%(int(confu[i][j]))
        string+='%10s'%(int(sum_row[i]))# support
        string+='\n'
    # support
    string+='%10s'%''
    for i in range(class_num):
        string+='%10s'%(int(sum_col[i]))
    string+='\n'

    # TODO:準(zhǔn)確率评疗、召回率等評(píng)估結(jié)果
    cr = classification_report(true_label,
                               predict_label)

    string+='report:\n'
    string+=str(cr)
    return string

決策樹的一些認(rèn)知

  • 一些方法:
    • ID3:
      • 增熵测砂。
      • 會(huì)越分越細(xì),容易過(guò)擬合百匆,所以有C4.5
    • C4.5
      • 信息增益率(增熵要除以屬性熵)
      • 需要對(duì)數(shù)據(jù)集進(jìn)行多次掃描砌些,算法效率相對(duì)較低
    • CART:
      • GINI指數(shù)。
      • 同樣容易過(guò)擬合加匈。需剪枝存璃,對(duì)特別長(zhǎng)的樹直接剪掉。

一些要點(diǎn):

  1. 節(jié)點(diǎn)的分裂:一般當(dāng)一個(gè)節(jié)點(diǎn)所代表的屬性無(wú)法給出判斷時(shí)雕拼,則選擇將這一節(jié)點(diǎn)分成2個(gè)子節(jié)點(diǎn)(如不是二叉樹的情況會(huì)分成n個(gè)子節(jié)點(diǎn))
  2. 閾值的確定:選擇適當(dāng)?shù)拈撝凳沟梅诸愬e(cuò)誤率最小 (Training Error)纵东。
  3. 剪枝:預(yù)剪枝、后剪枝

熵的計(jì)算:
熵的計(jì)算

基尼系數(shù)的計(jì)算:
基尼系數(shù)的計(jì)算
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啥寇,一起剝皮案震驚了整個(gè)濱河市偎球,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辑甜,老刑警劉巖衰絮,帶你破解...
    沈念sama閱讀 212,185評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異磷醋,居然都是意外死亡猫牡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,445評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門邓线,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)淌友,“玉大人,你說(shuō)我怎么就攤上這事骇陈≌鹜ィ” “怎么了?”我有些...
    開封第一講書人閱讀 157,684評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵你雌,是天一觀的道長(zhǎng)归薛。 經(jīng)常有香客問(wèn)我,道長(zhǎng)匪蝙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,564評(píng)論 1 284
  • 正文 為了忘掉前任习贫,我火速辦了婚禮逛球,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘苫昌。我一直安慰自己颤绕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,681評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奥务,像睡著了一般物独。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上氯葬,一...
    開封第一講書人閱讀 49,874評(píng)論 1 290
  • 那天挡篓,我揣著相機(jī)與錄音,去河邊找鬼帚称。 笑死官研,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的闯睹。 我是一名探鬼主播戏羽,決...
    沈念sama閱讀 39,025評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼楼吃!你這毒婦竟也來(lái)了始花?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,761評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤孩锡,失蹤者是張志新(化名)和其女友劉穎酷宵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浮创,經(jīng)...
    沈念sama閱讀 44,217評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忧吟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,545評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斩披。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溜族。...
    茶點(diǎn)故事閱讀 38,694評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垦沉,靈堂內(nèi)的尸體忽然破棺而出煌抒,到底是詐尸還是另有隱情,我是刑警寧澤厕倍,帶...
    沈念sama閱讀 34,351評(píng)論 4 332
  • 正文 年R本政府宣布寡壮,位于F島的核電站,受9級(jí)特大地震影響讹弯,放射性物質(zhì)發(fā)生泄漏况既。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,988評(píng)論 3 315
  • 文/蒙蒙 一组民、第九天 我趴在偏房一處隱蔽的房頂上張望棒仍。 院中可真熱鬧,春花似錦臭胜、人聲如沸莫其。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,778評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)乱陡。三九已至浇揩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間憨颠,已是汗流浹背胳徽。 一陣腳步聲響...
    開封第一講書人閱讀 32,007評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留烙心,地道東北人膜廊。 一個(gè)月前我還...
    沈念sama閱讀 46,427評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像淫茵,于是被迫代替她去往敵國(guó)和親爪瓜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,580評(píng)論 2 349