工具學(xué)習(xí) -python -04 Sklearn

借著別人的文章(王圣元 [王的機(jī)器] ),復(fù)盤一下python的基礎(chǔ)知識(shí)點(diǎn)。感謝原作者的分享!

Sklearn (全稱 Scikit-Learn) 是基于 Python 語言的機(jī)器學(xué)習(xí)工具。它建立在 NumPy, SciPy, Pandas 和 Matplotlib 之上,里面的 API 的設(shè)計(jì)非常好,所有對象的接口簡單,很適合新手上路。

在 Sklearn 里面有六大任務(wù)模塊:分別是分類、回歸、聚類、降維、模型選擇和預(yù)處理,如下圖從其官網(wǎng)的截屏。

image.png

要使用上述六大模塊的方法,可以用以下的偽代碼,注意 import 后面我用的都是一些通用名稱,如 SomeClassifier, SomeRegressor, SomeModel,具體化的名稱由具體問題而定,比如

  • SomeClassifier = RandomForestClassifier
  • SomeRegressor = LinearRegression
  • SomeModel = KMeans, PCA
  • SomeModel = GridSearchCV, OneHotEncoder
# 分類 (Classification)
from sklearn import SomeClassifier
from sklearn.linear_model import SomeClassifier
from sklearn.ensemble import SomeClassifier

# 回歸 (Regression)
from sklearn import SomeRegressor
from sklearn.linear_model import SomeRegressor
from sklearn.ensemble import SomeRegressor

# 聚類 (Clustering)
from sklearn.cluster import SomeModel

# 降維 (Dimensionality Reduction)
from sklearn.decomposition import SomeModel

# 模型選擇 (Model Selection)
from sklearn.model_selection import SomeModel

# 預(yù)處理 (Preprocessing)
from sklearn.preprocessing import SomeModel

SomeClassifier, SomeRegressor, SomeModel 其實(shí)都叫做估計(jì)器 (estimator),就像 Python 里「萬物皆對象」那樣,Sklearn 里「萬物皆估計(jì)器」。

此外,Sklearn 里面還有很多自帶數(shù)據(jù)集供,引入它們的偽代碼如下。

數(shù)據(jù)集 (Dataset)

from sklearn.datasets import SomeData

本文我們用以下思路來講解:

  • 第一章介紹機(jī)器學(xué)習(xí),從定義出發(fā)引出機(jī)器學(xué)習(xí)四要素:數(shù)據(jù)、任務(wù)、性能度量模型。加這一章的原因是不把機(jī)器學(xué)習(xí)相關(guān)概念弄清楚之后很難完全弄明白 Sklearn。

  • 第二章介紹 Sklearn,從其 API 設(shè)計(jì)原理出發(fā)分析其五大特點(diǎn):一致性、可檢驗(yàn)、標(biāo)準(zhǔn)類、可組合默認(rèn)值。最后再分析 Sklearn 里面自帶數(shù)據(jù)以及儲(chǔ)存格式。

  • 第三章介紹 Sklearn 里面的三大核心 API,包括估計(jì)器、預(yù)測器轉(zhuǎn)換器。這一章的內(nèi)容最重要,幾乎所有模型都會(huì)用到這三大 API。

  • 第四章介紹 Sklearn 里面的高級(jí) API,即元估計(jì)器,有可以大大簡化代碼量的流水線 (Pipeline 估計(jì)器),有集成模型 (Ensemble 估計(jì)器)、有多類別-多標(biāo)簽-多輸出分類模型 (Multiclass 和 Multioutput 估計(jì)器) 和模型選擇工具 (Model Selection 估計(jì)器)。


1 機(jī)器學(xué)習(xí)簡介

1.1 定義和組成元素

什么是機(jī)器學(xué)習(xí)?字面上來講就是 (人用) 計(jì)算機(jī)來學(xué)習(xí)。談起機(jī)器學(xué)習(xí)就一定要提起湯姆米切爾 (Tom M.Mitchell),就像談起音樂就會(huì)提起貝多芬,談起籃球就會(huì)提起邁克爾喬丹,談起電影就會(huì)提起萊昂納多迪卡普里奧。米切爾對機(jī)器學(xué)習(xí)定義的原話是:

A computer program is said to learn from experience E with respect to some class of tasks T and performance measure P if its performance at tasks in T, as measured by P, improves with experience E.
假設(shè)用性能度量 P 來評(píng)估機(jī)器在某類任務(wù) T 的性能,若該機(jī)器通利用經(jīng)驗(yàn) E 在任務(wù) T 中改善其性能 P,那么可以說機(jī)器對經(jīng)驗(yàn) E 進(jìn)行了學(xué)習(xí)。

在該定義中,除了核心詞機(jī)器和學(xué)習(xí),還有關(guān)鍵詞經(jīng)驗(yàn) E,性能度量 P 和任務(wù) T。在計(jì)算機(jī)系統(tǒng)中,通常經(jīng)驗(yàn) E 是以數(shù)據(jù) D 的形式存在,而機(jī)器學(xué)習(xí)就是給定不同的任務(wù) T 從數(shù)據(jù)中產(chǎn)生模型 M,模型 M 的好壞就用性能度量 P 來評(píng)估。

