1. 程式人生 > >python3.5《機器學習實戰》學習筆記(五):決策樹演算法實戰之預測隱形眼鏡型別

python3.5《機器學習實戰》學習筆記(五):決策樹演算法實戰之預測隱形眼鏡型別

一、使用決策樹預測隱形眼鏡型別

在上一篇文章中,我們學習了決策樹演算法,接下來,讓我們通過一個例子講解決策樹如何預測患者需要佩戴的隱形眼鏡型別。
隱形眼鏡資料集是非常著名的資料集,它包含了很多患者眼部狀況的觀察條件以及醫生推薦的隱形眼鏡型別。隱形眼鏡型別包括硬材質(hard)、軟材質(soft)以及不適合佩戴隱形眼鏡(no lenses)。資料來源於UCI資料庫,資料儲存在文字檔案中,資料集下載地址:下載
資料集資訊:
* 特徵有四個:age(年齡)、prescript(症狀)、astigmatic(是否散光)、tearRate(眼淚數量)
* 隱形眼鏡類別有三類(最後一列):硬材質(hard)、軟材質(soft)、不適合佩戴隱形眼鏡(no lenses)

這裡寫圖片描述

在上篇文章的程式碼基本上,只需要在主函式改為如下程式碼即可。
if __name__ == '__main__':
    fr = open('lenses.txt')
    lenses = [inst.strip().split('\t') for inst in fr.readlines()]
    print(lenses)
    lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']
    myTree_lenses = createTree(lenses, lensesLabels)
    createPlot(myTree_lenses)

執行結果:

這裡寫圖片描述

二、sklearn實戰-預測隱形眼鏡型別

2-1 基本引數

引數說明如下:(引數說明網上有人已經翻譯過了,這裡就直接拿過來)

  • criterion:特徵選擇標準,可選引數,預設是gini,可以設定為entropy。gini是基尼不純度,是將來自集合的某種結果隨機應用於某一資料項的預期誤差率,是一種基於統計的思想。entropy是夏農熵,也就是上篇文章講過的內容,是一種基於資訊理論的思想。Sklearn把gini設為預設引數,應該也是做了相應的斟酌的,精度也許更高些?ID3演算法使用的是entropy,CART演算法使用的則是gini。
  • splitter:特徵劃分點選擇標準,可選引數,預設是best,可以設定為random。每個結點的選擇策略。best引數是根據演算法選擇最佳的切分特徵,例如gini、entropy。random隨機的在部分劃分點中找區域性最優的劃分點。預設的”best”適合樣本量不大的時候,而如果樣本資料量非常大,此時決策樹構建推薦”random”。
  • max_features:劃分時考慮的最大特徵數,可選引數,預設是None。尋找最佳切分時考慮的最大特徵數(n_features為總共的特徵數),有如下6種情況:
    • 如果max_features是整型的數,則考慮max_features個特徵;
    • 如果max_features是浮點型的數,則考慮int(max_features * n_features)個特徵;
    • 如果max_features設為auto,那麼max_features = sqrt(n_features);
    • 如果max_features設為sqrt,那麼max_featrues = sqrt(n_features),跟auto一樣;
    • 如果max_features設為log2,那麼max_features = log2(n_features);
    • 如果max_features設為None,那麼max_features = n_features,也就是所有特徵都用。
      一般來說,如果樣本特徵數不多,比如小於50,我們用預設的”None”就可以了,如果特徵數非常多,我們可以靈活使用剛才描述的其他取值來控制劃分時考慮的最大特徵數,以控制決策樹的生成時間。
  • max_depth:決策樹最大深,可選引數,預設是None。這個引數是這是樹的層數的。層數的概念就是,比如在貸款的例子中,決策樹的層數是2層。如果這個引數設定為None,那麼決策樹在建立子樹的時候不會限制子樹的深度。一般來說,資料少或者特徵少的時候可以不管這個值。或者如果設定了min_samples_slipt引數,那麼直到少於min_smaples_split個樣本為止。如果模型樣本量多,特徵也多的情況下,推薦限制這個最大深度,具體的取值取決於資料的分佈。常用的可以取值10-100之間。
  • min_samples_split:內部節點再劃分所需最小樣本數,可選引數,預設是2。這個值限制了子樹繼續劃分的條件。如果min_samples_split為整數,那麼在切分內部結點的時候,min_samples_split作為最小的樣本數,也就是說,如果樣本已經少於min_samples_split個樣本,則停止繼續切分。如果min_samples_split為浮點數,那麼min_samples_split就是一個百分比,ceil(min_samples_split * n_samples),數是向上取整的。如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。
  • min_weight_fraction_leaf:葉子節點最小的樣本權重和,可選引數,預設是0。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝。一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分佈類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。
  • max_leaf_nodes:最大葉子節點數,可選引數,預設是None。通過限制最大葉子節點數,可以防止過擬合。如果加了限制,演算法會建立在最大葉子節點數內最優的決策樹。如果特徵不多,可以不考慮這個值,但是如果特徵分成多的話,可以加以限制,具體的值可以通過交叉驗證得到。
  • class_weight:類別權重,可選引數,預設是None,也可以字典、字典列表、balanced。指定樣本各類別的的權重,主要是為了防止訓練集某些類別的樣本過多,導致訓練的決策樹過於偏向這些類別。類別的權重可以通過{class_label:weight}這樣的格式給出,這裡可以自己指定各個樣本的權重,或者用balanced,如果使用balanced,則演算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。當然,如果你的樣本類別分佈沒有明顯的偏倚,則可以不管這個引數,選擇預設的None。
  • random_state:可選引數,預設是None。隨機數種子。如果是證書,那麼random_state會作為隨機數生成器的隨機數種子。隨機數種子,如果沒有設定隨機數,隨機出來的數與當前系統時間有關,每個時刻都是不同的。如果設定了隨機數種子,那麼相同隨機數種子,不同時刻產生的隨機數也是相同的。如果是RandomState instance,那麼random_state是隨機數生成器。如果為None,則隨機數生成器使用np.random。
  • min_impurity_split:節點劃分最小不純度,可選引數,預設是1e-7。這是個閾值,這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,資訊增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。即為葉子節點 。
  • presort:資料是否預排序,可選引數,預設為False,這個值是布林值,預設是False不排序。一般來說,如果樣本量少或者限制了一個深度很小的決策樹,設定為true可以讓劃分點選擇更加快,決策樹建立的更加快。如果樣本量太大的話,反而沒有什麼好處。問題是樣本量少的時候,我速度本來就不慢。所以這個值一般懶得理它就可以了。

