機器學習——集成學習(一)

一. 集成學習概述

  1. 什麼是集成學習?

它本身不是一個單獨的機器學習算法,而是通過構建並結合多個機器學習器來完成學習任務。
一般說的集成學習方法都是指同質個體學習器,而同質個體學習器使用最多的模型是CART決策樹和神經網絡。

在這裏插入圖片描述

  1. 集成學習需要解決的問題是什麼?

a. 如何得到若干個個體學習器
b. 如何選擇一種結合策略,將這些個體學習器集合成一個強學習器

  1. 如何得到若干個個體學習器

a. 所有個體學習器都是同一種類的或者說是同質的
b. 所有的個體學習器不全是一個種類的,或者說是異質的。

二. 集成學習算法簡介

  1. bagging 算法

bagging的個體弱學習器的訓練集是通過隨機採樣得到的。通過T次的隨機採樣,我們就可以得到T個採樣集,對於這T個採樣集,我們可以分別獨立的訓練出T個弱學習器,再對這T個弱學習器通過集合策略來得到最終的強學習器。
對於這裏的隨機採樣有必要做進一步的介紹,這裏一般採用的是自助採樣法(Bootstrap sampling),即對於m個樣本的原始訓練集,我們每次先隨機採集一個樣本放入採樣集,接着把該樣本放回,也就是說下次採樣時該樣本仍有可能被採集到,這樣採集m次,最終可以得到m個樣本的採樣集,由於是隨機採樣,這樣每次的採樣集是和原始訓練集不同的,和其他採樣集也是不同的,這樣得到多個不同的弱學習器。

  1. bagging 原理圖
    在這裏插入圖片描述
  2. bagging 代碼實現
# bagging.py
#
import numpy as np
from sklearn import ensemble, neighbors, datasets, preprocessing
from sklearn.model_selection import train_test_split

from sklearn.metrics import accuracy_score

np.random.RandomState(0)

# 加載數據
wine = datasets.load_wine()

# 劃分訓練集與測試集
x, y = wine.data, wine.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)

# 數據預處理
scaler = preprocessing.StandardScaler().fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)

# 創建模型
""" 
參數n_estimators:表示創建多少個同質模型
max_samples: 隨機採樣(自助採樣法)
max_features: 隨機選擇特徵
"""
clf = ensemble.BaggingClassifier(neighbors.KNeighborsClassifier(), n_estimators=10, max_samples=0.5, max_features=0.5)

# 模型擬合
clf.fit(x_train, y_train)

# 預測
y_pred = clf.predict(x_test)

# 評估
print(accuracy_score(y_test, y_pred))
  1. 隨機森林

隨機森林(Random Forest, 簡稱RF)是bagging的一個特化進階版,所謂的特化是因爲隨機森林的弱學習器都是決策樹。所謂的進階是隨機森林在bagging的樣本隨機採樣基礎上,又加上了特徵的隨機選擇,其基本思想沒有脫離bagging的範疇。

首先,RF使用了CART決策樹作爲弱學習器。第二,在使用決策樹的基礎上,RF對決策樹的建立做了改進,對於普通的決策樹,我們會在節點上所有的nn個樣本特徵中選擇一個最優的特徵來做決策樹的左右子樹劃分,但是RF通過隨機選擇節點上的一部分樣本特徵,這個數字小於nn,假設爲nsubn_{sub},然後在這些隨機選擇的nsubn_{sub}個樣本特徵中,選擇一個最優的特徵來做決策樹的左右子樹劃分。這樣進一步增強了模型的泛化能力。
除了上面兩點,RF和普通的bagging算法沒有什麼不同.

  1. 隨機森林代碼實現
# 隨機深林.py
#
import numpy as np
from sklearn import tree,ensemble, datasets, preprocessing
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

np.random.RandomState(0)

# 加載數據
wine = datasets.load_wine()

# 劃分訓練集與測試集
x, y = wine.data, wine.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)

# 數據預處理
scaler = preprocessing.StandardScaler().fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)

# 創建模型
clf = ensemble.RandomForestClassifier(n_estimators=25,max_depth=3)

# 模型擬合
clf.fit(x_train, y_train)

# 預測
y_pred = clf.predict(x_test)

# 評估
print(accuracy_score(y_test, y_pred))

# 查看特徵權重
print(wine.feature_names)
print(clf.feature_importances_)
  1. boosting 算法

Bagging一般使用強學習器,其個體學習器之間不存在強依賴關係,容易並行。Boosting則使用弱分類器,其個體學習器之間存在強依賴關係,是一種序列化方法。Bagging主要關注降低方差,而Boosting主要關注降低偏差。Boosting是一族算法,其主要目標爲將弱學習器“提升”爲強學習器,大部分Boosting算法都是根據前一個學習器的訓練效果對樣本分佈進行調整,再根據新的樣本分佈訓練下一個學習器,如此迭代M次,最後將一系列弱學習器組合成一個強學習器。而這些Boosting算法的不同點則主要體現在每輪樣本分佈的調整方式上。