由上述機(jī)器學(xué)習(xí)的定義可知機(jī)器學(xué)習(xí)包含四個(gè)元素:
數(shù)據(jù) (Data),任務(wù) (Task),性能度量 (Quality Metric) 模型 (Model)

image.png

1.2 數(shù)據(jù)

數(shù)據(jù) (data) 是經(jīng)驗(yàn)的另一種說法,也是信息的載體。數(shù)據(jù)可分為

  1. 結(jié)構(gòu)化數(shù)據(jù)和非結(jié)構(gòu)化數(shù)據(jù) (按數(shù)據(jù)具體類型劃分)
  2. 原始數(shù)據(jù)和加工數(shù)據(jù) (按數(shù)據(jù)表達(dá)形式劃分)
  3. 樣本內(nèi)數(shù)據(jù)和樣本外數(shù)據(jù) (按數(shù)據(jù)統(tǒng)計(jì)性質(zhì)劃分)

在統(tǒng)計(jì)中,把研究對象的全體稱為總體 (population),而把組成總體的各個(gè)元素稱為個(gè)體,把從總體中抽取的若干個(gè)體稱為樣本 (sample)。舉個(gè)調(diào)查中國男性平均身高的例子:普查所有男性金錢花費(fèi)和時(shí)間成本太高,通常會(huì)抽取若干男性作為樣本,計(jì)算樣本里的男性平均身高作為總體里的所有男性平均身高的推理 (inference)。

統(tǒng)計(jì)學(xué)中做的事情就是用樣本數(shù)據(jù)的統(tǒng)計(jì) (statistics) 來推出總體數(shù)據(jù)的參數(shù) (parameter)。樣本數(shù)據(jù)也叫做樣本內(nèi)數(shù)據(jù),除樣本內(nèi)數(shù)據(jù)之外的總體數(shù)據(jù)叫做樣本外數(shù)據(jù)。

在機(jī)器學(xué)習(xí)中,樣本內(nèi)和樣本外數(shù)據(jù)的定義稍微有些不同
樣本內(nèi)數(shù)據(jù)是用來訓(xùn)練模型的數(shù)據(jù),也叫訓(xùn)練數(shù)據(jù)。它們是已知的,可計(jì)算統(tǒng)計(jì)的。樣本外數(shù)據(jù)是未來的沒見過的新數(shù)據(jù)。它們是未知的,不可計(jì)算統(tǒng)計(jì)的。

1.3 任務(wù)

根據(jù)學(xué)習(xí)的任務(wù)模式 (訓(xùn)練數(shù)據(jù)是否有標(biāo)簽),機(jī)器學(xué)習(xí)可分為四大類:

  1. 有監(jiān)督學(xué)習(xí) (有標(biāo)簽)
  2. 無監(jiān)督學(xué)習(xí) (無標(biāo)簽)
  3. 半監(jiān)督學(xué)習(xí) (有部分標(biāo)簽)
  4. 增強(qiáng)學(xué)習(xí) (有評(píng)級(jí)標(biāo)簽)

深度學(xué)習(xí)只是一種方法,而不是任務(wù)模式,因此與上面四類不屬于同一個(gè)維度,但是深度學(xué)習(xí)與它們可以疊加成:深度有監(jiān)督學(xué)習(xí)、深度非監(jiān)督學(xué)習(xí)、深度半監(jiān)督學(xué)習(xí)和深度增強(qiáng)學(xué)習(xí)。遷移學(xué)習(xí)也是一種方法,也可以分類為有監(jiān)督遷移學(xué)習(xí)、非監(jiān)督遷移學(xué)習(xí)、半監(jiān)督遷移學(xué)習(xí)和增強(qiáng)遷移學(xué)習(xí)。

1.4 性能度量

回歸和分類任務(wù)中最常見的誤差函數(shù)以及一些有用的性能度量如下。

image.png

除上述損失函數(shù)之外,分類任務(wù)還有很多其他有用的性能度量。

錯(cuò)誤率:分類錯(cuò)誤的樣本數(shù)占樣本總數(shù)的比例稱為錯(cuò)誤率 (error rate),相應(yīng)的分類正確的樣本數(shù)占樣本總數(shù)的比例稱為精度 (accuracy)。在 10 個(gè)樣本中有 2 個(gè)樣本分類錯(cuò)誤,則錯(cuò)誤率為 20%,而精度為 80%。

查準(zhǔn)率和查全率:錯(cuò)誤率和精度雖然常用,但是不能滿足所有任務(wù)需求。假定用訓(xùn)練好的模型預(yù)測騎士贏球,顯然,錯(cuò)誤率衡量了多少比賽實(shí)際是贏球但預(yù)測成輸球。但是若我們關(guān)心的是“預(yù)測出的比賽中有多少是贏球”,或“贏球的比賽中有多少被預(yù)測出了”,那么錯(cuò)誤率這個(gè)單一指標(biāo)顯然就不夠用了,這時(shí)需要引進(jìn)更為細(xì)分的性能度量,即查準(zhǔn)率 (precision) 和查全率 (recall)。

