Python 機器學習實戰 —— 監督學習(下)

前言

近年來AI人工智能成為社會發展趨勢,在IT行業引起一波熱潮,有關機器學習、深度學習、神經網絡等文章多不勝數。從智能家居、自動駕駛、無人機、智能機械人到人造衛星、安防軍備,無論是國家級軍事設備還是廣泛的民用設施,都充斥着AI應用的身影。接下來的一系列文章將會由淺入深從不同角度分別介紹機器學習、深度學習之間的關係與區別,通過一系統的常用案例講述它們的應用場景。
在上一篇文章《 Python 機器學習實戰 —— 監督學習(上)》中已經講述了機械學習的相關概念與基礎知識,監督學習的主要流程。對損失函數進行了基礎的介紹,並對常用的均方誤差與遞度下降法的計算過程進行演示,並對常用的 LogisticRegression , LinearSVC、SGDClassifier、 LinearRegression、Ridge、Lasso 、SGDRegressor  等線性模型進行了介紹,講解了非線性 PolynomialFeatures 多項式轉換器以及管道 Pipe 的基本用法。
本文將介紹支持向量機、k近鄰、樸素貝葉斯分類 、決策樹、決策樹集成等模型的應用。

 

 

目錄

一、淺談機器學習

二、基本概念

三、常用方法介紹

四、線性模型

五、支持向量機

六、k近鄰

七、樸素貝葉斯分類器 

八、決策樹與決策樹集成

 

 

五、支持向量機

支持向量機(Support Vector Machine,SVM)是一個功能強大的模型,它概支持線性分類和非線性分類(SVC),也支持回歸(SVR),是機器學習中最常用的模型之一。回顧上一章節《 Python 機器學習實戰 —— 監督學習(上)》所介紹的 LinearSVC 線性支持向量機就是屬於 SVC 的一種,可把它看作是 SVC 的一個特殊類型。

5.1 SVM 的由來

回顧在上一章節介紹 LogisticRegression 線性分類模型,可以知道在同一組二分類數據當中,有不止一條的直線可以把它們完美地分割,從中很難判斷哪一條分割線能更好地讓新的數據點分配到正確的標籤。

 1 def logistic(c=1.0):
 2     #生成數據集
 3     X,y=datasets.make_forge()
 4     X_train,X_test,y_train,y_test=train_test_split(X,y)
 5     #對Logistic模型進行訓練
 6     logistic=LogisticRegression(C=c,random_state=1)
 7     logistic.fit(X_train,y_train)
 8     #輸入正確率
 9     print('logistic\n  train data:{0}'.format(logistic.score(X_train,y_train)))
10     print('  test data:{0}'.format(logistic.score(X_test,y_test)))
11     #輸出模型點
12     plt.scatter(X[:,0], X[:,1],c=y,s=100)
13     plt.legend(['model','data'])
14     #輸出模型決策邊界
15     line = np.linspace(7, 13, 100)
16     y=(-logistic.coef_[0][0]*line-logistic.intercept_)/logistic.coef_[0][1]
17     plt.plot(line,y,'-')
18 
19 logistic(1)
20 logistic(2)
21 logistic(3)
22 plt.show()

運行結果

支持向量機就是為了改進這個問題而產生的模型,它提供的不再是一條直線來區分類型,而是畫出一條到最接近點邊界且有寬度的線條(決策邊界線),邊界最大的那條線就是模型的最優選答案。

因此,支持向量機也可以看作為邊界最大化的評估器。

 

5.2 SVC 分類模型

5.2.1 線性 SVM 分類

第四節介紹的 LinearSVC 線性支持向量機就是屬於線性分類模型,事實上它是屬於一種特殊的 SVC 模型,在編寫代碼時把 SVC 模型的 」kernel」 值設置 「linear 」 即:SVC (kernel=’linear’) ,也可得到與 LinearSVC 類似的效果。由運行結果可以觀察到,LinearSVC 可以根據測試數據生成一條決策邊界線,邊界線的緊密程度可以通過參數C調節。

 1 def linearSVC_test(c=100):
 2     # 訓練數據
 3     X,y=dataset.make_blobs(centers=2,random_state=2,n_features=2)
 4     # 使用 LinearSVC 模型,使用默認值 C=100
 5     linear=LinearSVC(C=c)
 6     linear.fit(X,y)
 7     # 畫出數據點
 8     plt.scatter(X[:,0],X[:,1],c=y,marker='^',s=50)
 9     # 建立網格數據
10     xx=np.linspace(-5,6,100)
11     yy=np.linspace(-13,3,100)
12     XX,YY=np.meshgrid(xx,yy)
13     ZZ=np.c_[XX.ravel(),YY.ravel()]
14     # 根據網絡數據推算出預測值
15     zz=linear.decision_function(ZZ)
16     # 顯示決策分界線
17     plt.contour(xx,yy,zz.reshape(XX.shape),levels=[-1,0,1],
18                 linestyles=['--','-','--'],alpha=0.7,cmap='jet')
19     plt.show()

運行結果

 

5.2.2 非線性 SVM 分類

5.2.2.1 多項式轉換器 

在處理線性分類時可以使用 LinearSVC,然而它受到了線性分類的限制,當處理非線性數據集時,LinearSVC 則無法單獨支撐,此時可以使用上一章介紹過的多項式轉換器 PolynomialFeatures 與管道 Pipe 來解決此問題。

 1 def polynomialFeatures_linearSVC_test():
 2     # 獲取數據集,通過求余方式把輸出值變為2個
 3     X,y=dataset.make_blobs(centers=4,random_state=8,n_features=2)
 4     y=y%2
 5     # 通過管道使用多項轉換器PolynomialFeatures和線性支持向量機LinearSVC
 6     pipe=make_pipeline(PolynomialFeatures(degree=2),LinearSVC(C=10))
 7     model=pipe.fit(X,y)
 8     # 建立網格數組
 9     xx=np.linspace(-9,11,100)
10     yy=np.linspace(-14,14,100)
11     XX,YY=np.meshgrid(xx,yy)
12     ZZ=np.c_[XX.ravel(),YY.ravel()]
13     # 計算網絡中的輸出值
14     zz=model.decision_function(ZZ)
15     # 顯示分類決策邊界線
16     plt.contourf(xx,yy,zz.reshape(XX.shape),alpha=0.7)
17     # 顯示測試數據點
18     plt.scatter(X[:,0],X[:,1],c=y,s=50,marker='^')
19     plt.show()

運行結果

上面例子的運行結果可以看出,通過多項式轉換器可以有效地利用 LinearSVC 解決非線性數據的問題。

 

5.2.2.2 核技巧的定義

通過某種非線性映射將原始數據嵌入到合適的高維特徵空間,利用通用的線性學習器在這個新的空間中分析和處理的模式被稱為核函數技巧。
常用的核函數有:

遺憾的是常用的 LinearSVC 模型並不支持核函數,為此 sklearn 特意開發了支持核函數的 SVC 模型。

 

5.2.2.3 SVC 模型

上面用到的 LinearSVC 模型是基於 liblinear 庫實現的 SVM 算法,它並不支持核技巧,因此它所訓練的數據基本都是線性數據,處理數據的速度較快,運行時間為O (m*n) ,適合處理量大的數據集。當遇到非線性數據時,也可使用多項式轉換器來處理。
下面說到的 SVC 模型則是基於 libsvm 庫實現的,它本身就支持核技巧,使用時只需要通過 kernel 參數進行設置。但不幸的是它的處理速度比較慢,運行時間O(m3*n)從指數級上升,因此只適合處理中小型的數據集。
下表就統計了 LinearSVC 與 SVC 兩個模型的區別,時間O公式中的 m 和 n 分別表示未知數的行數和列數。

模型 時間 核技巧 需要縮放
LinearSVC O(m*n) 不支持
SVC O(m2*n)到O(m3*n) 支持

SVC 構造函數

1 class SVC(BaseSVC):
2     @_deprecate_positional_args
3     def __init__(self, *, C=1.0, kernel='rbf', degree=3, gamma='scale',
4                  coef0=0.0, shrinking=True, probability=False,
5                  tol=1e-3, cache_size=200, class_weight=None,
6                  verbose=False, max_iter=-1, decision_function_shape='ovr',
7                  break_ties=False,
8                  random_state=None):
9     ......