除了這些引數要注意以外,其他在調參時的注意點有:

  • 當樣本數量少但是樣本特徵非常多的時候,決策樹很容易過擬合,一般來說,樣本數比特徵數多一些會比較容易建立健壯的模型
  • 如果樣本數量少但是樣本特徵非常多,在擬合決策樹模型前,推薦先做維度規約,比如主成分分析(PCA),特徵選擇(Losso)或者獨立成分分析(ICA)。這樣特徵的維度會大大減小。再來擬合決策樹模型效果會好。
  • 推薦多用決策樹的視覺化,同時先限制決策樹的深度,這樣可以先觀察下生成的決策樹裡資料的初步擬合情況,然後再決定是否要增加深度。
  • 在訓練模型時,注意觀察樣本的類別情況(主要指分類樹),如果類別分佈非常不均勻,就要考慮用class_weight來限制模型過於偏向樣本多的類別。
  • 決策樹的陣列使用的是numpy的float32型別,如果訓練資料不是這樣的格式,演算法會先做copy再執行。
  • 如果輸入的樣本矩陣是稀疏的,推薦在擬合前呼叫csc_matrix稀疏化,在預測前呼叫csr_matrix稀疏化。

2-2 載入資料

pandas是一個非常強大的庫,用它處理CSV、txt資料檔案很方便。接下來我們使用pandas載入隱形眼鏡檔案,程式碼如下:

import pandas as pd

lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate','class']
#特徵標籤+類別標籤
feature = ['age', 'prescript', 'astigmatic', 'tearRate']#特徵標籤
lenses = pd.read_table('lenses.txt',names=lensesLabels, sep='\t')
#names:設定列名 ,sep:分隔的正則表示式,'/t'表示以tab鍵進行分割

檢視lenses變數:

這裡寫圖片描述

2-3 資料處理

瞭解了上面的引數可以知道,sklearn函式fit時需要資料X(也即是特徵資料)滿足numpy的float32型別。但是隱形眼鏡的特徵資料是各種英文單詞,是字串。格式不對,所以,在使用fit()函式之前,我們需要對資料集進行編碼,這裡可以使用兩種方法:

使用LabelEncoder編碼結果:

這裡寫圖片描述

2-3 建立決策樹

程式碼如下:

'''
Created on Nov 10, 2017
Decision Tree Source Code for Machine Learning in Action Ch. 3
author: weepon
blog: http://blog.csdn.net/u013829973
Modify:
    2017-11-10
'''
from sklearn.preprocessing import LabelEncoder
from sklearn import tree
import pandas as pd

lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate','class']#特徵標籤+類別標籤
feature = ['age', 'prescript', 'astigmatic', 'tearRate']#特徵標籤
lenses = pd.read_table('lenses.txt',names=lensesLabels, sep='\t')
#names:設定列名 ,sep:分隔的正則表示式,'/t'表示以tab鍵進行分割

lenses_feature = lenses[feature]                        # 特徵資料
le = LabelEncoder()                                    
 #建立LabelEncoder()物件,用於序列化           
for col in lenses_feature.columns:                      #分列序列化
    lenses_feature[col] = le.fit_transform(lenses_feature[col])

clf = tree.DecisionTreeClassifier(max_depth = 4)            
#建立DecisionTreeClassifier()類
model = clf.fit(lenses_feature.values, lenses['class'])     #使用資料,構建決策樹
print(model)                                             # 檢視當前模型引數

#預測
pre = model.predict([[0,1,0,1]])
print('預測結果為',pre)

執行結果:

這裡寫圖片描述

PS: 如果覺得本篇本章對您有所幫助,歡迎關注、評論、頂!
本文出現的所有程式碼和資料集,均可在我的github上下載,歡迎Follow、Star:
我的GitHubhttps://github.com/weepon