其他概念比如混淆矩陣、ROC、AUC 我們再下帖的實(shí)例用到時(shí)再細(xì)講。

1.5 模型

有監(jiān)督模型如下圖所示:

image.png

無監(jiān)督模型包括各種聚類分析 (KMeans, DBSCAN)、主成分分析 (PCA)、獨(dú)立成分分析 (ICA)、隱含狄利克雷分配 (LDA) 等等。


2 Sklearn 數(shù)據(jù)

Sklearn 和之前討論的 NumPy, SciPy, Pandas, Matplotlib 相似,就是一個(gè)處理特殊任務(wù)的包,Sklearn 就是處理機(jī)器學(xué)習(xí) (有監(jiān)督學(xué)習(xí)和無監(jiān)督學(xué)習(xí)) 的包,更精確的說,它里面有六個(gè)任務(wù)模塊和一個(gè)數(shù)據(jù)引入模塊

  • 有監(jiān)督學(xué)習(xí)的分類任務(wù)

  • 有監(jiān)督學(xué)習(xí)的回歸任務(wù)

  • 無監(jiān)督學(xué)習(xí)的聚類任務(wù)

  • 無監(jiān)督學(xué)習(xí)的降維任務(wù)

  • 數(shù)據(jù)預(yù)處理任務(wù)

  • 模型選擇任務(wù)

  • 數(shù)據(jù)引入

2.1 數(shù)據(jù)格式

在 Sklean 里,模型能即用的數(shù)據(jù)有兩種形式:

  1. Numpy 二維數(shù)組 (ndarray) 的稠密數(shù)據(jù) (dense data),通常都是這種格式。
  2. SciPy 矩陣 (scipy.sparse.matrix) 的稀疏數(shù)據(jù) (sparse data),比如文本分析每個(gè)單詞 (字典有 100000 個(gè)詞) 做獨(dú)熱編碼得到矩陣有很多 0,這時(shí)用 ndarray 就不合適了,太耗內(nèi)存。

上述數(shù)據(jù)在機(jī)器學(xué)習(xí)中通常用符號(hào) X 表示,是模型自變量。它的大小 = [樣本數(shù), 特征數(shù)]。有監(jiān)督學(xué)習(xí)除了需要特征 X 還需要標(biāo)簽 y,而 y 通常就是 Numpy 一維數(shù)組,無監(jiān)督學(xué)習(xí)沒有 y。

2.2 自帶數(shù)據(jù)集

Sklearn 里面有很多自帶數(shù)據(jù)集供用戶使用。來看看 Sklearn 三種引入數(shù)據(jù)形式。

打包好的數(shù)據(jù):對于小數(shù)據(jù)集,用 sklearn.datasets.load_*
分流下載數(shù)據(jù):對于大數(shù)據(jù)集,用 sklearn.datasets.fetch_*
隨機(jī)創(chuàng)建數(shù)據(jù):為了快速展示,用 sklearn.datasets.make_*


3 核心 API

Sklearn 里萬物皆估計(jì)器。估計(jì)器是個(gè)非常抽象的叫法,可把它不嚴(yán)謹(jǐn)?shù)漠?dāng)成一個(gè)模型 (用來回歸、分類、聚類、降維),或當(dāng)成一套流程 (預(yù)處理、網(wǎng)格最終)。

本節(jié)三大 API 其實(shí)都是估計(jì)器:

  1. 估計(jì)器 (estimator) 當(dāng)然是估計(jì)器
  2. 預(yù)測器 (predictor) 是具有預(yù)測功能的估計(jì)器
  3. 轉(zhuǎn)換器 (transformer) 是具有轉(zhuǎn)換功能的估計(jì)器

這三句看似廢話,其實(shí)蘊(yùn)藏了很多內(nèi)容。其實(shí)我對第 1 點(diǎn)這個(gè)估計(jì)器的起名不太滿意,我覺得應(yīng)該叫擬合器 (fitter) - 具有擬合功能的估計(jì)器??赐赀@一節(jié)你就會(huì)明白「擬合器」這種叫法更合理。

3.1 估計(jì)器

定義:任何可以基于數(shù)據(jù)集對一些參數(shù)進(jìn)行估計(jì)的對象都被稱為估計(jì)器。

兩個(gè)核心點(diǎn):1. 需要輸入數(shù)據(jù),2. 可以估計(jì)參數(shù)。估計(jì)器首先被創(chuàng)建,然后被擬合。

創(chuàng)建估計(jì)器:需要設(shè)置一組超參數(shù),比如

  • 線性回歸里超參數(shù) normalize=True
  • K 均值里超參數(shù) n_clusters=3

在創(chuàng)建好的估計(jì)器 model 可以直接訪問這些超參數(shù),用 . 符號(hào)。

  • model.normalize
  • model.n_clusters