參數說明:

  • C: float參數 默認值為1.0,錯誤項的懲罰係數。C越大,即對分錯樣本的懲罰程度越大,因此在訓練樣本中準確率越高,但是泛化能力降低,也就是對測試數據的分類準確率降低。相反,減小C的話,容許訓練樣本中有一些誤分類錯誤樣本,泛化能力強。對於訓練樣本帶有噪聲的情況,一般採用後者,把訓練樣本集中錯誤分類的樣本作為噪聲。
  • kernel: str參數 默認為『rbf』,算法中採用的核函數類型,可選參數有:『linear』:線性核函數、『poly』:多項式核函數、『rbf』:徑像核函數/高斯核、『sigmod』:sigmod核函數、『precomputed』:核矩陣,precomputed表示自己提前計算好核函數矩陣,這時候算法內部就不再用核函數去計算核矩陣,而是直接用你給的核矩陣。除了上面限定的核函數外,還可以給出自己定義的核函數。
  • degree: int型參數 默認為3,這個參數只對 poly 多項式核函數有用,是指多項式核函數的階數 n,如果給的核函數參數是其他核函數,則會自動忽略該參數。
  • gamma: 可選 scale、auto 或 float參數, 默認為 scale,可調節決策邊界的影響範圍。值越大決策邊界越窄,每個實例影響範圍越小。反之值越小,決策邊界越大,影響範圍越廣。只對 kernel為:『rbf』,『poly』,『sigmod』有效,當使用線性核函數 linear 時無效。如果gamma為auto,代表其值為樣本特徵數的倒數,即1/n_features。
  • coef0: float參數 默認為0.0,核函數中的獨立項,控制模型受高階多項式的影響程度,只有對 kernel為 『poly』和『sigmod』 核函數有用
  • probability:bool參數 默認為False,是否啟用概率估計。這必須在調用fit()之前啟用,並且會fit()方法速度變慢。
  • shrinking:bool參數 默認為True,是否採用啟發式收縮方式
  • tol: float參數 默認為1e^-3,svm停止訓練的誤差精度
  • cache_size:float參數 默認為200,指定訓練所需要的內存,以MB為單位,默認為200MB。
  • class_weight:字典類型或者『balance』字符串。默認為None,給每個類別分別設置不同的懲罰參數C,如果沒有給,則會給所有類別都給C=1,即前面參數指出的參數C.如果給定參數『balance』,則使用y的值自動調整與輸入數據中的類頻率成反比的權重。
  • verbose :bool參數 默認為False,是否啟用詳細輸出。此設置利用libsvm中的每個進程運行時設置,如果啟用,可能無法在多線程上下文中正常工作。一般情況都設為False,不用管它。
  • max_iter :int參數 默認為-1,最大迭代次數,如果為-1,表示不限制
  • decision_function_shape: 可選 ‘ovo’ 或 ‘ovr’,默認值為 『ovr’。多分類時需要進行選擇的兩種不同策略。ovo:one versus one,一對一,即一對一的分類器,這時對K個類別需要構建K * (K – 1) / 2個分類器; ovr:one versus rest,一對其他,這時對K個類別只需要構建K個分類器。
  • break_ties:默認值為False。如果選擇 True 當decision_function_shape 為』ovr’ ,且測試數據類型大於2,系統將根據 decision_function 的值計算 predict 的類型輸出值。
  • random_state:int 型參數 默認為None,偽隨機數發生器的種子,在混洗數據時用於概率估計。

常用屬性:

  • svc.support_vectors_:位於邊界上的點,稱為支持向量,SVM 支持向量機也是由此得名
  • svc.n_support_:獲取不同類型的支持向量的數據
  • svc.support_:支持向量在訓練樣本中的索引
  • dual_coef_ : 決策函數中支持向量的係數,分類器為 『ovo』 一對一的係數
  • coef_ : 返回每個特徵的權重,僅在使用 linear 線性核函數時有效

(1)線性( Linear)核函數

使用 SVC 模型時,可以通過設置 kernel 參數得到不同的核函數,當使用 linear 核函數時,其結果與直接使用 LinearSVC 相仿,也是無法對非線性數據集進行精準的訓練。不同的是使用 SVC 可以通過 support_vectors_ 參數獲取支持向量,能夠更準備地預知決策邊界。

 1 def svc_test(c=0.01):
 2     #測試數據集
 3     X, y = dataset.make_blobs(centers=2, random_state=2, n_features=2)
 4     #生成SVC模型,使用Linear核函數,把C設置為0.01
 5     svc = SVC(C=c,kernel='linear')
 6     svc.fit(X, y)
 7     #生成矩形網絡數據
 8     xx = np.linspace(-5, 7, 1000)
 9     yy = np.linspace(-14, 4, 1000)
10     XX, YY = np.meshgrid(xx, yy)
11     ZZ = np.c_[XX.ravel(), YY.ravel()]
12     #計算分隔平面距離
13     zz = svc.decision_function(ZZ)
14     #划出分隔線
15     plt.contour(xx, yy, zz.reshape(XX.shape), levels=[-1,0,1],linestyles=['--','-','--'])
16     #划出數據點
17     plt.scatter(X[:, 0], X[:, 1], c=y,marker='^',s=80)
18     #划出支持向量
19     sv=svc.support_vectors_
20     plt.scatter(sv[:,0],sv[:,1],marker='.',color='red',s=300)
21     #坐標標識
22     plt.legend(['data point','supper vector'])
23     plt.xlabel('feature0')
24     plt.ylabel('feature1')
25     plt.show()

運行結果

通過調節 C 參數,可以調節懲罰程度。
上面代碼當 C 為默認值 0.01時,support_vectors_ 就有14個。C 值越小,能容納的訓練樣本中誤分類錯誤樣本越多,泛化能力強,這被稱為邊界軟化
C 越大對分錯樣本的懲罰程度越大,因此在訓練樣本中準確率越高,但是泛化能力降低,也就是對測試數據的分類準確率會降低,這被稱之為邊界硬化
下面試着把 C 設置為100 時,support_vectors_ 則只有2個,由此可知 C 對調節懲罰程度的作用。

 

(2)多項式 Poly 核函數

當把 kernel 參數設置為 poly 時,可無需通過多項式轉換器 PolynomialFeatures 就可得到類似的效果。
使用 poly 核函數時有兩個重要參數,degree 用於控制多項式的階數,coef0 可控制高階多項式與低階多項式對模型的影響。
把 degree 設置為2,coef0 設置為0.1 時,支持向量點 support_vectors_有66個之多,可見模型欠擬合。

 1 def svc_test():
 2     #測試數據集
 3     X, y = dataset.make_blobs(centers=8, random_state=18, n_features=2)
 4     y=y%2
 5     #生成SVC模型,使用poly核函數,把C設置為2,degree
 6     svc = SVC(C=2,kernel='poly',degree=2,coef0=0.1)
 7     svc.fit(X, y)
 8     #生成矩形網絡數據
 9     xx = np.linspace(-10, 11, 1000)
10     yy = np.linspace(-14, 14, 1000)
11     XX, YY = np.meshgrid(xx, yy)
12     ZZ = np.c_[XX.ravel(), YY.ravel()]
13     #計算分隔平面距離
14     zz = svc.decision_function(ZZ)
15     #划出分隔線
16     plt.contourf(xx, yy, zz.reshape(XX.shape),)
17     #划出數據點
18     plt.scatter(X[:, 0], X[:, 1], c=y,marker='^',s=80)
19     #划出支持向量
20     sv=svc.support_vectors_
21     plt.scatter(sv[:,0],sv[:,1],marker='.',color='red',s=150)
22     #標籤
23     plt.xlabel('feature0')
24     plt.ylabel('feature1')
25     print('support_vectors_ shape:{0}'.format(sv.shape))
26     plt.show()

運行結果

把degree設置為3,coef0設置為10後,運行結果如下,此支持向量點只剩11個,且模型的邊界更明確,擬合度有所提升。

 

(3)高斯 RBF 核函數

使用高斯RBF核函數時,可把 kerenl 設置為 rbf,此時通過調節 gamma 參數可調節決策邊界。值越大決策邊界越窄,每個實例影響範圍越小。反之值越小,決策邊界越大,影響範圍越廣。下面的例子使用環形數據集,把 gamma 設置為10。

 1 def svc_test():
 2     #測試數據集
 3     X, y = dataset.make_circles(random_state=2,noise=0.1,factor=0.1)
 4     #生成SVC模型,使用RBF核函數
 5     svc = SVC(C=2,kernel='rbf',gamma=10)
 6     svc.fit(X, y)
 7     #生成矩形網絡數據
 8     xx = np.linspace(-1.5, 1.5, 1000)
 9     yy = np.linspace(-1.5, 1.5, 1000)
10     XX, YY = np.meshgrid(xx, yy)
11     ZZ = np.c_[XX.ravel(), YY.ravel()]
12     #計算分隔平面距離
13     zz = svc.decision_function(ZZ)
14     #划出分隔線
15     plt.contourf(xx, yy, zz.reshape(XX.shape),alpha=0.8)
16     #划出數據點
17     plt.scatter(X[:, 0], X[:, 1], c=y,marker='^',s=50)
18     #划出支持向量
19     sv=svc.support_vectors_
20     plt.scatter(sv[:,0],sv[:,1],marker='.',color='red',s=150)
21     #標籤
22     plt.xlabel('feature0')
23     plt.ylabel('feature1')
24     print('support_vectors_ shape:{0}'.format(sv.shape))
25     plt.show()

運行結果

嘗試把 把 gamma 設置改 0.5,測試結果如下,很明顯其決策邊界加寬了,支持向量點也減小到18個。

 

 注意:gamma 配置只有在 kernel 為:『rbf』,『poly』,『sigmod』 時有效,當使用線性核函數 linear 時則無效。

當使用支持向量機時,如果數據量不大時,建議使用高斯RBF核函數,大部分情況下其準確率較高。當數據量較大時,可使用 LinearSVC ,其效率較高。

 

5.3 SVR 回歸模型

SVM 除了支持 SVC 分類外,還支持 SVR 回歸模型。使用方法與 SVC 模型類似,可以通過 kernel 參數選擇核函數,使用 poly 核函數時可通過 degree 設置階數。使用 『rbf』,『poly』,『sigmod』 等核函數時,可能通過 gamma 設置決策邊界的影響範圍。

構造函數

