1. 程式人生 > 其它 >機器學習sklearn(三十七):演算法例項(六)分類(四)分類決策樹(四)Bonus Chapter I 例項:分類樹在合成數集上的表現

機器學習sklearn(三十七):演算法例項(六)分類(四)分類決策樹(四)Bonus Chapter I 例項:分類樹在合成數集上的表現

我們在紅酒資料集上畫出了一棵樹,並且展示了多個引數會對樹形成這樣的影響,接下來,我們將在不同結構的資料集上測試一下決策樹的效果,讓大家更好地理解決策樹。 1. 匯入需要的庫
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_moons, make_circles, make_classification
from sklearn.tree import DecisionTreeClassifier
2. 生成三種資料集 我們先從sklearn自帶的資料庫中生成三種類型的資料集:1)月亮型資料,2)環形資料,3)二分型資料
#make_classification庫生成隨機的二分型資料
X, y = make_classification(n_samples=100, #生成100個樣本
              n_features=2, #包含2個特徵,即生成二維資料
              n_redundant=0, #新增冗餘特徵0個
              n_informative=2, #包含資訊的特徵是2個
              random_state=1, #
隨機模式1 n_clusters_per_class=1 #每個簇內包含的標籤類別有1個 ) #在這裡可以檢視一下X和y,其中X是100行帶有兩個2特徵的資料,y是二分類標籤 #也可以畫出散點圖來觀察一下X中特徵的分佈 #plt.scatter(X[:,0],X[:,1]) #從圖上可以看出,生成的二分型資料的兩個簇離彼此很遠,這樣不利於我們測試分類器的效果,因此我們使用np生成 隨機陣列,通過讓已經生成的二分型資料點加減0~1之間的隨機數,使資料分佈變得更散更稀疏 #注意,這個過程只能夠執行一次,因為多次執行之後X會變得非常稀疏,兩個簇的資料會混合在一起,分類器的效應會
繼續下降 rng = np.random.RandomState(2) #生成一種隨機模式 X += 2 * rng.uniform(size=X.shape) #加減0~1之間的隨機數 linearly_separable = (X, y) #生成了新的X,依然可以畫散點圖來觀察一下特徵的分佈 #plt.scatter(X[:,0],X[:,1]) #用make_moons建立月亮型資料,make_circles建立環形資料,並將三組資料打包起來放在列表datasets中 datasets = [make_moons(noise=0.3, random_state=0), make_circles(noise=0.2, factor=0.5, random_state=1), linearly_separable]
3. 畫出三種資料集和三棵決策樹的分類效應影象
#建立畫布,寬高比為6*9
figure = plt.figure(figsize=(6, 9))
#設定用來安排影象顯示位置的全域性變數i i = 1 #開始迭代資料,對datasets中的資料進行for迴圈
for ds_index, ds in enumerate(datasets):
  
  #對X中的資料進行標準化處理,然後分訓練集和測試集
  X, y = ds
  X = StandardScaler().fit_transform(X) 
  X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.4, 
random_state=42)
  
  #找出資料集中兩個特徵的最大值和最小值,讓最大值+0.5,最小值-0.5,創造一個比兩個特徵的區間本身更大
一點的區間
  x1_min, x1_max = X[:, 0].min() - .5, X[:, 0].max() + .5
  x2_min, x2_max = X[:, 1].min() - .5, X[:, 1].max() + .5
  
  #用特徵向量生成網格資料,網格資料,其實就相當於座標軸上無數個點
  #函式np.arange在給定的兩個數之間返回均勻間隔的值,0.2為步長
  #函式meshgrid用以生成網格資料,能夠將兩個一維陣列生成兩個二維矩陣。
  #如果第一個陣列是narray,維度是n,第二個引數是marray,維度是m。那麼生成的第一個二維陣列是以
narray為行,m行的矩陣,而第二個二維陣列是以marray的轉置為列,n列的矩陣
  #生成的網格資料,是用來繪製決策邊界的,因為繪製決策邊界的函式contourf要求輸入的兩個特徵都必須是二
維的
  array1,array2 = np.meshgrid(np.arange(x1_min, x1_max, 0.2),
             np.arange(x2_min, x2_max, 0.2))
  #接下來生成彩色畫布
  #用ListedColormap為畫布建立顏色,#FF0000正紅,#0000FF正藍
  cm = plt.cm.RdBu
  cm_bright = ListedColormap(['#FF0000', '#0000FF'])
  
  #在畫布上加上一個子圖,資料為len(datasets)行,2列,放在位置i上
  ax = plt.subplot(len(datasets), 2, i)
  
  #到這裡為止,已經生成了0~1之間的座標系3個了,接下來為我們的座標系放上標題
  #我們有三個座標系,但我們只需要在第一個座標系上有標題,因此設定if ds_index==0這個條件
  if ds_index == 0:
    ax.set_title("Input data")
  
  #將資料集的分佈放到我們的座標系上
  #先放訓練集
  ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, 
        cmap=cm_bright,edgecolors='k')
  #放測試集
  ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, 
        cmap=cm_bright, alpha=0.6,edgecolors='k')
  
   #為圖設定座標軸的最大值和最小值,並設定沒有座標軸
  ax.set_xlim(array1.min(), array1.max())
  ax.set_ylim(array2.min(), array2.max())
  ax.set_xticks(())
  ax.set_yticks(())
  
  #每次迴圈之後,改變i的取值讓圖每次位列不同的位置
  i += 1
  
  #至此為止,資料集本身的影象已經佈置完畢,執行以上的程式碼,可以看見三個已經處理好的資料集
  
  #############################從這裡開始是決策樹模型##########################
  
  #迭代決策樹,首先用subplot增加子圖,subplot(行,列,索引)這樣的結構,並使用索引i定義圖的位置
  #在這裡,len(datasets)其實就是3,2是兩列
  #在函式最開始,我們定義了i=1,並且在上邊建立資料集的影象的時候,已經讓i+1,所以i在每次迴圈中的取值
