小夥伴們你們好~o( ̄▽ ̄)ブ,今天咱們開始來看一下Sklearn分類樹的表現,個人開發環境是Jupyter lab,所用的庫和版本你們參考:python
Python算法
Scikit-learn 0.20.0 (你的版本至少要0.20)數據庫
Graphviz 0.8.4 (沒有畫不出決策樹哦,安裝代碼conda install python-graphviz)數組
Numpy 1.15.3, Pandas 0.23.4, Matplotlib 3.0.1, SciPy 1.1.0網絡
在這裏,咱們使用SKlearn構建三種不一樣分佈的數據,而後在這些數據集上測試一下決策樹的效果,讓你們更好地理解決策樹。下圖就是三種表現結果,後面會詳細介紹實現過程~dom
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
咱們先從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之間的隨機數,使數據分佈變得更散更稀疏。spa
【注意】這個過程只可以運行一次,由於屢次運行以後X會變得很是稀疏,兩個簇的數據會混合在一塊兒,分類器的效應會繼續降低3d
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]
#建立畫布,寬高比爲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支持向量機和高斯過程;最擅長環形數據的是最近鄰算法和高斯過程;最擅長對半分的數據的是樸素貝葉斯,神經網絡和隨機森林。