1 class SVR(RegressorMixin, BaseLibSVM):
2     @_deprecate_positional_args
3     def __init__(self, *, kernel='rbf', degree=3, gamma='scale',
4                  coef0=0.0, tol=1e-3, C=1.0, epsilon=0.1, shrinking=True,
5                  cache_size=200, verbose=False, max_iter=-1):
6     ......
  • C: float參數 默認值為1.0,錯誤項的懲罰係數。C越大,即對分錯樣本的懲罰程度越大,因此在訓練樣本中準確率越高,但是泛化能力降低,也就是對測試數據的分類準確率降低。相反,減小C的話,容許訓練樣本中有一些誤分類錯誤樣本,泛化能力強。對於訓練樣本帶有噪聲的情況,一般採用後者,把訓練樣本集中錯誤分類的樣本作為噪聲。
  • kernel: str參數 默認為『rbf』,算法中採用的核函數類型,可選參數有:『linear』:線性核函數、『poly』:多項式核函數、『rbf』:徑像核函數/高斯核、『sigmod』:sigmod核函數、『precomputed』:核矩陣,precomputed表示自己提前計算好核函數矩陣,這時候算法內部就不再用核函數去計算核矩陣,而是直接用你給的核矩陣。除了上面限定的核函數外,還可以給出自己定義的核函數。
  • degree: int型參數 默認為3,這個參數只對 poly 多項式核函數有用,是指多項式核函數的階數 n,如果給的核函數參數是其他核函數,則會自動忽略該參數。
  • gamma: 可選 scale、auto 或 float參數, 默認為 scale,可調節決策邊界的影響範圍。值越大決策邊界越窄,每個實例影響範圍越小。反之值越小,決策邊界越大,影響範圍越廣。只對 kernel為:『rbf』,『poly』,『sigmod』有效,當使用線性核函數 linear 時無效。如果gamma為auto,代表其值為樣本特徵數的倒數,即1/n_features。
  • coef0: float參數 默認為0.0,核函數中的獨立項,控制模型受高階多項式的影響程度,只有對 kernel為 『poly』和『sigmod』 核函數有用
  • shrinking:bool參數 默認為True,是否採用啟發式收縮方式
  • tol: float參數 默認為1e^-3,svm停止訓練的誤差精度
  • cache_size:float參數 默認為200,指定訓練所需要的內存,以MB為單位,默認為200MB。
  • verbose :bool參數 默認為False,是否啟用詳細輸出。此設置利用libsvm中的每個進程運行時設置,如果啟用,可能無法在多線程上下文中正常工作。一般情況都設為False,不用管它。
  • max_iter :int參數 默認為-1,最大迭代次數,如果為-1,表示不限制

下面例子嘗試使用多項式核函數 poly 對測試集進行計算,因為數據量較少,為了提高準確率,把 C 懲罰程度調高到 2,把階數 degree 設置為 2,此時測試數據的準確率已接近 99%,線條更接近於一條直線。

 1 def svr_test():
2 # 測試數據 3 X, y = dataset.make_regression(n_samples=100,noise=10,n_features=1,random_state=8) 4 X_train, X_test, y_train, y_test = train_test_split(X, y) 5 # SVR 模型,使用 poly 核函數,degree為2級 6 svr = SVR(kernel='poly',C=2,degree=2,coef0=2) 7 svr.fit(X_train, y_train) 8 # 準確率 9 print('SVR:\n train data:{0}\n test data:{1}' 10 .format(svr.score(X_train, y_train), svr.score(X_test, y_test))) 11 # 生成線狀圖 12 line=np.linspace(-3,3,100) 13 result=svr.predict(line.reshape(-1,1)) 14 plt.plot(line.reshape(-1,1),result) 15 plt.plot(X,y,'^') 16 plt.show()

運行結果

若改為使高斯核函數RBF,當懲罰係數依然為 C=2 時,準確率將會大幅下降,這是由於可訓練的數據量太少,前後數據的誤差所造成的。若遇到這種情況,有兩種不同的解決方案,一是提高測試集的數據量,讓模型得到充分的訓練,二是加大懲罰係數。

這裡還是使用高斯核函數RBF,但嘗試把懲罰係數修改為 C=100,運行則得到以下的結果,可見準確率有明顯的提升,而且相對 poly 核函數,線條扭曲程度會更高。

回到目錄

六、K 近鄰

K 近鄰(KNN,K-NearestNeighbor)是比較簡單的一種算法,它包含 KNN 分類與回歸算法。所謂 K 近鄰,就是K個最近的鄰居的意思,說的是每個樣本都可以用它最接近的K個鄰近值來做代表進行計算。

6.1 KNeighborsClassifier 分類

KNeighborsClassifier 近鄰分類算法就是將數據集中的每一個記錄進行分類的方法。最簡單的思路就是通過 n_neighbors 參數(默認值為5)控制近鄰的個數,把 n 個近鄰看到為同一類型。模型使用的近鄰點(n_neightbors)越大模型複雜程度越低,相反近鄰點數量越少模型的複雜程度低高。

構造函數

1 class KNeighborsClassifier(KNeighborsMixin,
2                            ClassifierMixin,
3                            NeighborsBase):
4     @_deprecate_positional_args
5     def __init__(self, n_neighbors=5, *,
6                  weights='uniform', algorithm='auto', leaf_size=30,
7                  p=2, metric='minkowski', metric_params=None, n_jobs=None,
8                  **kwargs):
9     ......
  • n_neighbors: int, 默認為 5 表示默認鄰居的數量
  • weights(權重): str 類型, 默認為 『uniform』,用於預測的權重函數。可選參數如下: 『uniform』 : 統一的權重. 在每一個鄰居區域里的點的權重都是一樣的。 『distance』 : 權重點等於他們距離的倒數。使用此函數,更近的鄰居對於所預測的點的影響更大。『callable』 : 一個用戶自定義的方法,此方法接收一個距離的數組,然後返回一個相同形狀並且包含權重的數組。
  • algorithm(算法): str 類型,默認值為 auto ,可選值 {『auto』, 『ball_tree』, 『kd_tree』, 『brute』},代表計算最近鄰居用的算法。’ball_tree’:使用BallTree維數大於20時建議使用。kd_tree’:原理是數據結構的二叉樹,以中值為劃分,每個節點是一個超矩形,在維數小於20是效率高。’brute’:暴力算法,線性掃描。’auto’:自動選取最合適的算法。
  • leaf_size(葉子數量): int, 默認為 30,代表使用 BallTree 或者 KDTree 算法時的葉子數量。此參數會影響構建、查詢BallTree或者KDTree的速度,以及存儲BallTree或者KDTree所需要的內存大小。
  • p: int,默認為 2,可選值為[1,2]。p=1表示用於使用曼哈頓距離進行度量。p = 2表示使用閔可夫斯基距離。
    進行度量
  • metric(矩陣): string or callable, 默認為 『minkowski』,用於樹的距離矩陣。
  • metric_params(矩陣參數): dict, 可選參數(默認為 None),代表給矩陣方法使用的其他的關鍵詞參數。
  • n_jobs: int, 默認為 1,可並行運行的任務數量。如果為-1, 任務數量設置為CPU核的數量。

knn 適用於集中的同類型數據,測試可見只有臨近的幾個數據點可能出現錯誤判斷的數據點。

 1 def knn_classifier_test():
 2     # 2類的測試數據100個
 3     X,y= dataset.make_blobs(n_samples=100,n_features=2,
 4                             centers=2,random_state=30)
 5     X_train,X_test,y_train,y_test=train_test_split(X,y)
 6     # 用k近鄰算法進行分類
 7     knn_classifier=KNeighborsClassifier(n_neighbors=3)
 8     knn_classifier.fit(X_train,y_train)
 9     knn_classifier.predict(X_test)
10     # 打印測試數據正確率
11     print('KNN Claassifier\n   test data:{0}'
12           .format(knn_classifier.score(X_test,y_test)))
13     # 划出分類圖形
14     plt.scatter(X[:,0],X[:,1],c=y,marker='^')
15     plt.title('neighbors 3')
16     plt.xlabel('feature0')
17     plt.ylabel('feature1')
18     plt.show()

運行結果

 嘗試把近鄰點的數量參數調高,測試數據的正確很容易就會上升到100%。

 

6.2 KNeighborsRegressor 回歸

KNeighborsRegressor 的用法基本與 KNeighborsClassifier 類似,主要也是通過 n_neighbors 來控制近鄰數量

構造函數

1 class KNeighborsRegressor(KNeighborsMixin,
2                           RegressorMixin,
3                           NeighborsBase):
4     @_deprecate_positional_args
5     def __init__(self, n_neighbors=5, *, weights='uniform',
6                  algorithm='auto', leaf_size=30,
7                  p=2, metric='minkowski', metric_params=None, n_jobs=None,
8                  **kwargs):
9     ......
  • n_neighbors: int, 默認為 5 表示默認鄰居的數量
  • weights(權重): str 類型, 默認為 『uniform』,用於預測的權重函數。可選參數如下: 『uniform』 : 統一的權重. 在每一個鄰居區域里的點的權重都是一樣的。 『distance』 : 權重點等於他們距離的倒數。使用此函數,更近的鄰居對於所預測的點的影響更大。『callable』 : 一個用戶自定義的方法,此方法接收一個距離的數組,然後返回一個相同形狀並且包含權重的數組。
  • algorithm(算法): str 類型,默認值為 auto ,可選值 {『auto』, 『ball_tree』, 『kd_tree』, 『brute』},代表計算最近鄰居用的算法。’ball_tree’:使用BallTree維數大於20時建議使用。kd_tree’:原理是數據結構的二叉樹,以中值為劃分,每個節點是一個超矩形,在維數小於20是效率高。’brute’:暴力算法,線性掃描。’auto’:自動選取最合適的算法。
  • leaf_size(葉子數量): int, 默認為 30,代表使用 BallTree 或者 KDTree 算法時的葉子數量。此參數會影響構建、查詢BallTree或者KDTree的速度,以及存儲BallTree或者KDTree所需要的內存大小。
  • p: int,默認為 2,可選值為[1,2]。p=1表示用於使用曼哈頓距離進行度量。p = 2表示使用閔可夫斯基距離。
    進行度量
  • metric(矩陣): string or callable, 默認為 『minkowski』,用於樹的距離矩陣。
  • metric_params(矩陣參數): dict, 可選參數(默認為 None),代表給矩陣方法使用的其他的關鍵詞參數。
  • n_jobs: int, 默認為 1,可並行運行的任務數量。如果為-1, 任務數量設置為CPU核的數量。