是2,4,6
  ax = plt.subplot(len(datasets),2,i)
  
  #決策樹的建模過程:例項化 → fit訓練 → score介面得到預測的準確率
  clf = DecisionTreeClassifier(max_depth=5)
  clf.fit(X_train, y_train)
  score = clf.score(X_test, y_test)
  
  #繪製決策邊界,為此,我們將為網格中的每個點指定一種顏色[x1_min,x1_max] x [x2_min,x2_max]
  #分類樹的介面,predict_proba,返回每一個輸入的資料點所對應的標籤類概率
  #類概率是資料點所在的葉節點中相同類的樣本數量/葉節點中的樣本總數量
  #由於決策樹在訓練的時候匯入的訓練集X_train裡面包含兩個特徵,所以我們在計算類概率的時候,也必須匯入
結構相同的陣列,即是說,必須有兩個特徵
  #ravel()能夠將一個多維陣列轉換成一維陣列
  #np.c_是能夠將兩個陣列組合起來的函式
  #在這裡,我們先將兩個網格資料降維降維成一維陣列,再將兩個陣列連結變成含有兩個特徵的資料,再帶入決策
樹模型,生成的Z包含資料的索引和每個樣本點對應的類概率,再切片,切出類概率
  Z = clf.predict_proba(np.c_[array1.ravel(),array2.ravel()])[:, 1]
  
  #np.c_[np.array([1,2,3]), np.array([4,5,6])]
  
  #將返回的類概率作為資料,放到contourf裡面繪製去繪製輪廓
  Z = Z.reshape(array1.shape)
  ax.contourf(array1, array2, Z, cmap=cm, alpha=.8)
  
  #將資料集的分佈放到我們的座標系上
  # 將訓練集放到圖中去
  ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright,
        edgecolors='k')
  # 將測試集放到圖中去
  ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright,
        edgecolors='k', alpha=0.6)
  
  #為圖設定座標軸的最大值和最小值
  ax.set_xlim(array1.min(), array1.max())
  ax.set_ylim(array2.min(), array2.max())
  #設定座標軸不顯示標尺也不顯示數字
  ax.set_xticks(())
  ax.set_yticks(())
  
  #我們有三個座標系,但我們只需要在第一個座標系上有標題,因此設定if ds_index==0這個條件
  if ds_index == 0:
    ax.set_title("Decision Tree")
  
  #寫在右下角的數字  
  ax.text(array1.max() - .3, array2.min() + .3, ('{:.1f}%'.format(score*100)),
      size=15, horizontalalignment='right')
  
  #讓i繼續加一
  i += 1
plt.tight_layout()
plt.show()
  從圖上來看,每一條線都是決策樹在二維平面上畫出的一條決策邊界,每當決策樹分枝一次,就有一條線出現。當資料的維度更高的時候,這條決策邊界就會由線變成面,甚至變成我們想象不出的多維圖形。   同時,很容易看得出,分類樹天生不擅長環形資料。每個模型都有自己的決策上限,所以一個怎樣調整都無法提升表現的可能性也是有的。當一個模型怎麼調整都不行的時候,我們可以選擇換其他的模型使用,不要在一棵樹上吊死。順便一說,最擅長月亮型資料的是最近鄰演算法,RBF支援向量機和高斯過程;最擅長環形資料的是最近鄰演算法和高斯過程;最擅長對半分的資料的是樸素貝葉斯,神經網路和隨機森林。 開發環境是Jupyter lab,所用的庫和版本大家參考: Python 3.7.1(你的版本至少要3.4以上 Scikit-learn 0.20.0 (你的版本至少要0.19 Graphviz 0.8.4 (沒有畫不出決策樹哦,安裝程式碼conda install python-graphviz Numpy 1.15.3, Pandas 0.23.4, Matplotlib 3.0.1, SciPy 1.1.0 以上的庫和模組都是必須的,但版本可以不用太過限制,只要python在3.4以上,保證sklearn可以使用就沒問題 了。接下來,大家可以根據自己計算機的開發環境,選讀下面的章節,以完成課程需要的開發環境的配置