主頁 > 後端開發 > Python 機器學習實戰 —— 監督學習(下)

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

2021-06-24 06:18:54 後端開發

前言

近年來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 機器學習實戰 —— 監督學習(下)

 

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

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

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/288298.html

標籤:Python

上一篇:2020,分手快樂;2021,且行且歌

下一篇:Python 執行緒互斥鎖 Lock - Python零基礎入門教程

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more