下面以簡單的單特徵數據集測試,把 n_neighbors 設置為1時,訓練數據的正確率為100%,而測試數據的正確率只有71%左右,可見數據的擬合度過高,線條基本上會經過所有的數據點。

 1 def knn_regressor_test():
 2     #測試數據集
 3     X,y=dataset.make_regression(n_features=1,noise=25,random_state=2)
 4     X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)
 5     #訓練KNeighborsRegressor模型
 6     knn_regressor=KNeighborsRegressor(n_neighbors=1)
 7     knn_regressor.fit(X_train,y_train)
 8     #輸出訓練數據集、測試數據集的正確率
 9     print('KNN_Regressor:\n     train data:{0}\n     test data:{1}'
10           .format(knn_regressor.score(X_train,y_train),
11                   knn_regressor.score(X_test,y_test)))
12     #畫出數據點與數據線
13     line=np.linspace(-3,3,1000).reshape(-1,1)
14     plt.plot(line,knn_regressor.predict(line))
15     plt.plot(X,y,'v')
16     plt.legend(['model predict','train data'])
17     plt.show()

運行結果

 

 把 n_neighbors 設置為 3 時,可見線條會更加平滑,數據的擬合度有所降低。

k 近鄰是一種很好理解的模型,它比較適用於特徵量較少的集合型數據,當特徵數上到幾個百個甚至更多時,k 近鄰的準確率就是急劇下降。使用時主要是控制好 n_neighbors 的數量,一般為 3 到 5 個比較合理。

 回到目錄

七、樸素貝葉斯分類器

樸素貝葉斯模型是一個簡單快速的分類算法,適用於維度較高的的數據集,因為它可調的參數少,運行速度快,所以多用於初步的數據分類。它基於 「 貝葉斯定理 」 而得名,是關於隨機事件 A 和 B 的條件概率的數學定理。其中 P(A|B)是在 B 發生的情況下 A 發生的可能性。這個數學定理十分有趣,並且跟生活有着密切的關聯,有興趣的朋友可以百度科普一下,在此不作詳述。

在 sklearn 中常用的樸素貝葉斯分類器有高斯樸素貝葉斯分類器(Gaussian naive Bayes)、多項式樸素貝葉斯分類器(Multinomial naive Bayes)和 伯努利貝葉斯分類器 (Bernoulli naive Bayes)。

7.1 GaussianNB 分類器

高斯樸素貝葉斯分類是最常用一種樸素貝葉斯分類器,它可以應用於任意連續的數據,而且會保存每個類別中每個特徵的平均值與標準差值。而且可以通過快節的方法 predict_proba() 找到測試數據所屬類型的概率。其構造函數簡單易用,只有兩個參數。

構造函數

1 class GaussianNB(_BaseNB):
2     @_deprecate_positional_args
3     def __init__(self, *, priors=None, var_smoothing=1e-9):
4     ....
  • prior:表示類的先驗概率。如果指定,則不根據數據調整先驗,如果不指定,則自行根據數據計算先驗概率P(Y)。
  • var_smoothing:float 類型,默認值為: 1e-9,在估計方差時,為了追求估計的穩定性,將所有特徵的方差中最⼤大的方差以某個比例添加到估計的方差中。

假設測試數據集服從高斯分佈,且變量無方差關係,則只要找到每個標籤樣本點的均值和標準差,就可以通過高斯分佈找到擬合的模型。從高斯模型的分界可以看出,它是一個二次方的曲線形成的。因為GaussianNB 模型的運算速度較快,測試的數據量較大,所以模型特意準備了一個 partial_fit() 方法,可以分批處理訓練數據。

 1 def gaussianNB():
 2    X, y = dataset.make_blobs(centers=4, random_state=2, n_features=2)
 3    X_train,X_test,y_train,y_test=train_test_split(X,y)
 4    #訓練數據
 5    gaussina=GaussianNB()
 6    model=gaussina.fit(X_train,y_train)
 7    #輸出準確率
 8    print('GaussianNB\n    train data:{0}\n    test data:{1}'
 9          .format((gaussina.score(X_train,y_train)),
10                   gaussina.score(X_test,y_test)))
11    #畫出數據點
12    plt.scatter(X[:,0],X[:,1],c=y,s=100,marker='^')
13    #畫出分界
14    xx=np.linspace(-8,4,100)
15    yy=np.linspace(-12,5,100)
16    XX,YY=np.meshgrid(xx,yy)
17    ZZ=np.c_[XX.ravel(),YY.ravel()]
18    zz=gaussina.predict(ZZ)
19    plt.contourf(xx,yy,zz.reshape(XX.shape),alpha=0.4)
20    #畫出坐標
21    plt.xlabel('feature0')
22    plt.ylabel('feature1')
23    #輸出數據所屬類型的概率
24    print('\ndata probability:\n{0}'.format(gaussina.predict_proba(X[1:3].reshape(-1,1))))
25    plt.show()

運行結果

 

 

7.2 MultinomialNB 分類器

高斯樸素貝葉斯分類器適用於連續型的數據分類,而 MultinomialNB 多項式樸素貝葉斯分類器更適用於分佈型的數據分類,例如在玩篩子的時候,1,2,3,4,5,6 出現的機率均為1/6,其出現的情況互不干擾也沒有相關性,它的特點在於所涉及的特徵往往是次數,頻率,計算等,不會有負值。因此,MultinomialNB 分類往往用於文本數據的分析。與 GaussianNB 類似,MultinomialNB 也可以通過快節的方法 predict_proba() 找到測試數據所屬類型的概率。通過 partial_fit() 方法對數據量大的數據進行分批處理。

構造函數

1 class MultinomialNB(_BaseDiscreteNB):
2     @_deprecate_positional_args
3     def __init__(self, *, alpha=1.0, fit_prior=True, class_prior=None):
4     ......
  • alpha: float 類型,默認為1.0,表示平滑值
  • fit_prior: bool類型,默認為True。如果為True,則不去學習類別先驗概率,以均勻分佈替代;如果為False,則去學習
  • class_prior: 數組類型,默認為空。它指定了每個分類的先驗概率,如果指定了該參數,則每個分類的先驗概率不再從數據集中學得

常用參數

  • class_log_prior_: 一個數組對象,形狀為(n_classes,)。給出了每個類別調整後的經驗概率分佈的對數值
  • feature_log_prob_: 一個數組對象,形狀為(n_classes, n_features)。給出了P(wi|c)的經驗概率分佈的對數值
  • class_count_: 一個數組,形狀為(n_classes,),是每個類別包含的訓練樣本數量
  • feature_count_: 一個數組,形狀為(n_classes, n_features)。訓練過程中,每個類別每個特徵遇到的樣本數
  • coef_ :將多項式模型解釋為線性模型後的係數序列w1,w2,…,wn,每個類別的詞語多項式權值向量,shpae=[類別數量,詞彙表長度]
  • intercept_:將多項式模型解釋為線性模型後的截距值b,每個類別的先驗概率,shape=[類別數量]

下面就是文本分析為案例,首先從 fetch_20newsgroups 測試集中獲取6類的文件做測試,通過管道 pipe 把數據先通過 TF-IDF 做文本分析,再使用 MultinomialNB 進行分類,最後用混淆矩陣把各類數據的數據顯示出來。可見,數據的準確率達到 88.8% 左右。

 1 def multinomialNB_test():
 2    #獲取6類文章做測試
 3    categories=['rec.autos','soc.religion.christian','talk.politics.guns'
 4       ,'sci.electronics','sci.med','sci.crypt']
 5    #獲取訓練數據和測試數據
 6    train=fetch_20newsgroups(subset='train',categories=categories)
 7    test=fetch_20newsgroups(subset='test',categories=categories)
 8    #通過pipe管道用TF_IDF文本統計器和MultinomialNB進行訓練
 9    pipe=make_pipeline(TfidfVectorizer(),MultinomialNB())
10    pipe.fit(train.data,train.target)
11    y_model=pipe.predict(test.data)
12    #輸入準確率
13    print('MultinomialNB\n  test data:{0}'
14          .format(pipe.score(test.data,test.target)))
15    #混淆矩陣
16    matrix=confusion_matrix(test.target,y_model)
17    heatmap(matrix,square=True,annot=True,cbar=False,fmt='d',linewidths=2
18            ,xticklabels=test.target_names,yticklabels=test.target_names)
19    plt.show()

運行結果

至於 BernoulliNB 伯努利貝葉斯分類器的使用方法與 MultinomialNB 十分類似,只不過BernoulliNB 更多用於二元離散值或者稀疏的多元離散值分類,在此就不作詳細描述。

回到目錄

八、決策樹與決策樹集成

8.1 決策樹

決策樹是廣泛應用於分類與回歸的模型,從本質上說它類似於 if / else 的語句,從是與否中對數據進行分析。打個比方,在現實生活中我們對交通工具的劃分,有輪子的是車,沒輪子的船,有輪子帶油箱的是機動車,有輪子不油箱的是電動車,沒輪子帶電機的游輪,沒輪子不帶電機的竹筏。這樣子,我們就把交通工具分成三層關係(如下圖),交通工具需要根結點,車跟船屬於內結點,電動車、機動車、游輪、竹筏屬於葉結點。

 

8.1.1 DecisionTreeClassifier 分類決策樹 

分類決策樹 DecisionTreeClassifier 就是通過二分類的方式對數據進行逐步分割,這表示決策樹的每個節點都是根據一個特徵的閾值將數據分成兩組進行分割的。如果結點進行無限的分枝,必然會引起性能的虛耗,導致數據過分擬合。為避免此類問題,決策樹提供了預剪枝的功能,可以通過 max_depth 參數控制樹的最大深度。通過 min_samples_split 控制結點的最小樣本數量,當樣本數量可能小於此值時,節點將不會在劃分。通過 min_samples_leaf 限制了葉子節點最少的樣本數,如果葉子節點數目小於最小樣本數,就會和兄弟節點一起被剪枝。特別是在數據量比較大的時候,通過設置幾個參數,將有效提高系統的性能。