但 model 中有很多超參數(shù),你不可能一開始都知道要設(shè)置什么值,沒設(shè)置的用 Sklearn 會(huì)給個(gè)合理的默認(rèn)值,因此新手不用擔(dān)心。

擬合估計(jì)器:需要訓(xùn)練集。

在有監(jiān)督學(xué)習(xí)中的代碼范式為:model.fit( X_train, y_train )
在無監(jiān)督學(xué)習(xí)中的代碼范式為:model.fit( X_train )

擬合之后可以訪問 model 里學(xué)到的參數(shù),比如線性回歸里的特征前的系數(shù) coef_,或 K 均值里聚類標(biāo)簽 labels_。

  • model.coef_
  • model.labels_

說了這么多抽象的東西,現(xiàn)在展示有監(jiān)督學(xué)習(xí)的「線性回歸」的具體例子。

線性回歸

# 首先從 sklearn 下的 linear_model 中引入 LinearRegression,再創(chuàng)建估計(jì)器起名 model,設(shè)置超參數(shù) normalize 為 **True**,指的在每個(gè)特征值上做標(biāo)準(zhǔn)化,這樣會(huì)加速數(shù)值運(yùn)算。

from sklearn.linear_model import LinearRegression

model = LinearRegression(normalize=True)

# 自己創(chuàng)建一個(gè)簡單數(shù)據(jù)集 (沒有噪聲完全線性) 只為了講解估計(jì)器里面的特征。
x = np.arange(10)
y = 2 * x + 1
plt.plot( x, y, 'o' )

# Sklearn 里模型要求特征 X 是個(gè)兩維變量么 (樣本數(shù)×特征數(shù))?但在本例中 X 是一維,因?yàn)槲覀冇?np.newaxis 加一個(gè)維度,它做的事情就是把 [1, 2, 3] 轉(zhuǎn)成 [[1],[2],[3]]。再把 X 和 y 丟進(jìn) fit() 函數(shù)來擬合線性模型的參數(shù)。
X = x[:, np.newaxis]
model.fit( X, y )

#擬合完后的估計(jì)器和創(chuàng)建完的樣子看起來一樣,但是已經(jīng)用「model.param_」可以訪問到學(xué)好的參數(shù)了,展示如下。
print( model.coef_ )
print( model.intercept_ )

3.2 預(yù)測器

定義:預(yù)測器在估計(jì)器上做了一個(gè)延展,延展出預(yù)測的功能。

兩個(gè)核心點(diǎn):1. 基于學(xué)到的參數(shù)預(yù)測,2. 預(yù)測有很多指標(biāo)。最常見的就是 predict() 函數(shù):

  • model.predict(X_test):評(píng)估模型在新數(shù)據(jù)上的表現(xiàn)

  • model.predict(X_train):確認(rèn)模型在老數(shù)據(jù)上的表現(xiàn)

舉個(gè)例子:

# 加載數(shù)據(jù)集
from sklearn.datasets import load_iris
iris = load_iris()

# 切分?jǐn)?shù)據(jù)集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split( iris['data'],  iris['target'], test_size=0.2 )

# 創(chuàng)建估計(jì)器
from sklearn.linear_model import LinearRegression
model = LinearRegression(solver = 'lbfgs')
# 擬合估計(jì)器
model.fit(X_train, y_train)

# 預(yù)測器
y_pred = model.predict( X_test )      #預(yù)測的類別
p_pred = model.predict_proba( X_test )      # 預(yù)測該類別的信心

預(yù)測器里還有額外的兩個(gè)函數(shù)可以使用。在分類問題中

score() 返回的是分類準(zhǔn)確率
decision_function() 返回的是每個(gè)樣例在每個(gè)類下的分?jǐn)?shù)值

print( model.score( X_test, y_test ) )
decision_score = model.decision_function( X_test )
print( decision_score )

小節(jié): 估計(jì)器都有 fit() 方法,預(yù)測器都有 predict() 和 score() 方法,言外之意不是每個(gè)預(yù)測器都有 predict_proba() 和 decision_function() 方法

3.3 轉(zhuǎn)換器

定義:轉(zhuǎn)換器也是一種估計(jì)器,兩者都帶擬合功能,但估計(jì)器做完擬合來預(yù)測,而轉(zhuǎn)換器做完擬合來轉(zhuǎn)換。

核心點(diǎn):估計(jì)器里 fit + predict,轉(zhuǎn)換器里 fit + transform。

本節(jié)介紹兩大類轉(zhuǎn)換器

  1. 將分類型變量 (categorical) 編碼成數(shù)值型變量 (numerical)
  2. 規(guī)范化 (normalize) 或標(biāo)準(zhǔn)化 (standardize) 數(shù)值型變量
3.3.1分類型變量編碼

LabelEncoder & OrdinalEncoder

LabelEncoder和 OrdinalEncoder 都可以將字符轉(zhuǎn)成數(shù)字,但是

  • LabelEncoder的輸入是一維,比如 1d ndarray

  • OrdinalEncoder 的輸入是二維,比如 DataFrame

