前言
《機器學習-回歸問題》知道了回歸問題的處理方式,分類問題才是機器學習的重點.從數據角度講,回歸問題可以轉換為分類問題的微分
邏輯回歸
邏輯回歸(Logistics Regression),邏輯回歸雖然帶有回歸字樣,但是邏輯回歸屬于分類算法。但只可以解決二分類問題
- 先回顧一下回歸問題的公式: y ^ = θ T X \hat y=\theta^TX y^?=θTX
- 通常線性方程的值域為 ( ? ∞ , + ∞ ) (-\infty,+\infty) (?∞,+∞),我們想辦法轉換成百分比,即概率, 概率值域為[0, 1],因此我們在這個基礎上做一個變形,完成從 ( ? ∞ , + ∞ ) (-\infty,+\infty) (?∞,+∞)到[0,1]的轉換。 p ^ = σ ( θ T X ) \hat p= \sigma(\theta^TX) p^?=σ(θTX)
- 這個轉換函數就叫做Sigmoid函數,函數的表達式 σ ( t ) = 1 1 + e ? t \sigma(t)={1 \over 1+e^{-t}} σ(t)=1+e?t1?
相當于把一條直線強行掰彎,使其值域在0-1之間。這樣就完成從直線回歸到邏輯回歸的轉變。 - 最后給出邏輯回歸的公式: y = { 1 if? p ≥ 0.5 0 if? p < 0.5 y=\begin{cases} 1 &\text{if } p \ge 0.5 \\ 0 &\text{if } p \lt 0.5 \end{cases} y={10?if?p≥0.5if?p<0.5?
為什么先用0.5這值? σ ( 0 ) = 0.5 即 θ T X = 0 \sigma(0) = 0.5 即 \theta^TX = 0 σ(0)=0.5即θTX=0
損失函數
對于給定的樣本數據集x,y如何找到參數 θ \theta θ,使得使用這樣的方式,可以最大程度地獲得樣本數據集x,對應的分類輸出y?
- 從公司本身去分析:
- 假設y=1, [0.1,0.2] 和[0.3,0.4] 的差值都是0.1.但是Sigmoid函數壓縮過的,即要通邊log函數解壓
- 整合到一起:
到此,就可以總結出Logistic Regression的損失函數:
這個函數是一個凸函數,他沒有公式解,只能使用梯度下降法求解。
決策邊界
如圖所示,直線就是所謂的決策邊界,左邊為紅點,右邊為藍點. 樣例中選用了兩個特征值,即邊界公式
具體代碼如下
import numpy as np
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split# 加載數據集, 只選取2個特征,2種花
iris = datasets.load_iris()
x = iris.data
y = iris.target
x = x[y<2, :2]
y = y[y<2]
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=666)
log_reg = LogisticRegression()
log_reg.fit(x_train, y_train)## 分界函數
def x2(x1): return (-log_reg.coef_[0][0] * x1 - log_reg.intercept_) / log_reg.coef_[0][1]## 虛擬axis范圍的點,傳入訓練的model
def plot_decision_boundary(model, axis):x0, x1 = np.meshgrid(np.linspace(axis[0], axis[1], int((axis[1] - axis[0])*100)).reshape(1, -1),np.linspace(axis[2], axis[3], int((axis[3] - axis[2])*100)).reshape(1, -1),)x_new = np.c_[x0.ravel(), x1.ravel()]y_predict = model.predict(x_new)zz = y_predict.reshape(x0.shape)from matplotlib.colors import ListedColormapcustom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])plt.contourf(x0, x1, zz, cmap=custom_cmap)# 畫出數據點和決策邊界
x1_plot = np.linspace(4, 8, 1000)
x2_plot= x2(x1_plot)
plot_decision_boundary(log_reg, axis=[4, 7.5, 1.5, 4.5])
plt.scatter(x[y==0, 0], x[y==0, 1], color='red')
plt.scatter(x[y==1, 0], x[y==1, 1], color='blue')
plt.plot(x1_plot, x2_plot)
plt.show()
KNN算法的決策邊界也可以同理得出
邏輯回歸中使用多項式特征
如果像下圖中不可能使用一根直線完成分割,但是很顯然可以使用圓形或者橢圓形完整這個分類任務。
其實在線性回歸到多項式回歸我們思想就是給訓練數據集添加多項式項。同理我們把這個東西用到邏輯回歸中。
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScalerdef PolynomiaLogisticRegression(degree):return Pipeline([('poly', PolynomialFeatures(degree=degree)),('std_scale', StandardScaler()),('log_reg', LogisticRegression())])poly_log_reg = PolynomiaLogisticRegression(degree=2)
poly_log_reg.fit(x, y)## 決策邊界
plot_decision_boundary(poly_log_reg, axis=[-4, 4, -4, 4])
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()
邏輯回歸中使用正則化
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler# 傳入一個新的參數C
def PolynomiaLogisticRegression(degree, C):return Pipeline([('poly', PolynomialFeatures(degree=degree)),('std_scale', StandardScaler()),('log_reg', LogisticRegression(C=C))])poly_log_reg3 = PolynomiaLogisticRegression(degree=20, C=0.1)
poly_log_reg3.fit(x, y)
plot_decision_boundary(poly_log_reg3, axis=[-4, 4, -4, 4])
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()
邏輯回歸解決多分類問題
在開始之初,說邏輯回歸只可以解決二分類問題, 其實可以稍加改造使其能夠解決多分類問題。當然這個改造方式并不是只針對邏輯回歸這一種算法,這是一種通用的近乎于可以改造所有的二分類。
- ? OvR(One vs Rest)一對剩余,有些說法也叫(One vs All,OVA)。針對多煩問題,如果我們取出其中任意一種,將剩下的作為另一種,這種就是一個2分類問題,同理將每一個類別分別做一次這樣的2分類,如果有n個類別就進行n次分類,選擇分類得分最高的。
通常我們把One定義成正樣本即p>0.5的. 我們可以求得每個分類的p,然后找到最高的
- OvO(One vs One)一對一,就是在多個類別中,先挑出2個來進行2分類,然后逐個進行,也就是C(n,2)中情況進行2分類,選擇贏數最高的分類。
相當于每一個分類有n-1次PK. 選PK贏次數最多的
分類算法的評價
假如現在有一個癌癥預測系統,輸入檢測信息,可以判斷是否有癌癥。如果僅僅使用分類準確度來評價模型的好壞是否合理呢?假如此時模型的預測準確度是99.9%,那么是否能認為模型是好的呢?如果癌癥產生的概率只有0.01%,那就意味著這個癌癥預測系統只有預測所有人都是健康,即可達到99.99%的準確率。到這里,就能大概理解分類準確度評價模型存在的問題。什么時候才會出現這樣的問題呢?這就是對于極度偏斜的數據(Skewed Data),也就樣本數據極度不平衡的情況下,只使用分類準確度是遠遠不夠的。因此需要引進更多的指標。
混淆矩陣
混淆矩陣也稱誤差矩陣,是表示精度評價的一種標準格式,用n行n列的矩陣形式來表示。以二分類為例子
- TN(True Negative):真實值Negative,預測Negative
- FP(False Positive):真實值Negative,預測Positive
- FN(False Negative):真實值Positive,預測Negative
- TP(True Positive):真實值Positive,預測Positive
假設還是癌癥預測,先測試了10000個人,預測結果如下
TN:9978個人真實沒有癌癥,預測沒有癌癥;FP:12個人真實沒有癌癥,預測有癌癥;FN:2個人真實有癌癥,預測沒有癌癥;TP:8個人真實有癌癥,預測也有癌癥。其實,就是希望右斜對角線越多越好就,即TN和TP的數量越多越好,也由此會延伸出更多的二級指標。
- 精準率(precision): p r e c i s i o n = T P F P + T P = 8 12 + 8 = 40 % precision = {TP \over {FP+ TP}}={8 \over {12+8}} = 40\% precision=FP+TPTP?=12+88?=40%,把健康的預測錯
- 召回率(recall): r e c a l l = T P F N + T P = 8 2 + 8 = 80 % recall = {TP \over {FN+ TP}}={8 \over {2+8}} = 80\% recall=FN+TPTP?=2+88?=80%,把癌癥的預測錯.
精準率,召回率就是對更加關注的事件進行一個評判,比如例子中我們把預測有癌癥作為關注的重點.在現實的使用過程中,這兩個評價指標可能會出現一些矛盾,比如有些時候使用這種方法精準率高但召回率低,使用另外一種方法精準率低召回率高,那么如何權衡兩種指標呢?
有時候比較注重精準率,比如股票預測,有時候更加注重召回率,比如病人診斷。對于不同的應用場景,偏好不同的指標。而往往有些時候可能并不是這么的極端,既需要保證精準率又需要保證召回率?由此引出一個新的指標:F1-score。
F1分數(F1 Score),是統計學中用來衡量二分類模型精確度的一種指標。它同時兼顧了分類模型的精確率和召回率。F1分數可以看作是模型精確率和召回率的一種調和平均,它的最大值是1,最小值是0。
決策邊界: θ T X = 0 \theta^TX = 0 θTX=0 ,在解析幾何中,其實這就是一條直線,這條直線就是分類中的決策邊界,在直線的一側為0,另一側為1,那么為什么要取0呢? 因為要對半開? 那為什么要對半開呢?
如果讓決策邊界: θ T X = t h r e s h o l d \theta^TX = threshold θTX=threshold ,此時就是相當于平移決策邊界,從而影響分類結果。
這樣子threshold就相當一個超參數,可以根據F1的分值去調整
另外也可以通過以下兩種曲線,反應超參數調解的效果
- P-R曲線
- ROC曲線
支持向量機
支持向量機(support vector machines)是尋找一個超平面來對樣本進行分割,分割的原則是間隔最大化,最終轉化為一個凸二次規劃問題來求解。
邏輯回歸通過最小化損失函數來確定決策邊界而svm嘗試尋找一個最優的決策邊界,距離兩個類別最近的樣本最遠,圖中3個點到決策邊界距離相同。這三個點就叫做支持向量(support vector)。而平行于決策邊界的兩條直線之間的距離就是 m a r g i n margin margin ,svm就是要最大化 m a r g i n margin margin保證模型的泛化能力,這樣就把這個問題轉化稱為最優化問題。
- 在二維空間中點 ( x , y ) (x,y) (x,y)到直線 A x + B y + C = 0 Ax+By+C=0 Ax+By+C=0的距離公式 : ∣ A x + B y + C ∣ A 2 + B 2 |Ax+By+C| \over \sqrt {A^2+B^2} A2+B2?∣Ax+By+C∣?
- 將其拓展到n維 w T x + b = 0 w^Tx+b=0 wTx+b=0的距離公式: ∣ w T x + b ∣ ∣ ∣ w ∣ ∣ |w^Tx+b| \over ||w|| ∣∣w∣∣∣wTx+b∣?其中 w = w 1 2 + w 2 2 + . . . + w n 2 w= \sqrt {w_1^2+w_2^2+...+w_n^2} w=w12?+w22?+...+wn2??
要找到具有最大間隔的劃分超平面,即是找到能滿足條件約束的參數 w w w和 b b b,使得 m i n 1 2 ∣ ∣ w ∣ ∣ 2 min {1 \over 2}||w||^2 min21?∣∣w∣∣2,這就是支持向量機的基本型。
解決有約束問題的最優化問題需要使用拉格朗日乘子法得到對偶問題,最終得到函數:
其中 α i \alpha_i αi?就是拉格朗日乘子。這就是Hard Margin SVM。
SVM正則化
如果有一個藍色的點混進了紅色的點當中,這就導致數據集根本就是線性不可分的情況,根本找不出一條直線能夠將這兩類分開,在這種情況下Hard margin就不再是泛化能力強不強的問題,而是根本找不出一條直線將其分開。由此引出Soft Margin SVM(正則化)。
如圖,將直線往里面移點,來點誤差 ζ i \zeta_i ζi?,最終函數將變成
L1正則還引入一個新的超參數C去權衡容錯能力和目標函數,因為已經限制了 ζ i > 0 \zeta_i > 0 ζi?>0,所以不加絕對值。C越大越趨近于一個Hard Margin SVM,C越小,就意味著有更大的容錯空間。
其實這也可以理解為我們為其加入了L1正則項,避免模型向一個極端方向發展,使得對于極端的數據集不那么敏感,對于未知的數據有更好的泛華能力。
那么有L1正則,相對應就有L2正則。
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsiris = datasets.load_iris()
x = iris.data
y = iris.target
# 只做一個簡單的二分類
x = x[y<2, :2]
y = y[y<2]from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC## 數據標準化
standardscaler = StandardScaler()
standardscaler.fit(x)
x_standard = standardscaler.transform(x)svc = LinearSVC(C=0.1)
svc.fit(x_standard, y)## 畫圖
def plot_svc_decision_boundary(model, axis):x0, x1 = np.meshgrid(np.linspace(axis[0], axis[1], int((axis[1] - axis[0])*100)).reshape(1, -1),np.linspace(axis[2], axis[3], int((axis[3] - axis[2])*100)).reshape(1, -1),)x_new = np.c_[x0.ravel(), x1.ravel()]y_predict = model.predict(x_new)zz = y_predict.reshape(x0.shape)from matplotlib.colors import ListedColormapcustom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])plt.contourf(x0, x1, zz, cmap=custom_cmap)w = model.coef_[0]b = model.intercept_[0]# w0*x0 + w1*x1 + b = 0# x1 = -w0/w1 * x0 - b/w1plot_x = np.linspace(axis[0], axis[1], 200)up_y = -w[0]/w[1] * plot_x - b/w[1] + 1/w[1]down_y = -w[0]/w[1] * plot_x - b/w[1] - 1/w[1]up_index = (up_y >= axis[2]) & (up_y <= axis[3])down_index = (down_y >= axis[2]) & (down_y <= axis[3])plt.plot(plot_x[up_index], up_y[up_index], color='black')plt.plot(plot_x[down_index], down_y[down_index], color='black')plot_svc_decision_boundary(svc, axis=[-3, 3, -3, 3])
plt.scatter(x_standard[y==0, 0], x_standard[y==0, 1], color='red')
plt.scatter(x_standard[y==1, 0], x_standard[y==1, 1], color='blue')
plt.show()
核函數
前面一直都在講的是線性的svm,對于svm來說也可以解決非線性問題,類比線性回歸到非線性回歸的思想,首先使用多項式特征PolynomialFeatures。另外也可以使用核函數
與多項式的方法相同,核函數的目的幫忙從原始空間映射到一個更高維的特征空間. 但不同的是多項的方式要自己造數據,占據大量空間
以高斯核函數為例: 實質上就是把一個mn維的數據映射成了mm的數據。由于理論上數據量可以是無窮維,所以說是映射到一個無窮維空間中。
高斯分布和正態分布可以互相等價
gamma( γ \gamma γ) 就是正態中常數的匯總
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsx, y = datasets.make_moons(noise=0.15, random_state=666)
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipelinedef RBFKernelSVC(gamma=1.0):return Pipeline([('std_scale', StandardScaler()),('svc', SVC(kernel='rbf', gamma=gamma))])svc = RBFKernelSVC(gamma=1.0)
svc.fit(x, y)plot_decision_boundary(svc, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()
svm解決回歸問題的思路:在margin區域內的點越多越好
決策樹
決策樹是基于樹結構進行決策的。決策樹(Decision Tree)是在已知各種情況發生概率的基礎上,通過構成決策樹來求取凈現值的期望值大于等于零的概率.以一現實中招聘為例子
發表過論文|是否研究生等,對應的就是我們的特征值
如何找出這個2.4,1.8的特征判斷值呢?
信息熵
熵在信息論中代表隨機變量不確定度的度量。熵越大,數據不確定性越高,熵越低,數據的不確定性越低。假定當前樣本集合D中k類樣本所占比例為 p i p_i pi?,則信息熵的定義:
- 節點中,計算把A類別 和B類別能到達此處的概率 p i p_i pi?,調節判斷值,讓H盡量小
- 葉子節點中, A類別的 P a P_a Pa? > B類別的 P b P_b Pb?, 則程序走到這就是A類型
以二分類的例公式為: H = ? x l o g ( x ) ? ( 1 ? x ) l o g ( 1 ? x ) H = -xlog(x)-(1-x)log(1-x) H=?xlog(x)?(1?x)log(1?x),其圖為下,H值在0.5的時最大
基尼指數
基尼指數CART和信息熵的作用是一樣的,也是來幫助決策樹選擇劃分屬性.其公式
決策樹中的超參數
當決策樹建立完成后,平均來說模型預測時候的復雜度: O ( l o g ( m ) ) O(log(m)) O(log(m))其中m表示數據集中的樣本個數,但是模型訓練的復雜度: m ? n O ( l o g ( m ) ) m*nO(log(m)) m?nO(log(m))。決策樹(非參數)的缺點就是非常容易產生過擬合.而決策樹中解決過擬合問題的主要手段就是剪枝(pruning)。主要手段
- 樹的深度
- 最小樣本數量
- 葉子節點的最小樣本數量
- 葉子節點的數量
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsx, y = datasets.make_moons(noise=0.25, random_state=666)
from sklearn.tree import DecisionTreeClassifier# 在不傳入任何參數時候,默認就是使用gini指數,樹的結構分不到不能再分為止。很容易過擬合
# 傳入max_depth=2,限制樹的最大層數
dt_clf = DecisionTreeClassifier(max_depth=2)
dt_clf.fit(x, y)
plot_decision_boundary(dt_clf, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()
決策樹的局限性
- 局限性1:橫平豎直的直線劃分,并不是能使用斜線。因此并不是最好的劃分方式。
- 局限性2:對個別數據敏感。這也是非參數學習的一個共性。
集成學習
集成學習(ensemble learning)通過構建并結合多個學習器來完成學習任務。假如邏輯回歸、決策樹、svm三種算法集成.
- Hard Voting,通過各算法的結果進行投票,票多為最終結果
- Soft Voting,要求集合的每一個模型都能估計概率,然后再根據各模型的估計概率算出總概率,概率最大的為最終結果
- 邏輯回歸,本身就是基于概率模型的
- KNN,k個近鄰中數量最多的那個類的數量除以k就是概率
- 決策樹。葉子節點中那個類數量最大就是那個類,概率就是數量最大的那個類除以所有葉子節點的類。
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
x, y =datasets.make_moons(n_samples=10000, noise=0.3, random_state=42)
x_train, x_test, y_train, y_test = train_test_split(x, y,test_size=0.4, random_state=42)from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC## voting='soft'
voting_clf = VotingClassifier(estimators=[('log_reg', LogisticRegression()),('svm_clf', SVC()),('dt_clf', DecisionTreeClassifier()),
], voting='hard')voting_clf.fit(x_train, y_train)
voting_clf.score(x_test, y_test)
根據輸出結果顯然比Hard Voting效果要好很多,但是仍然有個問題就是雖然有很多機器學習算法,但是從投票的角度看,仍然不夠多。因此需要創建更多的子模型,集成更多的子模型的意見。而且子模型之間不能一致,必須要有差異性。
Bagging和Pasting
更多的子模型且模型之間不能一致會產生什么效果呢?
這就是集成學習的威力。但是在實際的使用過程很難保證500個子模型的準確率都高于平均水平,甚至有些子模型可能預測錯誤的概率比預測正確的概率還要高,但是這樣并不影響總體準確率的提升。
如何創建差異性?每個子模型只能看數據樣本的一部分,就涉及取樣.
取樣:放回取樣(Bagging)和不放回取樣(Pasting)。在統計學,放回取樣:bootstrap。
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsx, y =datasets.make_moons(n_samples=5000, noise=0.3, random_state=42)from sklearn.model_selection import train_test_splitx_train, x_test, y_train, y_test = train_test_split(x, y, random_state=42)from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifierbagging_clf = BaggingClassifier(DecisionTreeClassifier(),n_estimators=50, # 模型個數max_samples=100, # 最大樣本數bootstrap=True) # 有放回隨機
bagging_clf.fit(x_train, y_train)
# n_estimators=500 0.912
# n_estimators=50 0.9096
bagging_clf.score(x_test, y_test)dt_clf = DecisionTreeClassifier()
dt_clf.fit(x_train, y_train)
# 0.872
dt_clf.score(x_test, y_test)
根據對比,當不適用集成學習只是用DecisionTree時,準確率只有0.872,使用50個子模型,每次有放回抽樣100個樣本,準確率為0.9096,使用500個樣本,每次有放回抽樣100個樣本,準確率為0.912。
更多關于Bagging的特性:
-
OOB(Out-of-Bag):放回取樣會有一定的概率導致一部分樣本很有可能沒有被取到,嚴格地進行數據計算平均大約有37%的樣本是取不到的,這部分樣本就成為Out-of-Bag。因此為了解決這個問題,就不需要將數據集劃分為訓練集和測試集了,就使用這部分沒有被取到的樣本做測試或驗證。
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),n_estimators=500,max_samples=100,bootstrap=True,oob_score=True) # 此時使用的數據集就是全部數據。 # oob_score=True的意思就使用剩下未取到的數據作為測試集。 bagging_clf.fit(x, y) bagging_clf.oob_score_
-
Bagging的思路極易并行化處理,在sklearn中對于并行處理傳入的參數:n_jobs,-1表示使用全部的核。
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),n_estimators=5000,max_samples=100,bootstrap=True,oob_score=True,n_jobs=-1)
-
使得子模型具有差異化。除了使用有放回的隨機取樣使得訓練子模型的數據集有差異之外
- 針對特征進行隨機采樣,Random Subspaces
- 還可以既針對樣本,又針對特征進行隨機采樣。Random Patches。Random Patches
clf = BaggingClassifier(DecisionTreeClassifier(),n_estimators=5000,max_samples=100,bootstrap=True,oob_score=True,n_jobs=-1,max_features=1,bootstrap_features=True,) # max_samples=100, bootstrap=True,表示針對樣本進行隨機抽樣 # max_features=1,bootstrap_features=True表示針對樣本特征進行隨機抽樣 clf.fit(x, y) clf.oob_score_
隨機森林
隨機森林(Random Forest,簡稱RF)是Bagging的一個擴展變體,RF在以決策樹為基學習器構建Bagging集成的基礎是,進一步在決策樹的訓練過程中引入隨機屬性選擇。
決策樹在節點劃分上,在隨機的特征子集上尋找最優的劃分特征。具體來說在傳統決策樹在選擇劃分屬性時是當前結點的屬性結合(假設有d個屬性)中隨機選擇一個最優屬性;而在RF中,對基決策樹的每個結點,先從該結點的屬性集合中隨機選擇一個包含k個屬性的子集,然后再從這個子集中選擇一個屬性用于劃分。一般情況下,推薦 k = l o g 2 d k=log_2d k=log2?d。隨機森林中基學習器的多樣性不僅來自樣本擾動,還來自屬性擾動。這就使得最終集成的泛華性能可通過個體學習器之間差異度的增加而進一步提升。
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsx, y =datasets.make_moons(n_samples=500, noise=0.3, random_state=666)
from sklearn.ensemble import RandomForestClassifierrf_clf = RandomForestClassifier(n_estimators=500, random_state=666, oob_score=True, n_jobs=-1,max_leaf_nodes=16)
rf_clf.fit(x, y)
# 0.906
rf_clf.oob_score_
除了隨機樣本的方法RF,還可以隨機特性值,極端隨機樹ET(Extremely randomized trees).即根據特征數去拆出模型.ET與RF的區別:
- RF應用了Bagging進行隨機抽樣,而ET的每棵決策樹應用的是相同的樣本。
- RF在一個隨機子集內基于信息熵和基尼指數尋找最優屬性,而ET完全隨機尋找一個特征值進行劃分。
Boosting
目前集成學習的方法大致分為兩類:一類就是個體學習器之間不存在強依賴關系、可同時生成的并行化方法;另一類是個體學習器之間存在強依賴關系,必須串行生成的序列化方法。前者的代表是Bagging和隨機森林,后者的代表是Boosting。
具體來說:就是先從初始訓練集訓練出一個基學習器,再根據基學習器的表現對訓練樣本分布進行調整,使得先前學習器做的訓練樣本在后續受到更多的關注,然后基于調整后的樣本分布來訓練下一個學習器,如此重讀進行,直至學習器數目達到預先指定的值。
根據上面這張圖來看,經過第一個學習器的學習后給預測錯誤樣本呈現為更深的藍色的點,訓練正確的為淺色的藍色的點,賦予錯誤的訓練樣本以更高的權重,對于經過調整的訓練樣本再次訓練一個學習器,同理一直迭代下去。最終函數是
h ( x ) = h 1 ( x ) + h 2 ( x ) + h 3 ( x ) h(x)=h_1(x)+h_2(x)+h_3(x) h(x)=h1?(x)+h2?(x)+h3?(x)
from sklearn.ensemble import GradientBoostingClassifier
gb_clf = GradientBoostingClassifier(max_depth=2, n_estimators=30)
gb_clf.fit(x_train, y_train)
# 0.9048
gb_clf.score(x_test, y_test)
在sklearn中梯度提升回歸樹(Gradient Boosting Decision Tree),簡稱GBDT
- 通過采用加法模型(即基函數的線性組合),以及不斷減小訓練過程產生的殘差來達到將數據分類或者回歸的算法。
- 訓練一個模型m1,產生錯誤e1,針對e1訓練第二個模型m2,產生錯誤e2,針對e2訓練第三個模型m3,產生錯誤e3…,最終的預測結果是m1+m2+m3+…。
- 有四種可選的損失函數,分別為’ls:平方損失’,‘lad:絕對損失’,‘huber:huber損失’,‘quantile:分位數損失’;
Stacking
除了采用加法模型的方式之外,還有一類學習型Stacking.
將訓練樣本分為三部分,
- 第一部分訓練layer1的三個學習器
- 第二部分的樣本特征值通過layer1處理得到新的特征值, 再訓練layer2的學習器.(當然第一部份數據也參加了)
- 第三部分的樣本特征值通過layer1,layer2處理得到新的特征值,訓練得到layer3的學習器(當然第一,二部份數據也參加了)
第一部分確定layer1的模型,第二部分+第一部分確定layer2的模型,第三部分+第二部分+第一部分確定layer3的模型
這樣得到最終的學習結果。此時這樣的網絡跟人工神經網絡就有點類似了。
主要參考
《機器學習理論(八)邏輯回歸》
《機器學習理論(九)分類算法的評價》
《機器學習理論(十)支持向量機》
《機器學習理論(十一)決策樹》
《機器學習理論(十二)集成學習》
《分類模型評判指標–混淆矩陣》