構造函數

 1 class DecisionTreeClassifier(ClassifierMixin, BaseDecisionTree):
 2     @_deprecate_positional_args
 3     def __init__(self, *,
 4                  criterion="gini",
 5                  splitter="best",
 6                  max_depth=None,
 7                  min_samples_split=2,
 8                  min_samples_leaf=1,
 9                  min_weight_fraction_leaf=0.,
10                  max_features=None,
11                  random_state=None,
12                  max_leaf_nodes=None,
13                  min_impurity_decrease=0.,
14                  min_impurity_split=None,
15                  class_weight=None,
16                  ccp_alpha=0.0):
17      ......
  • criterion:str類型,默認值為 『gini’。表示特徵選擇標準,可選 gini 或者 entropy ,前者是基尼係數,後者是信息熵。
  • splitter:str 類型,默認值為 』best’ 。表示特徵劃分標準,可選擇 best 或 random,」best」是在所有特徵中找最好的切分點,適合樣本量不大的時候。而random 在部分特徵中選擇分割點,適用於樣本數據量較大時使用。
  • max_depth: int 類型,默認值 為 None。 設置決策隨機森林中的決策樹的最大深度,深度越大,越容易過擬合,推薦樹的深度為:5-20之間。
  • min_samples_split:int 類型,默認值為2。設置結點的最小樣本數量,當樣本數量可能小於此值時,節點將不會在劃分。
  • min_samples_leaf:int 類型,默認值為1。 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。
  • min_weight_fraction_leaf: int 類型,默認值為 0。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝默認是0,就是不考慮權重問題。
  • max_features:類型 int, float or {“auto”, “sqrt”, “log2”}, 默認值為 None,表示限制的最大特徵數。{“auto”, “sqrt”, “log2”} 一般在特徵小於50的時候使用
  • random_state:隨機數種子,推薦設置一個任意整數,同一個隨機值,模型可以復現。
  • max_leaf_nodes: int 類型,默認是”None」。表示限制最大葉子的節點數,可以防止過擬合。當設置為None時,即不限制最大的葉子節點數。
  • min_impurity_decrease:float 類型,默認值為0.0。表示節點劃分最小不純度, 這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。 
  • min_impurity_split: float 類型,默認值為0.0。功能可用 min_impurity_decrease 參數代替,新版不推薦使用,這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值則該節點不再生成子節點。即為葉子節點 。
  • class_weight:dict 或 list 類型,默認值為 None , 可選 “balanced” 。指定樣本各類別的的權重,主要是為了防止訓練集某些類別的樣本過多導致訓練的決策樹過於偏向這些類別。這裡可以自己指定各個樣本的權重,如果使用「balanced」,則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。
  • ccp_alpha:float 類型,默認值為 0.0 。表示使用 CCP 算法的誤差率增益率α閾值,小於該值的誤差率增益率對應的節點都會被剪枝。

下面以一個4類的數據集作為例子,看一下決策樹是如果通過二分類的方式對數據進行逐步分割的。從運行結果可以看到每一層分類時數據的劃分情況,深度越大,數據的分類就越仔細,這裡把最大深度設置為5,然後進行剪枝。

 1 def decisionTreeClassifier_test():
 2     #測試集,用四類數據
 3     X,y=make_blobs(n_samples=200,centers=4,random_state=0,n_features=2)
 4     X_train,X_test,y_train,y_test=train_test_split(X,y)
 5     #生成決策樹模型進行訓練
 6     decisiontree=DecisionTreeClassifier(max_depth=5)
 7     decisiontree.fit(X_train,y_train)
 8     #顯示準確率
 9     print('DecisionTreeClassifier:\n  train data:{0}\n  test data:{1}'
10         .format(decisiontree.score(X_train,y_train),
11                 decisiontree.score(X_test,y_test)))
12     #打印數據分佈圖
13     xx=np.linspace(-5,5,200)
14     yy=np.linspace(-2,11,200)
15     XX,YY=np.meshgrid(xx,yy)
16     ZZ=np.c_[XX.ravel(),YY.ravel()]
17     zz=decisiontree.predict(ZZ).reshape(XX.shape)
18     plt.contourf(xx,yy,zz,alpha=0.4,zorder=2)
19     #畫出數據點
20     plt.scatter(X[:,0],X[:,1],c=y,marker='^',s=50)
21     plt.show()

運行結果

 

除此以外,還可以使用 tree.export_graphviz() 保存決策樹和重要信息。使用 DecisionTreeClassifier.feature_importances_ 屬性查看決策樹每個特徵的重要性佔比,每個特徵的重要性比率加起來必然是等於1 。注意,即使特徵的重要性為0,並不說明此特徵沒有提供任何信息,只是表示此次運行中該特徵並末被此決策樹選中,每次運行同樣的數據集,特徵的佔比均不相同。

 1 def decisionTreeClassifier_test():
 2     #測試集,用四類數據
 3     X,y=make_blobs(n_samples=500,centers=10,random_state=1,n_features=10)
 4     X_train,X_test,y_train,y_test=train_test_split(X,y)
 5     #生成決策樹模型進行訓練
 6     decisiontree=DecisionTreeClassifier(max_depth=8)
 7     decisiontree.fit(X_train,y_train)
 8     #顯示準確率
 9     print('DecisionTreeClassifier:\n  train data:{0}\n  test data:{1}'
10         .format(decisiontree.score(X_train,y_train),
11                 decisiontree.score(X_test,y_test)))
12     #輸出 feature 特性重要性比率
13     print('  feature_importance:\n{0}'.format(decisiontree.feature_importances_))
14     #保存決策樹重要信息
15     export_graphviz(decisiontree,out_file='data2.dot')

運行結果

 

8.1.2 DecisionTreeRegressor  回歸決策樹 

回歸決策樹的原理與分類決策樹的原理基本一致,但是有一點必須注意的是,他的測試數據不能在訓練範圍以外進行預測,一但超出訓練範圍,測試值就是一定被認定為最後的一個值。

構造函數

 1 class DecisionTreeRegressor(RegressorMixin, BaseDecisionTree):
 2     @_deprecate_positional_args
 3     def __init__(self, *,
 4                  criterion="mse",
 5                  splitter="best",
 6                  max_depth=None,
 7                  min_samples_split=2,
 8                  min_samples_leaf=1,
 9                  min_weight_fraction_leaf=0.,
10                  max_features=None,
11                  random_state=None,
12                  max_leaf_nodes=None,
13                  min_impurity_decrease=0.,
14                  min_impurity_split=None,
15                  ccp_alpha=0.0):
16         ......
  • criterion:str類型,默認值為 『mse’。表示特徵選擇標準,可選 gini 或者 entropy ,前者是基尼係數,後者是信息熵。
  • splitter:str 類型,默認值為 』best’ 。表示特徵劃分標準,可選擇 best 或 random,」best」是在所有特徵中找最好的切分點,適合樣本量不大的時候。而random 在部分特徵中選擇分割點,適用於樣本數據量較大時使用。
  • max_depth: int 類型,默認值 為 None。 設置決策隨機森林中的決策樹的最大深度,深度越大,越容易過擬合,推薦樹的深度為:5-20之間。
  • min_samples_split:int 類型,默認值為2。設置結點的最小樣本數量,當樣本數量可能小於此值時,節點將不會在劃分。
  • min_samples_leaf:int 類型,默認值為1。 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。
  • min_weight_fraction_leaf: int 類型,默認值為0。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝默認是0,就是不考慮權重問題。
  • max_features:類型 int, float or {“auto”, “sqrt”, “log2”}, 默認值為 None,表示限制的最大特徵數。{“auto”, “sqrt”, “log2”} 一般在特徵小於50的時候使用
  • random_state:隨機數種子,推薦設置一個任意整數,同一個隨機值,模型可以復現。
  • max_leaf_nodes: int 類型,默認是”None」。表示限制最大葉子的節點數,可以防止過擬合。當設置為None時,即不限制最大的葉子節點數。
  • min_impurity_decrease:float 類型,默認值為0.0。表示節點劃分最小不純度, 這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。 
  • min_impurity_split: float 類型,默認值為0.0。功能可用 min_impurity_decrease 參數代替,新版不推薦使用,這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值則該節點不再生成子節點。即為葉子節點 。
  • class_weight:dict 或 list 類型,默認值為 None , 可選 “balanced” 。指定樣本各類別的的權重,主要是為了防止訓練集某些類別的樣本過多導致訓練的決策樹過於偏向這些類別。這裡可以自己指定各個樣本的權重,如果使用「balanced」,則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。
  • ccp_alpha:float 類型,默認值為 0.0 。表示使用 CCP 算法的誤差率增益率α閾值,小於該值的誤差率增益率對應的節點都會被剪枝。

下面的例子使用一個自定義的數據集進行訓練,輸出測試集的準確率,同時把訓練集以外的數據進行測試。從運行結果可以看出,超出訓練集以外的數據都會以最後一個值作為輸出。

 1 def decisionRegression_test():
 2     # 生成數據集
 3     X = np.linspace(-3, 3, 100)
 4     y = 2*X+1+np.random.ranf(100)
 5     X_train,X_test,y_train,y_test=train_test_split(X.reshape(-1,1),y)
 6     # 使用決策樹模型進行訓練
 7     decisiontree=DecisionTreeRegressor(max_depth=4)
 8     decisiontree.fit(X_train,y_train)
 9     # 測試數據
10     model_y=decisiontree.predict(X.reshape(-1,1))
11     print('DecisionTreeRegression:\n  train data:{0}\n  test data{1}'
12           .format(decisiontree.score(X_train,y_train),
13                   decisiontree.score(X_test,y_test)))
14     # 畫出數據點
15     plt.plot(X_train,y_train,'.')
16     plt.plot(X,model_y,'-')
17 
18     #超越訓練範圍會取最後一個點值
19     XX=np.linspace(3, 5, 20)
20     YY=decisiontree.predict(XX.reshape(-1,1))
21     plt.plot(XX,YY,'-')
22     plt.legend(['train data','predict data','out tree data'])
23     plt.show()

運行結果

 