# 首先給出要編碼的列表 enc 和要解碼的列表 dec。
enc = ['win','draw','lose','win']
dec = ['draw','draw','win']

# LabelEncoder編碼
# 從 sklearn 下的 preprocessing 中引入 LabelEncoder,再創(chuàng)建轉(zhuǎn)換器起名 LE。 
from sklearn.preprocessing import LabelEncoder
LE = LabelEncoder()

print( LE.fit(enc) )           --LabelEncoder()
print( LE.classes_ )           --['draw' 'lose' 'win']
print( LE.transform(dec) )     --[0 0 2]

# OrdinalEncoder編碼
# 從 sklearn 下的 preprocessing 中引入 OrdinalEncoder,再創(chuàng)建轉(zhuǎn)換器起名 OE
from sklearn.preprocessing import OrdinalEncoder
OE = OrdinalEncoder()

enc_DF = pd.DataFrame(enc)
dec_DF = pd.DataFrame(dec)

print( OE.fit(enc_DF) )           --OrdinalEncoder(categories='auto', dtype=<class 'numpy.float64'>)      
print( OE.categories_ )           --[array(['draw', 'lose', 'win'], dtype=object)]
print( OE.transform(dec_DF) )     --[[0.] [0.] [2.]]

OneHotEncoder

轉(zhuǎn)換器 OneHotEncoder 可以接受兩種類型的輸入:

  1. 用 LabelEncoder 編碼好的一維數(shù)組
  2. DataFrame
from sklearn.preprocessing import OneHotEncoder