*** AdaBoost後面單獨進行講解。

AdaBoost的具體流程爲先對每個樣本賦予相同的初始權重,每一輪學習器訓練過後都會根據其表現對每個樣本的權重進行調整,增加分錯樣本的權重,這樣先前做錯的樣本在後續就能得到更多關注,按這樣的過程重複訓練出M個學習器,最後進行加權組合

  1. adaboost代碼實現
# bagging.py
#
import numpy as np
from sklearn import ensemble, neighbors, datasets, preprocessing
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

np.random.RandomState(0)

# 加載數據
wine = datasets.load_wine()

# 劃分訓練集與測試集
x, y = wine.data, wine.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)

# 數據預處理
scaler = preprocessing.StandardScaler().fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)

# 創建模型
clf = ensemble.AdaBoostClassifier(n_estimators=50)

# 模型擬合
clf.fit(x_train, y_train)

# 預測
y_pred = clf.predict(x_test)

# 評估
print(accuracy_score(y_test, y_pred))
  1. Stacking 概述

Stacking 與 bagging 和 boosting 主要存在兩方面的差異。首先,Stacking
通常考慮的是異質弱學習器(不同的學習算法被組合在一起),而bagging 和 boosting
主要考慮的是同質弱學習器。其次,stacking 學習用元模型組合基礎模型,而bagging 和 boosting則根據確定性算法組合弱學習器。

  1. Stacking 原理

將訓練好的所有基模型對整個訓練集進行預測,第j個基模型對第i個訓練樣本的預測值將作爲新的訓練集中第i個樣本的第j個特徵值,最後基於新的訓練集進行訓練。同理,預測的過程也要先經過所有基模型的預測形成新的測試集,最後再對測試集進行預測:

在這裏插入圖片描述10. Stacking實現代碼
介紹一款功能強大的stacking利器,mlxtend庫,它可以很快地完成對sklearn模型地stacking。

from sklearn import datasets
 
iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target
 
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import StackingClassifier
import numpy as np
 
clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
lr = LogisticRegression()
sclf = StackingClassifier(classifiers=[clf1, clf2, clf3], 
                          meta_classifier=lr)
 
print('3-fold cross validation:\n')
 
for clf, label in zip([clf1, clf2, clf3, sclf], 
                      ['KNN', 
                       'Random Forest', 
                       'Naive Bayes',
                       'StackingClassifier']):
 
    scores = model_selection.cross_val_score(clf, X, y, 
                                              cv=3, scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]" 
          % (scores.mean(), scores.std(), label))
  1. GBRT算法
    *** 後面單獨對GBRT進行講解

Gradient Tree Boosting 或梯度提升迴歸樹(GBRT)是對於任意的可微損失函數的提升算法的泛化。 GBRT是一個準確高效的現有程序, 它既能用於分類問題也可以用於迴歸問題。梯度樹提升模型被應用 到各種領域,包括網頁搜索排名和生態領域。
GBRT 的優點: 對混合型數據的自然處理(異構特徵) 強大的預測能力 在輸出空間中對異常點的魯棒性(通過具有魯棒性的損失函數實現) Gradient
Boost與傳統的Boost有着很大的區別,它的每一次計算都是爲了減少上一次的殘差 (residual),而爲了減少這些殘差,可以在殘差減少的梯度(Gradient)方向上建立一個新模型。所以說, 在Gradient Boost中,每個新模型的建立是爲了使得先前模型殘差往梯度方向減少,與傳統的Boost算 法對正確、錯誤的樣本進行加權有着極大的區別。
它主要的思想是,每一次建立模型是在之前建立模型 損失函數的梯度下降方向。損失函數(loss function)描述的是模型的不靠譜程度,損失函數越大,則說明模型越容易出錯(其實這裏有一個方差、偏差均衡的問題,但是這裏假設損失函數越大,模型越容易出錯)。如果我們的模型能夠讓損失函數持續的下降,則說明我們的模型在不停的改進,而最好的方式就是讓損失函數在其梯度(Gradient)的方向上下降。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor
from sklearn import linear_model
from sklearn import ensemble
# Data set
x = np.array(list(range(1, 11))).reshape(-1, 1)
y = np.array([5.56, 5.70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05]).ravel()

# Fit regression model
"""分類"""
# model1 = ensemble.GradientBoostingClassifier(max_depth=1,n_estimators=20)

"""迴歸"""
model1 = ensemble.GradientBoostingRegressor(max_depth=1,n_estimators=20)
model1.fit(x, y)

# Predict
X_test = np.arange(0.0, 10.0, 0.01)[:, np.newaxis]
y_1 = model1.predict(X_test)

# Plot the results
plt.figure()
plt.scatter(x, y, s=20, edgecolor="black", c="darkorange", label="data")
plt.plot(X_test, y_1, color="cornflowerblue", label="max_depth=1", linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章