決策樹的原理比較容易理解,在計算前不需要對特徵進行預處理,當特徵獨立性較強或多元特徵與連續特徵同時存在時,決策樹的效果會比較好。而且處理時只需要通過調節上述的幾個參數: max_depth 、 min_samples_split 、 min_samples_leaf 就可以適應多樣性的特徵。然而,它的泛化性能較差,有時候即使做了剪枝,也會出現過擬合的情況。

有見及此,sklearn 還提供了決策樹集成模型,下面就為大家介紹 2 種常用的決策樹集成模型:隨機森林與梯度提升決策樹。

 

8.2 隨機森林

隨機森林顧名思義就是把多棵決策樹集成一起同時運行,最後把個運算結果進行合併運算求平均值。類似這種通過多個擬合評估器來降低擬合程度的算法被稱作裝袋算法,它使用並行評估器對數據進行有效的數據抽取並集成 ,對本來的過擬合的數量通過求和取平均值,最後通過更好的分類效果。因此,相比起決策樹,隨機森林的準確率會更高,也是應該最廣的模型之一。
隨機森林可以通過 n_estimators 參數來設置隨機森林中決策樹的數量,通過 estimator_ 屬性可以獲取隨機森林中的每一棵決策樹。一般情況下,n_estimators 越大越好。還能然後通過 max_features 來控制每個節點的特徵數,回歸時一般 max_features 可以設置為數據集中所有的特徵數,在分類時,max_features=sqrt(n_features)。

8.2.1 RandomForestClassifier 隨機森林分類

使用 RandomForestClassifier 進行分類時,通過增加決策樹的數量(在默認設置中隨機森林往往使用100棵決策樹),可以減小數據擬合度,使數據邊界更加平滑。在設置特徵數時,max_features 直接使用默認值 auto ,則最大特徵數 max_features = sqrt(n_features)。

構造函數

 1 class RandomForestClassifier(ForestClassifier):
 2  @_deprecate_positional_args
 3     def __init__(self,
 4                  n_estimators=100, *,
 5                  criterion="gini",
 6                  max_depth=None,
 7                  min_samples_split=2,
 8                  min_samples_leaf=1,
 9                  min_weight_fraction_leaf=0.,
10                  max_features="auto",
11                  max_leaf_nodes=None,
12                  min_impurity_decrease=0.,
13                  min_impurity_split=None,
14                  bootstrap=True,
15                  oob_score=False,
16                  n_jobs=None,
17                  random_state=None,
18                  verbose=0,
19                  warm_start=False,
20                  class_weight=None,
21                  ccp_alpha=0.0,
22                  max_samples=None):
23         ......
  • n_estimators:類型 int,默認值100,森林中決策樹的數量。
  • criterion:str類型,默認值為 『mse’。表示特徵選擇標準,可選 gini 或者 entropy ,前者是基尼係數,後者是信息熵。
  • max_depth: int 類型,默認值 為 None。 設置決策隨機森林中的決策樹的最大深度,深度越大,越容易過擬合,推薦樹的深度為:5-20之間。
  • min_samples_split:int 類型,默認值為2。設置結點的最小樣本數量,當樣本數量可能小於此值時,節點將不會在劃分。
  • min_samples_leaf:int 類型,默認值為1。 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。
  • min_weight_fraction_leaf: int 類型,默認值為0。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝默認是0,就是不考慮權重問題。
  • max_features:類型 int, float or {“auto”, “sqrt”, “log2”}  默認值為 auto ,此時 max_features =sqrt( n_features)。表示最佳分割時要考慮的特徵數量,如果為int,則在每個拆分中考慮max_features個特徵。如果為float,則max_features是一個分數,並在每次拆分時考慮int(max_features * n_features)個特徵。如果為「auto」,則 max_features = sqrt(n_features)。如果為「 sqrt」,則 max_features = sqrt(n_features)。如果為「 log2」,則max_features = log2(n_features)。注意:在找到至少一個有效的節點樣本分區之前,分割的搜索不會停止。
  • max_leaf_nodes:int 類型,默認為None,最大葉子節點數。
  • min_impurity_decrease:float 類型,默認值為0.0。表示節點劃分最小不純度, 這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。 
  • min_impurity_split:float 類型,默認值為0.0。功能可用 min_impurity_decrease 參數代替,新版不推薦使用,這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值則該節點不再生成子節點。即為葉子節點 。
  • bootstrap:bool類型,默認值為 True,表示是否進行bootstrap操作。當為 True 時,將每次有放回地隨機選取樣本,只有在extra-trees中,才可設置為 False
  • oob_score:bool類型,默認值為 False。表示是否使用袋外樣本來估計泛化精度。
  • n_jobs:int, 默認為 None,可並行運行的任務數量。如果為-1, 任務數量設置為CPU核的數量。
  • random_state:int 默認為 None。隨機數種子,推薦設置一個任意整數,同一個隨機值,模型可以復現。
  • verbose:int 默認是0。表示在擬合和預測時控制詳細程度。
  • warm_start:bool 類型,默認值 False,當設置為True時,重用之前調用的解決方案作為初始化,否則,需要刪除前面的解決方案。
  • class_weight:dict 或 list 類型,默認值為 None , 可選 “balanced” 。指定樣本各類別的的權重,主要是為了防止訓練集某些類別的樣本過多導致訓練的決策樹過於偏向這些類別。這裡可以自己指定各個樣本的權重,如果使用「balanced」,則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。
  • ccp_alpha:float 類型,默認值為 0.0 。表示使用 CCP 算法的誤差率增益率α閾值,小於該值的誤差率增益率對應的節點都會被剪枝。
  • max_samples:bool 類型,默認值為None。如果bootstrap為True,則從X抽取以訓練每個基本分類器的樣本數。如果為None(默認),則抽取X.shape [0]樣本。如果為int,則抽取max_samples樣本。如果為float,則抽取max_samples * X.shape [0]個樣本。

下面例子嘗試使用 6 棵決策樹的隨機森林,分別把每棵決策樹的數據分佈與特徵權重打印出來作比較。可見每棵決策樹的邊界並不相同,而且特徵權重也有區別。隨機森林會根據特徵權重求和並取平均值,最後算出的權重更客觀平均。

 1 def randomforestclassifier_test():
 2     #測試集,用四類數據
 3     X,y=make_blobs(n_samples=100,centers=4,random_state=1,n_features=2)
 4     X_train,X_test,y_train,y_test=train_test_split(X,y)
 5     #生成隨機森林模型進行訓練
 6     randomforest=RandomForestClassifier(n_estimators=6,max_features=2)
 7     #訓練模型
 8     randomforest.fit(X_train,y_train)
 9     #顯示準確率
10     print('RandomForestClassifier:\n  train data:{0}\n  test data:{1}\n'
11         .format(randomforest.score(X_train,y_train),
12                 randomforest.score(X_test,y_test)))
13     #打印數據分佈圖
14     fig,axes=plt.subplots(2,3)
15     axes1=axes.reshape(1,-1)[0]
16     # 打印每棵決策樹的數據分佈圖
17     for ax,estimator in zip(axes1,randomforest.estimators_):
18         xx=np.linspace(-13,2,200)
19         yy=np.linspace(-11,8,200)
20         XX,YY=np.meshgrid(xx,yy)
21         ZZ=np.c_[XX.ravel(),YY.ravel()]
22         zz=estimator.predict(ZZ).reshape(XX.shape)
23         ax.contourf(xx,yy,zz,alpha=0.4,zorder=2)
24         #畫出數據點
25         ax.scatter(X[:,0],X[:,1],c=y,marker='^',s=50)
26         # 顯示特徵佔比
27         print(estimator.feature_importances_)
28     plt.show()

運行結果

 

 8.2.2 RandomForestRegressor 隨機森林回歸

隨機森林也支持回歸算法,且 RandomForestRegressor 的構造函數與 RandomForestClassifier 基本一至。由於它是由多棵決策樹構成,所以回歸曲線會更加平滑。也可進行剪枝等操作,但必須注意超出訓練集以外的數據與決策樹一樣,都會以最後一個值作為輸出。而在 max_features 設置方面與 RandomForestClassifier 也有不同,默認情況下 RandomForestClassifier 分類模型 max_features = sqrt(n_features),而在 RandomForestRegressor  回歸模型 max_features = n_features。