# 1. 用 LabelEncoder 編碼好的一維數(shù)組 (元素為整數(shù)),重塑 成二維數(shù)組作為 OneHotEncoder 輸入。
OHE = OneHotEncoder()
num = LE.fit_transform( enc )
print( num )           --[2 0 1 2]
OHE_y = OHE.fit_transform( num.reshape(-1,1) )
OHE_y.toarray()     # 想看該矩陣?yán)锞唧w內(nèi)容,用 toarray() 函數(shù)。
--array([[0., 0., 1.],
       [1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

# 2. 用 DataFrame作為 OneHotEncoder 輸入
OHE = OneHotEncoder()
OHE.fit_transform( enc_DF ).toarray()
3.3.2特征縮放

數(shù)據(jù)要做的最重要的轉(zhuǎn)換之一是特征縮放 (feature scaling)。當(dāng)輸入的數(shù)值的量剛不同時(shí),機(jī)器學(xué)習(xí)算法的性能都不會(huì)好。具體來說,對于某個(gè)特征,我們有兩種方法:

  • 標(biāo)準(zhǔn)化 (standardization):每個(gè)維度的特征減去該特征均值,除以該維度的標(biāo)準(zhǔn)差。
  • 規(guī)范化 (normalization):每個(gè)維度的特征減去該特征最小值,除以該特征的最大值與最小值之差。

MinMaxScalerStandardScaler

整套轉(zhuǎn)換器「先創(chuàng)建再 fit 在 transform」的流程應(yīng)該很清楚了。自己讀下面代碼看看是不是秒懂。唯一需要注意的就是輸入 X 要求是兩維。

# MinMaxScaler
from sklearn.preprocessing import MinMaxScaler
X = np.array( [0, 0.5, 1, 1.5, 2, 100] )
X_scale = MinMaxScaler().fit_transform( X.reshape(-1,1) )

# StandardScaler
from sklearn.preprocessing import StandardScaler
X_scale = StandardScaler().fit_transform( X.reshape(-1,1) )

警示: fit() 函數(shù)只能作用在訓(xùn)練集上,千萬不要作用在測試集上,要不然你就犯了數(shù)據(jù)窺探的錯(cuò)誤了!拿標(biāo)準(zhǔn)化舉例,用訓(xùn)練集 fit 出來的均值標(biāo)準(zhǔn)差參數(shù),來對測試集做標(biāo)準(zhǔn)化。


4 高級(jí) API

Sklearn 里核心 API 接口是估計(jì)器,那高級(jí) API 接口就是元估計(jì)器 (meta-estimator),即由很多基估計(jì)器 (base estimator) 組合成的估計(jì)器。元估計(jì)器把估計(jì)器當(dāng)成參數(shù)。代碼范式大概如下:

meta_model( base_model )

本節(jié)討論五大元估計(jì)器,分別帶集成功能的 ensemble,多分類和多標(biāo)簽的 multiclass,多輸出的 multioutput,選擇模型的 model_selection,和流水線的 pipeline

1 ensemble.BaggingClassifier
2 ensemble.VotingClassifier
3 multiclass.OneVsOneClassifier
4 multiclass.OneVsRestClassifier
5 multioutput.MultiOutputClassifier
6 model_selection.GridSearchCV
7 model_selection.RandomizedSearchCV
8 pipeline.Pipeline

在下面五節(jié),我們會(huì)用的鳶尾花數(shù)據(jù) iris 和數(shù)字?jǐn)?shù)據(jù) digits,還有一些自己創(chuàng)建的數(shù)據(jù)。

4.1 Ensemble 估計(jì)器

Ensemble 估計(jì)器是用來做集成學(xué)習(xí),該估計(jì)器里面有若干個(gè)分類器 (classifier) 或回歸器 (regressor)。

最常用的 Ensemble 估計(jì)器排列如下:

  • AdaBoostClassifier: 逐步提升分類器
  • AdaBoostRegressor: 逐步提升回歸器
  • BaggingClassifier: 裝袋分類器
  • BaggingRegressor: 裝袋回歸器
  • GradientBoostingClassifier: 梯度提升分類器
  • GradientBoostingRegressor: 梯度提升回歸器
  • RandomForestClassifier: 隨機(jī)森林分類器
  • RandomForestRegressor: 隨機(jī)森林回歸器
  • VotingClassifier: 投票分類器
  • VotingRegressor: 投票回歸器

我們用鳶尾花數(shù)據(jù) iris,拿

同質(zhì)估計(jì)器 RandomForestClassifier
異質(zhì)估計(jì)器 VotingClassifier

來舉例。首先將數(shù)據(jù)分成 80:20 的訓(xùn)練集和測試集,并引入 metrics 來計(jì)算各種性能指標(biāo)。

from sklearn.datasets import load_iris
iris = load_iris()
from sklearn.model_selection import train_test_split
from sklearn import metrics

X_train, X_test, y_train, y_test = train_test_split( iris['data'],  iris['target'], test_size=0.2 )```

RandomForestClassifier

隨機(jī)森林 (random forest) 是決策樹 (decision tree) 的一種集成模型,每棵決策樹處理的數(shù)據(jù)用裝袋法 (bagging) 生成。隨機(jī)森林可以減小預(yù)測的方差,并且可以評(píng)估特征重要性。

from sklearn.ensemble import RandomForestClassifier

# 4 棵決策樹 (森林由樹組成);此外每棵樹的最大樹深為 5
RF = RandomForestClassifier( n_estimators=4, max_depth=5 )
RF.fit( X_train, y_train )

# 擬合 RF 完再做預(yù)測
print ( "RF - Accuracy (Train):  %.4g" %  metrics.accuracy_score(y_train, RF.predict(X_train)) )
--RF - Accuracy (Train): 0.9833
print ( "RF - Accuracy (Test):  %.4g" % metrics.accuracy_score(y_test, RF.predict(X_test)) )
--RF - Accuracy (Test): 1

print( RF.n_estimators )      --4
RF.estimators_
image.png

VotingClassifier

和隨機(jī)森林由同質(zhì)分類器「決策樹」不同,投票分類器由若干個(gè)異質(zhì)分類器組成。下例用 VotingClassifier 建立個(gè)含有對率回歸 (LR)、隨機(jī)森林 (RF) 和高斯樸素貝葉斯 (GNB) 三個(gè)分類器的集成模型。

RandomForestClassifier 的基分類器只能是決策樹,因此只用通過控制 n_estimators 超參數(shù)來決定樹的個(gè)數(shù),而 VotingClassifier 的基分類器要實(shí)實(shí)在在的輸入其本身

from sklearn.linear_model import LinearRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier

LR = LinearRegression(solver= 'lbfgs', multi_class='multinomial')
RF = RandomForestClassifier( n_estimators=5)
GNB = GaussianNB()

Ensemble = VotingClassifier(estimators = [('lr', LR), ('rf', RF), 
                           ('gnb', GNB)], voting='hard' )

Ensemble.fit( X_train, y_train )

print( len(Ensemble.estimators_) )
Ensemble.estimators_
image.png

比較元估計(jì)器和它三個(gè)組成元素的表現(xiàn)。還是集成后的 Ensemble 表現(xiàn)最好。

LR.fit( X_train, y_train )
RF.fit( X_train, y_train )
GNB.fit( X_train, y_train )
image.png
LR - Accuracy (Train): 0.975
RF - Accuracy (Train): 0.9833
GNB - Accuracy (Train): 0.95
Ensemble - Accuracy (Train): 0.9833

LR - Accuracy (Test): 1
RF - Accuracy (Test): 1
GNB - Accuracy (Test): 1
Ensemble - Accuracy (Test): 1

4.2 Multiclass 估計(jì)器

sklearn.multiclass 可以處理多類別 (multi-class) 的多標(biāo)簽 (multi-label) 的分類問題。

從小節(jié) 4.2 到 4.4,我們都會(huì)使用數(shù)字?jǐn)?shù)據(jù)集 digits。首先將數(shù)據(jù)分成 80:20 的訓(xùn)練集和測試集。

from sklearn.datasets import load_digits

digits = load_digits()
digits.keys()

X_train, X_test, y_train, y_test 
= train_test_split( digits['data'],
                    digits['target'],
                    test_size=0.2 )

4.2.1 多類別分類

手寫數(shù)字有 0-9 十類,但手頭上只有兩分類估計(jì)器 (比如像支撐向量機(jī)) 怎么用呢?我們可以采取下面三種常見策略:

  • 一對一 (One vs One, OvO):一個(gè)分類器用來處理數(shù)字 0 和數(shù)字 1,一個(gè)用來處理數(shù)字 0 和數(shù)字 2,一個(gè)用來處理數(shù)字 1 和 2,以此類推。N 個(gè)類需要 N(N-1)/2 個(gè)分類器。

  • 一對其他 (One vs All, OvA):訓(xùn)練 10 個(gè)二分類器,每一個(gè)對應(yīng)一個(gè)數(shù)字,第一個(gè)分類 1 和「非1」,第二個(gè)分類 2 和「非2」,以此類推。N 個(gè)類需要 N 個(gè)分類器。

OneVsOneClassifier

image.png

print( len(ovo_lr.estimators_) )
ovo_lr.estimators
image.png

OneVsRestClassifier

image.png

print( len(ova_lr.estimators_) )
ova_lr.estimators_

image.png
4.2.2 多標(biāo)簽分類

為了闡明「多標(biāo)簽分類」的原理。在手寫數(shù)字的例子上,我們特意為每個(gè)數(shù)字設(shè)計(jì)了多標(biāo)簽:

  • 標(biāo)簽 1 - 奇數(shù)、偶數(shù)

  • 標(biāo)簽 2 - 小于等于 4,大于 4

再建立多標(biāo)簽 y_train_multilabel,代碼如下 (OneVsRestClassifier 也可以用來做多標(biāo)簽分類):

from sklearn.multiclass import OneVsRestClassifier

y_train_multilabel = np.c_[ y_train%2==0, y_train<=4 ]
print(y_train_multilabel)      --[[ True True] [False False] [False False] ... [False False] [False False] [False False]]

訓(xùn)練模型,只不過這時(shí)用的是 y_train_multilabel。

image.png
print( len(ova_ml.estimators_) )
ova_ml.estimators_
image.png

4.3 Multioutput 估計(jì)器*

sklearn.multioutput 可以處理多輸出 (multi-output) 的分類問題。

Multioutput 估計(jì)器有兩個(gè):

  • MultiOutputRegressor: 多輸出回歸

  • MultiOutputClassifier: 多輸出分類

本節(jié)只關(guān)注多輸出分類。

MultiOutputClassifier

首先引入 MultiOutputClassifier 和 RandomForestClassifier。你看,這兩個(gè)都是元估計(jì)器,因此在 Sklearn 里面估計(jì)器可以隨意組合。

from sklearn.multioutput import MultiOutputClassifier
from sklearn.ensemble import RandomForestClassifier

在手寫數(shù)字的例子上,我們也為特意每個(gè)數(shù)字設(shè)計(jì)了多標(biāo)簽而且每個(gè)標(biāo)簽的類別都大于二。

  • 標(biāo)簽 1 - 小于等于 4,4 和 7 之間,大于等于 7 (三類)
  • 標(biāo)簽 2 - 數(shù)字本身 (十類)

代碼如下:

from sklearn.multioutput import MultiOutputClassifier
from sklearn.ensemble import RandomForestClassifier
用含有 100 棵決策樹的隨機(jī)森林來解決這個(gè)多輸入分類問題。

image.png
# 這個(gè)模型在測試集前五張照片上的預(yù)測。
MO.predict( X_test[:5,:] )
--array([[0, 2],
       [0, 2],
       [0, 0],
       [2, 9],
       [1, 5]])


# 真實(shí)標(biāo)簽
y_test_1st = y_test.copy()
y_test_1st[ y_test<=4 ] = 0
y_test_1st[ np.logical_and(y_test>4, y_test<7) ] = 1
y_test_1st[ y_test>=7 ] = 2

y_test_multioutput 
= np.c_[ y_test_1st, y_test ]

y_test_multioutput[:5]
--array([[0, 2],
       [0, 2],
       [0, 0],
       [2, 9],
       [1, 5]]

4.4 Model Selection 估計(jì)器

模型選擇 (Model Selction) 在機(jī)器學(xué)習(xí)非常重要,它主要用于評(píng)估模型表現(xiàn),常見的 Model Selection 估計(jì)器有以下幾個(gè):

  • cross_validate: 評(píng)估交叉驗(yàn)證的表現(xiàn)。

  • learning_curve: 建立學(xué)習(xí)曲線。

  • GridSearchCV: 用交叉驗(yàn)證從網(wǎng)格中一組超參數(shù)搜索出最佳超參數(shù)。

  • RandomizedSearchCV: 用交叉驗(yàn)證從一組隨機(jī)超參數(shù)搜索出最佳超參數(shù)。

本小節(jié)關(guān)注調(diào)節(jié)超參數(shù)的兩個(gè)估計(jì)器,即上面列出的最后兩個(gè)。它們都要用到交叉驗(yàn)證,我們來看這兩個(gè)調(diào)參的估計(jì)器,網(wǎng)格追蹤和隨機(jī)追蹤。

網(wǎng)格追蹤參數(shù) 1 在 [1, 10, 100, 1000] 中取值,**參數(shù) 2 **在 [0.01, 0.1, 1 10] 中取值,注意并不是等間距取值。模型在所有 16 個(gè)組合跑,選取一對對應(yīng)最小交叉驗(yàn)證誤差的參數(shù)。

隨機(jī)追蹤:根據(jù)指定分布隨機(jī)搜索,可以選擇獨(dú)立于參數(shù)個(gè)數(shù),比如 log(參數(shù) 1) 服從 0 到 3 的均勻分布, log(參數(shù) 2) 服從 -2 到 1 的均勻分布。此外,會(huì)設(shè)定一個(gè)預(yù)算參數(shù)。

原理講清楚了,看代碼吧。


image.png

4.5 Pipeline 估計(jì)器

Pipeline 估計(jì)器又叫流水線,把各種估計(jì)器串聯(lián) (Pipeline) 或并聯(lián) (FeatureUnion) 的方式組成一條龍服務(wù)。用好了它真的能大大提高效率。

4.5.1 Pipeline

Pipeline 將若干個(gè)估計(jì)器按順序連在一起,比如

特征提取 -> 降維 -> 擬合 -> 預(yù)測

在整個(gè) Pipeline 中,它的屬性永遠(yuǎn)和最后一個(gè)估計(jì)器屬性一樣

  • 如果最后一個(gè)估計(jì)器是預(yù)測器,那么 Pipeline 是預(yù)測器

  • 如果最后一個(gè)估計(jì)器是轉(zhuǎn)換器,那么 Pipeline 是轉(zhuǎn)換器

下面用一個(gè)簡單例子來說明如果用 Pipeline 來做「先填補(bǔ)缺失值-再標(biāo)準(zhǔn)化」這兩步的。先生成含缺失值 NaN 的數(shù)據(jù) X。

image.png

首先引入 Pipeline,再引入

  • 處理缺失值的轉(zhuǎn)換器 SimpleImputer

  • 做規(guī)劃化的轉(zhuǎn)換器 MinMaxScaler

image.png

由于最后一個(gè)估計(jì)器是轉(zhuǎn)換器,因此 pipe 也是個(gè)轉(zhuǎn)換器。寫好了就可以那它來做「先填補(bǔ)缺失值-再標(biāo)準(zhǔn)化」的重復(fù)工作了。

看看運(yùn)行結(jié)果,值都被填滿了,而且兩列也被標(biāo)準(zhǔn)化了。

image.png
4.5.2 FeatureUnion

如果我們想在一個(gè)節(jié)點(diǎn)同時(shí)運(yùn)行幾個(gè)估計(jì)器,我們可用 FeatureUnion。下例首先建立一個(gè) DataFrame,

  • 前兩列智力 IQ 和脾氣 temper 都是分類型變量

  • 后兩列收入 income 和身高 height 都是數(shù)值型變量

  • 每列中都有缺失值

image.png

image.png
image.gif

我們現(xiàn)在按下列步驟來清洗數(shù)據(jù)。

  • 對分類型變量:獲取 -> 中位數(shù)填充 -> 獨(dú)熱編碼

  • 對數(shù)值型變量:獲取 -> 均值填充 -> 標(biāo)準(zhǔn)化

上面兩步是平行進(jìn)行的。

首先我們自己定義一個(gè)從 DataFrame 里面獲取每列的類,起名叫 DataFrameSelector。

image.png

接下來建立一個(gè)流水線 full_pipe,它并聯(lián)著兩個(gè)流水線

  • categorical_pipe 處理分類型變量
    DataFrameSelector 用來獲取
    SimpleImputer 用出現(xiàn)最多的值來填充 None
    OneHotEncoder 來編碼返回非稀疏矩陣
  • numeric_pipe 處理數(shù)值型變量
    DataFrameSelector 用來獲取
    SimpleImputer 用均值來填充 NaN
    normalize 來規(guī)范化數(shù)值

下面代碼非常漂亮。

image.png

將結(jié)果打印出來,齊活!

X_proc = full_pipe.fit_transform( X )
print( X_proc )

5 總結(jié)

結(jié)合本帖講的總結(jié)一套機(jī)器學(xué)習(xí)的初級(jí)框架:

確定任務(wù):是「有監(jiān)督」的分類或回歸?還是「無監(jiān)督」的聚類或降維?確定好后基本就能知道用 Sklearn 里哪些模型了。

數(shù)據(jù)預(yù)處理:這步最繁瑣,要處理缺失值、異常值;要編碼分類型變量;要正規(guī)化或標(biāo)準(zhǔn)化數(shù)值型變量,等等。但是有了 Pipeline 神器一切變得簡單高效。

訓(xùn)練和評(píng)估:這步最簡單,訓(xùn)練用估計(jì)器 fit() 先擬合,評(píng)估用預(yù)測器 predict() 來評(píng)估。

選擇模型:啟動(dòng) Model Selection 估計(jì)器里的 GridSearchCV 和 RandomizedSearchCV,選擇得分最高的那組超參數(shù) (即模型)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容