構造函數

 1 class RandomForestRegressor(ForestRegressor):
 2     @_deprecate_positional_args
 3     def __init__(self,
 4                  n_estimators=100, *,
 5                  criterion="mse",
 6                  max_depth=None,
 7                  min_samples_split=2,
 8                  min_samples_leaf=1,
 9                  min_weight_fraction_leaf=0.,
10                  max_features="auto",
11                  max_leaf_nodes=None,
12                  min_impurity_decrease=0.,
13                  min_impurity_split=None,
14                  bootstrap=True,
15                  oob_score=False,
16                  n_jobs=None,
17                  random_state=None,
18                  verbose=0,
19                  warm_start=False,
20                  ccp_alpha=0.0,
21                  max_samples=None):
22         ......
  • n_estimators:類型 int,默認值100,森林中決策樹的數量。
  • criterion:str類型,默認值為 『mse’。表示特徵選擇標準,「mse」 表示均方誤差,可選 gini 或者 entropy ,前者是基尼係數,後者是信息熵。
  • max_depth: int 類型,默認值 為 None。 設置決策隨機森林中的決策樹的最大深度,深度越大,越容易過擬合,推薦樹的深度為:5-20之間。
  • min_samples_split:int 類型,默認值為2。設置結點的最小樣本數量,當樣本數量可能小於此值時,節點將不會在劃分。
  • min_samples_leaf:int 類型,默認值為1。 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。
  • min_weight_fraction_leaf: int 類型,默認值為0。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝默認是0,就是不考慮權重問題。
  • max_features:類型 int, float or {“auto”, “sqrt”, “log2”}  默認值為 auto ,此時 max_features = n_features。表示最佳分割時要考慮的特徵數量,如果為int,則在每個拆分中考慮 max_features個特徵。如果為float,則max_features是一個分數,並在每次拆分時考慮int(max_features * n_features)個特徵。如果為「auto」,則 max_features = n_features。如果為「 sqrt」,則max_features = sqrt(n_features)。如果為「 log2」,則max_features = log2(n_features)。注意:在找到至少一個有效的節點樣本分區之前,分割的搜索不會停止。
  • max_leaf_nodes:int 類型,默認為None,最大葉子節點數。
  • min_impurity_decrease:float 類型,默認值為0.0。表示節點劃分最小不純度, 這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。 
  • min_impurity_split:float 類型,默認值為0.0。功能可用 min_impurity_decrease 參數代替,新版不推薦使用,這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值則該節點不再生成子節點。即為葉子節點 。
  • bootstrap:bool類型,默認值為 True,表示是否進行bootstrap操作。當為 True 時,將每次有放回地隨機選取樣本,只有在extra-trees中,才可設置為 False
  • oob_score:bool類型,默認值為 False。表示是否使用袋外樣本來估計泛化精度。
  • n_jobs:int, 默認為 None,可並行運行的任務數量。如果為-1, 任務數量設置為CPU核的數量。
  • random_state:int 默認為 None。隨機數種子,推薦設置一個任意整數,同一個隨機值,模型可以復現。
  • verbose:int 默認是0。表示在擬合和預測時控制詳細程度。
  • warm_start:bool 類型,默認值 False,當設置為True時,重用之前調用的解決方案作為初始化,否則,需要刪除前面的解決方案。
  • ccp_alpha:float 類型,默認值為 0.0 。表示使用 CCP 算法的誤差率增益率α閾值,小於該值的誤差率增益率對應的節點都會被剪枝。
  • max_samples:bool 類型,默認值為None。如果bootstrap為True,則從X抽取以訓練每個基本分類器的樣本數。如果為None(默認),則抽取X.shape [0]樣本。如果為int,則抽取max_samples樣本。如果為float,則抽取max_samples * X.shape [0]個樣本。

用與決策樹回歸相同的例子對自定義的數據集進行訓練,輸出測試集的準確率。從輸出圖片對比可以看到,經過隨機森林計算的結果會明顯比決策樹更平滑,而超出訓練集以外的數據高樣會以最後一個值作為輸出。在多特徵數據集中,你會發現隨機森林的準確率會更高。

 1 def randomforestregressor_test():
 2     # 生成數據集
 3     X = np.linspace(-3, 3, 100)
 4     y = 2*X+1+np.random.ranf(100)
 5     X_train,X_test,y_train,y_test=train_test_split(X.reshape(-1,1),y)
 6     # 使用隨機森林模型進行訓練
 7     randomforest=RandomForestRegressor()
 8     randomforest.fit(X_train,y_train)
 9     # 測試數據
10     model_y=randomforest.predict(X.reshape(-1,1))
11     print('randomforestRegression:\n  train data:{0}\n  test data{1}'
12           .format(randomforest.score(X_train,y_train),
13                   randomforest.score(X_test,y_test)))
14     # 畫出數據點
15     plt.plot(X_train,y_train,'.')
16     plt.plot(X,model_y,'-')
17 
18     #超越訓練範圍會取最後一個點值
19     XX=np.linspace(3, 5, 20)
20     YY=randomforest.predict(XX.reshape(-1,1))
21     plt.plot(XX,YY,'-')
22     plt.legend(['train data','predict data','out tree data'])
23     plt.show()

運行結果

 

8.3 梯度提升回歸樹

雖然名稱中包含回歸字樣,但其實這模型既支持分類也支持回歸。與隨機森林不同的地方在於,隨機森林是以多棵決策樹求平均值的方式得到最終結果,而梯度提升回歸樹是以連續方式構建決策樹,每棵決策樹都會試圖糾正前一棵樹的錯誤。在默認情況下,每棵決策樹都會使用預剪枝,其深度都在1~5之間,以減少內存消耗。

8.3.1 GradientBoostingClassifier 梯度提升分類器

使用梯度提升分類器時,值得注意的是除了常用的 n_estimators 、min_samples_split 、 min_samples_leaf 參數外,會把 max_depth 調節到 3 ~5 之間,以減少內存消耗 。一般情況下會使用默認值把max_features 調節為 sqrt(n_features) 或以下,而學習率 learn_rate 會視乎訓練數據的多少而設定。如果訓練集數量不能確定時,可使用 validation_fraction 和 n_iter_no_change 參數,使訓練數據達到某一比例時停止訓練,並根據 n_iter_no_change 設置值把部分訓練層的數據作為參數值。

構造函數

 1 class GradientBoostingClassifier(ClassifierMixin, BaseGradientBoosting):
 2     @_deprecate_positional_args
 3     def __init__(self, *, loss='deviance', learning_rate=0.1, n_estimators=100,
 4                  subsample=1.0, criterion='friedman_mse', min_samples_split=2,
 5                  min_samples_leaf=1, min_weight_fraction_leaf=0.,
 6                  max_depth=3, min_impurity_decrease=0.,
 7                  min_impurity_split=None, init=None,
 8                  random_state=None, max_features=None, verbose=0,
 9                  max_leaf_nodes=None, warm_start=False,
10                  validation_fraction=0.1, n_iter_no_change=None, tol=1e-4,
11                  ccp_alpha=0.0):
12         ......
  • loss:str 類型,表示每一次節點分裂所要最小化的損失函數 (loss function),默認值為 deviance 。可選值 “deviance”和”exponential” ,deviance 代表使用 「logistic」 作為損失函數進行分類與概率輸出。exponential 代表使用 「Adaboost」 作為損失函數進行回歸。
  • learning_rate:float 類型,默認值為0.1 ,表示學習率。每一次樹分類都會更新這個值,而 learning_ rate控制着每次更新的幅度。只要訓練數據足夠多,這個值不應該設得太大,因為較小的learning rate使得模型對不同的樹更加穩健,就能更好地綜合它們的結果。
  • n_estimators:int 類型,默認值100,森林中決策樹的數量。通常會把 n_estimators 與參數 learning_rate 一起考慮,控制學習的質量。
  • subsample: float 類型,默認值 1.0。代表訓練每個決定樹所用到的子樣本佔總樣本的比例,因為是對於子樣本的,選擇是隨機的0.5 ~0.8就有更好的調參結果。如果使用默認值1.0,即代表不使用子樣本採樣。
  • criterion:str類型,默認值為 『friedman_mse’,可選值 {‘friedman_mse’, ‘mse’, ‘mae’}。friedman_mse」 表示對均方誤差改進的「弗里德曼得分」,「mse」 表示均方誤差,「mae」 表示平均絕對誤差。
  • min_samples_split:int 類型,默認值為2。設置結點的最小樣本數量,當樣本數量可能小於此值時,節點將不會在劃分。
  • min_samples_leaf:int 類型,默認值為1。 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。
  • min_weight_fraction_leaf: int 類型,默認值為0。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝默認是0,就是不考慮權重問題。
  • max_depth: int 類型,默認值 為 3。 決策樹的最大深度,深度越大,越容易過擬合。每棵決策樹都會使用預剪枝,其深度都在1~5之間,以減少內存消耗。
  • min_impurity_decrease:float 類型,默認值為 0.0。表示節點劃分最小不純度, 這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。 
  • min_impurity_split:float 類型,默認值為 None 。功能可用 min_impurity_decrease 參數代替,新版不推薦使用,這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值則該節點不再生成子節點。即為葉子節點 。
  • init:可選 estimator 或  ‘zero’,默認值為 None,代表初始化的時候的弱學習器。默認情況下會用訓練集樣本來做樣本集的初始化分類回歸預測。否則用init參數提供的學習器做初始化分類回歸預測。一般用在對數據已有先檢查的經驗,或者之前做過一些擬合的時候。
  • random_state:int 默認為 None。隨機數種子,推薦設置一個任意整數,同一個隨機值,模型可以復現。
  • max_features:類型 int, float or {“auto”, “sqrt”, “log2”}  默認值為 none,此時 max_features = n_features。表示最佳分割時要考慮的特徵數量,如果為int,則在每個拆分中考慮 max_features個特徵。如果為float,則max_features是一個分數,並在每次拆分時考慮int(max_features * n_features)個特徵。如果為「auto」,則 max_features = sqrt(n_features)。如果為「 sqrt」,則max_features = sqrt(n_features)。如果為「 log2」,則max_features = log2(n_features)。注意:在找到至少一個有效的節點樣本分區之前,分割的搜索不會停止。
  • verbose:int 默認是0。表示在擬合和預測時控制詳細程度。
  • max_leaf_nodes:int 類型,默認為None,最大葉子節點數。
  • warm_start:bool 類型,默認值 False,當設置為True時,重用之前調用的解決方案作為初始化,否則,需要刪除前面的解決方案。
  • validation_fraction:float 類型,默認值0.1 。測試數據占驗證集的比例時提前停止工作,必須介於0和1之間 float 類型。只有當 n_iter_no_chang 有效時才起作用。
  • n_iter_no_change:int 類型,默認值為 None。表示是否在驗證集比例達到 validation_fraction 設定值時提前終止訓練。由默認情況下,它被設置為 「None」 以禁用提前停止訓練。如果設置為 n 時,它將根據 validation_fraction 的設置去訓練數據多次,將前 n 次的訓練數據作為參考值去修改模型。
  • tol:float類型,默認值1e-4 ,表示停止訓練的誤差精度。
  • ccp_alpha:float 類型,默認值為 0.0 。表示使用 CCP 算法的誤差率增益率α閾值,小於該值的誤差率增益率對應的節點都會被剪枝。

下面以 breast_cancer 數據集為例,使用 GradientBoostingClassifier 模型進行分類測試。

 1 def gradientboostingclassifier_test():
 2     #測試數據
 3     cancer=dt.load_breast_cancer()
 4     X_train,X_test,y_train,y_test=train_test_split(cancer.data,cancer.target,random_state=1)
 5     #使用GradientBoostingClassifier模型進行學習
 6     gradientBoosting=GradientBoostingClassifier(max_depth=5,learning_rate=0.1)
 7     gradientBoosting.fit(X_train,y_train)
 8     #顯示準確率
 9     print('GradientBoostingClassifier:\n  train data:{0}\n  test data:{1}'
10         .format(gradientBoosting.score(X_train,y_train),
11                 gradientBoosting.score(X_test,y_test)))
12     #輸出 feature 特性重要性比率
13     print('\n  feature_importance:\n{0}'.format(gradientBoosting.feature_importances_))

運行結果

從運行結果看到訓練數據的準確率達到 100%,有可能存在可過擬合的情況。此時可以試着把最大深度調節為 2,把學習率降低到 0.05,可得到下面的結果。可見減小最大深度,調節學習率有利於預防過擬合情況,提高泛化性。

 

8.3.1  GradientBoostingRegressor 梯度提升回歸器

GradientBoostingRegressor 的使用方法與 RandomForestRegressor 類似,要注意的一點是 GradientBoostingRegressor 模型中 n_estimators 並非越大越好,因為值越大,模型的複雜程度就會越大,消耗的硬件資源也會越高。結合數據集的大小、內存情況以及 learning_rate 來設置 n_estimators 是比較好的選擇。  

構造函數

 1 class GradientBoostingRegressor(RegressorMixin, BaseGradientBoosting):
 2     @_deprecate_positional_args
 3     def __init__(self, *, loss='ls', learning_rate=0.1, n_estimators=100,
 4                  subsample=1.0, criterion='friedman_mse', min_samples_split=2,
 5                  min_samples_leaf=1, min_weight_fraction_leaf=0.,
 6                  max_depth=3, min_impurity_decrease=0.,
 7                  min_impurity_split=None, init=None, random_state=None,
 8                  max_features=None, alpha=0.9, verbose=0, max_leaf_nodes=None,
 9                  warm_start=False, validation_fraction=0.1,
10                  n_iter_no_change=None, tol=1e-4, ccp_alpha=0.0):
11         ......
  • loss:str 類型,表示每一次節點分裂所要最小化的損失函數 (loss function),默認值為 ‘ ls ‘。可選值 {‘ls’, ‘lad’, ‘huber’, ‘quantile’}  ,「ls」是使用最小二乘法,『lad’ 是使用最小絕對偏差,『huber’ 則是兩者的結合,’quantitle’ 則是使用 alpha 的設置值作為分位數進行使用。
  • learning_rate:float 類型,默認值為0.1 ,表示學習率。每一次樹分類都會更新這個值,而 learning_ rate控制着每次更新的幅度。只要訓練數據足夠多,這個值不應該設得太大,因為較小的learning rate使得模型對不同的樹更加穩健,就能更好地綜合它們的結果。
  • n_estimators:int 類型,默認值100,森林中決策樹的數量。通常會把 n_estimators 與參數 learning_rate 一起考慮,控制學習的質量。
  • subsample: float 類型,默認值 1.0。代表訓練每個決定樹所用到的子樣本佔總樣本的比例,因為是對於子樣本的,選擇是隨機的0.5 ~0.8就有更好的調參結果。如果使用默認值1.0,即代表不使用子樣本採樣。
  • criterion:str類型,默認值為 『friedman_mse’,可選值 {‘friedman_mse’, ‘mse’, ‘mae’}。friedman_mse」 表示對均方誤差改進的「弗里德曼得分」,「mse」 表示均方誤差,「mae」 表示平均絕對誤差。
  • min_samples_split:int 類型,默認值為2。設置結點的最小樣本數量,當樣本數量可能小於此值時,節點將不會在劃分。
  • min_samples_leaf:int 類型,默認值為1。 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。
  • min_weight_fraction_leaf: int 類型,默認值為0。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝默認是0,就是不考慮權重問題。
  • max_depth: int 類型,默認值 為 3。 決策樹的最大深度,深度越大,越容易過擬合。每棵決策樹都會使用預剪枝,其深度都在1~5之間,以減少內存消耗。
  • min_impurity_decrease:float 類型,默認值為 0.0。表示節點劃分最小不純度, 這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。 
  • min_impurity_split:float 類型,默認值為 None 。功能可用 min_impurity_decrease 參數代替,新版不推薦使用,這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值則該節點不再生成子節點。即為葉子節點 。
  • init:可選 estimator 或  ‘zero’,默認值為 None,代表初始化的時候的弱學習器。默認情況下會用訓練集樣本來做樣本集的初始化分類回歸預測。否則用init參數提供的學習器做初始化分類回歸預測。一般用在對數據已有先檢查的經驗,或者之前做過一些擬合的時候。
  • random_state:int 默認為 None。隨機數種子,推薦設置一個任意整數,同一個隨機值,模型可以復現。
  • max_features:類型 int, float or {“auto”, “sqrt”, “log2”}  默認值為 None,此時 max_features = n_features。表示最佳分割時要考慮的特徵數量,如果為int,則在每個拆分中考慮 max_features個特徵。如果為float,則max_features是一個分數,並在每次拆分時考慮int(max_features * n_features)個特徵。如果為「auto」,則 max_features = n_features。如果為「 sqrt」,則max_features = sqrt(n_features)。如果為「 log2」,則max_features = log2(n_features)。注意:在找到至少一個有效的節點樣本分區之前,分割的搜索不會停止。
  • alpha: float類型,默認值是0.9 。當使用 「quantile」 作為 loss 時,所指定分位數的值。默認是0.9,如果噪音點較多,可以適當降低這個分位數的值。
  • verbose:int 默認是0。表示在擬合和預測時控制詳細程度。
  • max_leaf_nodes:int 類型,默認為None,最大葉子節點數。
  • warm_start:bool 類型,默認值 False,當設置為True時,重用之前調用的解決方案作為初始化,否則,需要刪除前面的解決方案。
  • validation_fraction:float 類型,默認值0.1 。測試數據占驗證集的比例時提前停止工作,必須介於0和1之間 float 類型。只有當 n_iter_no_chang 有效時才起作用。
  • n_iter_no_change:int 類型,默認值為 None。表示是否在驗證集比例達到 validation_fraction 設定值時提前終止訓練。由默認情況下,它被設置為 「None」 以禁用提前停止訓練。如果設置為 n 時,它將根據 validation_fraction 的設置去訓練數據多次,將前 n 次的訓練數據作為參考值去修改模型。
  • tol:float類型,默認值1e-4 ,表示停止訓練的誤差精度。
  • ccp_alpha:float 類型,默認值為 0.0 。表示使用 CCP 算法的誤差率增益率α閾值,小於該值的誤差率增益率對應的節點都會被剪枝。

使用與 RandomForestRegressor 相同的測試數據,嘗試把 n_estimators 降低到 20,把 max_depth 設置為 1,學習率 learning_rate 設置為 0.08 。把參數調低後,也可達到隨機森林類似的結果,而且線條的順滑程度同樣比決策樹要高。

 1 def gradientbootingregressor_test():
 2     # 生成數據集
 3     X = np.linspace(-3, 3, 100)
 4     y = 2*X+1+np.random.ranf(100)
 5     X_train,X_test,y_train,y_test=train_test_split(X.reshape(-1,1),y)
 6     # 使用梯度提升回歸樹模型進行訓練
 7     gradientbooting=GradientBoostingRegressor(n_estimators=40,max_depth=3,learning_rate=0.08)
 8     gradientbooting.fit(X_train,y_train)
 9     # 測試數據
10     model_y=gradientbooting.predict(X.reshape(-1,1))
11     print('gradientbootingRegression:\n  train data:{0}\n  test data{1}'
12           .format(gradientbooting.score(X_train,y_train),
13                   gradientbooting.score(X_test,y_test)))
14     # 畫出數據點
15     plt.plot(X_train,y_train,'.')
16     plt.plot(X,model_y,'-')
17 
18     #超越訓練範圍會取最後一個點值
19     XX=np.linspace(3, 5, 20)
20     YY=gradientbooting.predict(XX.reshape(-1,1))
21     plt.plot(XX,YY,'-')
22     plt.legend(['train data','predict data','out tree data'])
23     plt.show()

運行結果

 

 回到目錄

本章總結

本文主要介紹支持向量機、k近鄰、樸素貝葉斯分類 、決策樹、決策樹集成等模型的應用。講解了支持向量機 SVM 線性與非線性模型的適用環境,並對核函數技巧作出深入的分析,對線性 Linear 核函數、多項式 Poly 核函數,高斯 RBF 核函數進行了對比。講述了 K 近鄰的使用方法。對高斯樸素貝葉斯分類器(Gaussian naive Bayes)、多項式樸素貝葉斯分類器(Multinomial naive Bayes)和 伯努利貝葉斯分類器 (Bernoulli naive Bayes)進行了不同的介紹。最後對決策樹(DecisionTree)、隨機森林(RandomForest)、梯度提升回歸器(GradientBoosting)進行分析。
希望本篇文章對相關的開發人員有所幫助,由於時間倉促,錯漏之處敬請點評。
下篇文章將為大家介紹《Python 機器學習實戰——無監督學習》,敬請留意!

對 .Python  開發有興趣的朋友歡迎加入QQ群:790518786 共同探討 !
對 JAVA 開發有興趣的朋友歡迎加入QQ群:174850571 共同探討!
對 .NET  開發有興趣的朋友歡迎加入QQ群:162338858 共同探討 !

 

機器學習相關文章

Python 機器學習實戰 —— 監督學習(上)

Python 機器學習實戰 —— 監督學習(下)

 

作者:風塵浪子
//www.cnblogs.com/leslies2/p/14893403.html

原創作品,轉載時請註明作者及出處