Sklearn (全稱 Scikit-Learn) 是基於 Python 語言的機器學習工具。它建立在 NumPy, SciPy, Pandas 和 Matplotlib 之上,裡面的 API 的設計非常好,所有對象的接口簡單,很適合新手上路。
在 Sklearn 裡面有六大任務模塊:分別是分類、回歸、聚類、降維、模型選擇和預處理,如下圖從其官網的截屏。
要使用上述六大模塊的方法,可以用以下的偽代碼,注意 import 後面我用的都是一些通用名稱,如 SomeClassifier, SomeRegressor, SomeModel,具體化的名稱由具體問題而定,比如
SomeClassifier = RandomForestClassifier
SomeRegressor = LinearRegression
SomeModel = KMeans, PCA
SomeModel = GridSearchCV, OneHotEncoder
上面具體化的例子分別是隨機森林分類器、線性回歸器、K 均值聚類、主成分分析、網格追蹤法、獨熱編碼。
from sklearn import SomeClassifierfrom sklearn.linear_model import SomeClassifierfrom sklearn.ensemble import SomeClassifierfrom sklearn import SomeRegressorfrom sklearn.linear_model import SomeRegressorfrom sklearn.ensemble import SomeRegressorfrom sklearn.cluster import SomeModel降維 (Dimensionality Reduction)from sklearn.decomposition import SomeModelfrom sklearn.model_selection import SomeModelfrom sklearn.preprocessing import SomeModelSomeClassifier, SomeRegressor, SomeModel 其實都叫做估計器 (estimator),就像 Python 裡「萬物皆對象」那樣,Sklearn 裡「萬物皆估計器」。
此外,Sklearn 裡面還有很多自帶數據集供,引入它們的偽代碼如下。
from sklearn.datasets import SomeData本貼我們用以下思路來講解:
第一章介紹機器學習,從定義出發引出機器學習四要素:數據、任務、性能度量和模型。加這一章的原因是不把機器學習相關概念弄清楚之後很難完全弄明白 Sklearn。
第二章介紹 Sklearn,從其 API 設計原理出發分析其五大特點:一致性、可檢驗、標準類、可組合和默認值。最後再分析 Sklearn 裡面自帶數據以及儲存格式。
第三章介紹 Sklearn 裡面的三大核心 API,包括估計器、預測器和轉換器。這一章的內容最重要,幾乎所有模型都會用到這三大 API。
第四章介紹 Sklearn 裡面的高級 API,即元估計器,有可以大大簡化代碼量的流水線 (Pipeline 估計器),有集成模型 (Ensemble 估計器)、有多類別-多標籤-多輸出分類模型 (Multiclass 和 Multioutput 估計器) 和模型選擇工具 (Model Selection 估計器)。
本帖目錄如下:
第一章 - 機器學習簡介
1.1 定義和組成元素
1.2 數據
1.3 任務
1.4 性能指標
1.5 模型
第二章 - Sklearn 數據
2.1 數據格式
2.2 自帶數據集
第三章 - 核心 API
3.1 估計器
3.2 預測器
3.3 轉換器
第四章 - 高級 API
4.1 Ensemble 估計器
4.2 Multiclass 估計器
4.3 Multioutput 估計器
4.4 Model Selection 估計器
4.5 Pipeline 估計器
總結
很多介紹 Sklearn 的文章是不會像我這麼詳細介紹「機器學習」裡的概念的,但是不弄清出這些概念或術語,學 Sklearn 只是走馬觀花,只看到表面,抓不到實質。
建議認真仔細讀第一章!
建議認真仔細讀第一章!
建議認真仔細讀第一章!
什麼是機器學習?字面上來講就是 (人用) 計算機來學習。談起機器學習就一定要提起湯姆米切爾 (Tom M.Mitchell),就像談起音樂就會提起貝多芬,談起籃球就會提起麥可喬丹,談起電影就會提起萊昂納多迪卡普裡奧。米切爾對機器學習定義的原話是:
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.
整段英文有點抽象難懂對嗎?首先注意到兩個詞 computer program 和 learn,翻譯成中文就是機器 (電腦程式) 和學習,再把上面英譯中:
假設用性能度量 P 來評估機器在某類任務 T 的性能,若該機器通利用經驗 E 在任務 T 中改善其性能 P,那麼可以說機器對經驗 E 進行了學習。
在該定義中,除了核心詞機器和學習,還有關鍵詞經驗 E,性能度量 P 和任務 T。在計算機系統中,通常經驗 E 是以數據 D 的形式存在,而機器學習就是給定不同的任務 T 從數據中產生模型 M,模型 M 的好壞就用性能度量 P 來評估。
由上述機器學習的定義可知機器學習包含四個元素
數據 (Data)
任務 (Task)
性能度量 (Quality Metric)
模型 (Model)
下面四小節分別介紹數據、任務、性能度量和模型。
數據 (data) 是經驗的另一種說法,也是信息的載體。數據可分為
結構化數據和非結構化數據 (按數據具體類型劃分)
原始數據和加工數據 (按數據表達形式劃分)
樣本內數據和樣本外數據 (按數據統計性質劃分)
結構化數據 (structured data) 是由二維表結構來邏輯表達和實現的數據。非結構化數據是沒有預定義的數據,不便用資料庫二維表來表現的數據。
非結構化數據包括圖片,文字,語音和視屏等如下圖。
對於以上的非結構數據,相關應用實例有
深度學習的卷積神經網絡 (convolutional neural network, CNN) 對圖像數據做人臉識別或物體分類
深度學習的循環神經網絡 (recurrent neural network, RNN) 對語音數據做語音識別或機器對話,對文字數據做文本生成或閱讀理解
增強學習的阿爾法狗 (AlphaGo) 對棋譜數據學習無數遍最終打敗了圍棋世界冠軍李世石和柯潔
計算機追根到底還是只能最有效率的處理數值型的結構化數據,如何從原始數據加工成計算機可應用的數據會在後面講明。
機器學習模型主要使用的是結構化數據,即二維的數據表。非結構化數據可以轉換成結構化數據,比如把
圖像類數據裡像素張量重塑成一維數組
文本類數據用獨熱編碼轉成二維數組
對於結構化數據,我們用勒布朗詹姆斯 (Lebron James) 四場比賽的數據舉例。
下面術語大家在深入了解機器學習前一定要弄清楚:
每行的記錄 (這是一場比賽詹姆斯的個人統計) ,稱為一個示例 (instance)
反映對象在某方面的性質,例如得分,籃板,助攻,稱為特徵 (feature) 或輸入(input)
特徵上的取值,例如「示例 1」對應的 27, 10, 12 稱為特徵值 (feature value)
關於示例結果的信息,例如贏,稱為標籤 (label) 或輸出 (output)
包含標籤信息的示例,則稱為樣例 (example),即樣例 = (特徵, 標籤)
從數據中學得模型的過程稱為學習 (learning) 或訓練 (training)
在訓練數據中,每個樣例稱為訓練樣例 (training example),整個集合稱為訓練集(training set)
計算機處理數值型的結構型數據最有效率,但是現實世界到處出是原始數據,分為兩類
非結構數據比如圖片和文字型數據 (情況一)
結構型數據的分類型變量 (情況二)
拿情況一的圖片為例,通過特定函數 imread 將彩色圖片用 RGB 像素表示出來,再按紅綠藍的順序,將所有像素排成一個數值列向量 (column vector),而計算機可以接受這樣的輸入。具體轉換過程見下圖。
推特 (twitter) 的每條推文 (tweet) 規定只能發 280 個字符。在編碼推文時,將 280 個字符的序列用獨熱編碼 (one-hot encoding) 到包含 128 個字符的 ASCII 表,如下所示。
這樣,每條推文都可以編碼為 2 維張量形狀 (280, 128),比如一條 tweet 是 「I love python :)」,這句話映射到 ASCII 表變成:
如果收集到 1 百萬條推文,那麼整個數據集的形狀為 (1000000, 280, 128)。傳統機器學習的對率回歸可以來做情感分析。
籃球比賽結果非輸即贏,是一個二類 (binary class) 變量
二類變量用「0-1編碼」,比如比賽結果= {贏, 輸} 表示成 y= [1 0 0 1],1 代表贏,0 代表輸。
而足球比賽結果是有贏、平、輸三種,是一個多類 (multi-class) 變量。
多類變量分別用 0, 1, 2 來表示,那麼 y = [0 1 0 2]。但更常見的是用獨熱編碼 (one-hot encoding),即
在統計中,把研究對象的全體稱為總體 (population),而把組成總體的各個元素稱為個體,把從總體中抽取的若干個體稱為樣本 (sample)。
舉個調查中國男性平均身高的例子:
普查所有男性金錢花費和時間成本太高,通常會抽取若干男性作為樣本,計算樣本裡的男性平均身高作為總體裡的所有男性平均身高的推理 (inference)。
統計學中做的事情就是用樣本數據的統計 (statistics) 來推出總體數據的參數 (parameter)。樣本數據也叫做樣本內數據,除樣本內數據之外的總體數據叫做樣本外數據。
在機器學習中,樣本內和樣本外數據的定義稍微有些不同,如下圖:
樣本內數據是用來訓練模型的數據,也叫訓練數據。它們是已知的,可計算統計的。
樣本外數據是未來的沒見過的新數據。它們是未知的,不可計算統計的。
機器學習在樣本內數據訓練模型用來預測:
機器學習的難點就是如何用好的樣本內預測來保證好的樣本外預測,幸運的是我們有〖計算學習理論〗來保證它。
根據學習的任務模式 (訓練數據是否有標籤),機器學習可分為四大類:
有監督學習 (有標籤)
無監督學習 (無標籤)
半監督學習 (有部分標籤)
增強學習 (有評級標籤)
深度學習只是一種方法,而不是任務模式,因此與上面四類不屬於同一個維度,但是深度學習與它們可以疊加成:深度有監督學習、深度非監督學習、深度半監督學習和深度增強學習。遷移學習也是一種方法,也可以分類為有監督遷移學習、非監督遷移學習、半監督遷移學習和增強遷移學習。
下圖畫出機器學習各類之間的關係。
由於 Sklearn 裡面模型主要處理「有監督學習」和「無監督學習」兩類,我們接下來也只討論這兩類。
有監督學習 (supervised learning) 利用輸入數據及其對應標籤來訓練模型。這種學習方法類似學生通過研究問題和參考答案來學習,在掌握問題和答案之間的對應關係後,學生可自己給出相似新問題的答案了。
在有監督學習中,數據 = (特徵,標籤),而其主要任務是分類和回歸。以上述詹姆斯的個人統計為例。
如果預測的是離散值 (discrete value),例如比賽結果贏或輸,此類學習任務稱為分類 (classification)。
如果預測的是連續值 (continuous value),例如詹姆斯效率 65.1, 70.3 等等,此類學習任務稱為回歸 (regression)。
無監督學習 (unsupervised learning) 是找出輸入數據的模式。比如,它可以根據電影的各種特徵做聚類,用這種方法收集數據為電影推薦系統提供標籤。此外無監督學習還可以降低數據的維度,它可以幫助我們更好的理解數據。
在無監督學習中,數據 = (特徵,)。
除了根據詹姆斯個人統計來預測騎士隊輸贏或者個人效率值外,我們還可以對該數據做聚類 (clustering),即將訓練集中的數據分成若干組,每組成為一個簇 (cluster)。
假設聚類方法將數據聚成二個簇 A 和 B,如下圖
後來發現簇 A 代表贏,簇 B 代表輸。聚類的用處就是可以找到一個潛在的原因來解釋為什麼樣例 1 和 3 可以贏球。難道真的是只要詹姆斯三雙就可以贏球?
註:下面對降維的理解不是那麼嚴謹,只為了讓小白對降維大概有個概念。
詹姆斯完整統計數據還有搶斷、蓋帽和犯規,但這些對預測比賽輸贏、效率值都沒什麼用,因此可以通過降維的方法將其去除。
回歸和分類任務中最常見的誤差函數以及一些有用的性能度量如下。
回歸任務的誤差函數估量在數據集 D 上模型的連續型預測值 h(x) 與連續型真實值 y 的距離,h(x) 和 y 可以取任意實數。誤差函數是一個非負實值函數,通常使用 ED[h] 來表示。圖表展示如下。
分類任務的誤差函數估量在數據集 D 上模型的離散型預測值 h(x) 與離散型真實值 y 的不一致程度,慣例是 y 和 h(x) 取±1,比如正類取 1 負類取 -1。圖表展示如下。
除上述損失函數之外,分類任務還有很多其他有用的性能度量。
錯誤率:分類錯誤的樣本數佔樣本總數的比例稱為錯誤率 (error rate),相應的分類正確的樣本數佔樣本總數的比例稱為精度 (accuracy)。在 10 個樣本中有 2 個樣本分類錯誤,則錯誤率為 20%,而精度為 80%。
查準率和查全率:錯誤率和精度雖然常用,但是不能滿足所有任務需求。假定用訓練好的模型預測騎士贏球,顯然,錯誤率衡量了多少比賽實際是贏球但預測成輸球。但是若我們關心的是「預測出的比賽中有多少是贏球」,或「贏球的比賽中有多少被預測出了」,那麼錯誤率這個單一指標顯然就不夠用了,這時需要引進更為細分的性能度量,即查準率 (precision) 和查全率 (recall)。
其他概念比如混淆矩陣、ROC、AUC 我們再下帖的實例用到時再細講。
有監督模型如下圖所示:
無監督模型包括各種聚類分析 (KMeans, DBSCAN)、主成分分析 (PCA)、獨立成分分析 (ICA)、隱含狄利克雷分配 (LDA) 等等。
如要了解更多機器學習的細節,請參考本帖次條的〖機器學習帖子匯總〗,裡面是我寫的所有關於「有監督學習」的內容。
費了這麼多時間來介紹機器學習,無非就是讓大家在使用 Sklearn 時知道自己在做什麼,知道那些概念在說什麼就夠了。
Sklearn 和之前討論的 NumPy, SciPy, Pandas, Matplotlib 相似,就是一個處理特殊任務的包,Sklearn 就是處理機器學習 (有監督學習和無監督學習) 的包,更精確的說,它裡面有六個任務模塊和一個數據引入模塊:
有監督學習的分類任務
有監督學習的回歸任務
無監督學習的聚類任務
無監督學習的降維任務
數據預處理任務
模型選擇任務
數據引入
本節就來看看 Sklearn 裡數據格式和自帶數據集。
在 Sklean 裡,模型能即用的數據有兩種形式:
Numpy 二維數組 (ndarray) 的稠密數據 (dense data),通常都是這種格式。
SciPy 矩陣 (scipy.sparse.matrix) 的稀疏數據 (sparse data),比如文本分析每個單詞 (字典有 100000 個詞) 做獨熱編碼得到矩陣有很多 0,這時用 ndarray 就不合適了,太耗內存。
上述數據在機器學習中通常用符號 X 表示,是模型自變量。它的大小 = [樣本數, 特徵數],圖下圖所示。該房屋數據有 21000 條包括平方英尺,臥室數,樓層,日期,翻新年份等等 21 欄。該數據形狀為 [21000, 21]
有監督學習除了需要特徵 X 還需要標籤 y,而 y 通常就是 Numpy 一維數組,無監督學習沒有 y。
Sklearn 裡面有很多自帶數據集供用戶使用。
還記得〖統計可視化之 Seaborn〗一貼裡鳶尾花的數據集嗎?
數據集包括 150 條鳶尾花的四個特徵 (萼片長/寬和花瓣長/寬) 和三個類別。在盤 Seaborn 時是從 csv 文件讀取的,本帖從 Sklearn 裡面的 datasets 模塊中引入,代碼如下:
from sklearn.datasets import load_irisiris = load_iris()數據是以「字典」格式存儲的,看看 iris 的鍵有哪些。
dict_keys(['data', 'target',
'target_names', 'DESCR',
'feature_names', 'filename'])鍵裡面的名稱解釋如下:
data:特徵值 (數組)
target:標籤值 (數組)
target_names:標籤 (列表)
DESCR:數據集描述
feature_names:特徵 (列表)
filename:iris.csv 文件路徑
具體感受一下 iris 數據中特徵的大小、名稱和前五個示例。
n_samples, n_features = iris.data.shapeprint((n_samples, n_features))print(iris.feature_names)iris.data[0:5](150, 4)
['sepal length (cm)', 'sepal width (cm)',
'petal length (cm)', 'petal width (cm)']
array([[5.1, 3.5, 1.4, 0.2],
[4.9, 3. , 1.4, 0.2],
[4.7, 3.2, 1.3, 0.2],
[4.6, 3.1, 1.5, 0.2],
[5. , 3.6, 1.4, 0.2]])150 個樣本,4 個特徵,沒毛病!再感受一下標籤的大小、名稱和全部示例。
print(iris.target.shape)print(iris.target_names)iris.target(150,)
['setosa' 'versicolor' 'virginica']
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])150 個標籤,3 類別 (分別用 0, 1, 2 數值來代表 setosa, versicolor, virginica)。
用 Pandas 的 DataFrame (將 X 和 y 合併) 和 Seaborn 的 pairplot (看每個特徵之間的關係) 來用表格和圖來展示一下數據集的內容。
iris_data = pd.DataFrame( iris.data, columns=iris.feature_names )iris_data['species'] = iris.target_names[iris.target]iris_data.head(3).append(iris_data.tail(3))sns.pairplot( iris_data, hue='species', palette='husl' );看完鳶尾花的 iris 數據展示後,現在來看看 Sklearn 三種引入數據形式。
打包好的數據:對於小數據集,用 sklearn.datasets.load_*
分流下載數據:對於大數據集,用 sklearn.datasets.fetch_*
隨機創建數據:為了快速展示,用 sklearn.datasets.make_*
上面這個星號 * 是什麼意思,指的是具體文件名,敲完
datasets.load_<TAB>
datasets.fetch_<TAB>
datasets.make_<TAB>
點擊鍵盤上的 <TAB> 鍵就可以看到很多完整的文件名,看下面動圖就明白了。
Load 一個數字小數據集 digits?
digits = datasets.load_digits()digits.keys()dict_keys(['data', 'target', 'target_names',
'images', 'DESCR'])Fetch 一個加州房屋大數據集 california_housing?
california_housing = datasets.fetch_california_housing()california_housing.keys()dict_keys(['data', 'target',
'feature_names', 'DESCR'])Make 一個高斯分位數數據集 gaussian_quantile?
gaussian_quantiles = datasets.make_gaussian_quantiles()type(gaussian_quantiles), len(gaussian_quantiles)好了,本節講的就是通過 sklearn 獲得數據三種方式。在自己做數據分析時,最常見的還是從 csv 和 txt 文件中通過 Pandas 讀取並存儲成 DataFrame 的形式,做法在〖數據結構之 Pandas (上)〗一貼中講得很詳細了。
Sklearn 裡萬物皆估計器。估計器是個非常抽象的叫法,可把它不嚴謹的當成一個模型 (用來回歸、分類、聚類、降維),或當成一套流程 (預處理、網格最終)。
本節三大 API 其實都是估計器:
估計器 (estimator) 當然是估計器
預測器 (predictor) 是具有預測功能的估計器
轉換器 (transformer) 是具有轉換功能的估計器
這三句看似廢話,其實蘊藏了很多內容。其實我對第 1 點這個估計器的起名不太滿意,我覺得應該叫擬合器 (fitter) - 具有擬合功能的估計器。看完這一節你就會明白「擬合器」這種叫法更合理。
定義:任何可以基於數據集對一些參數進行估計的對象都被稱為估計器。
兩個核心點:1. 需要輸入數據,2. 可以估計參數。估計器首先被創建,然後被擬合。
創建估計器:需要設置一組超參數,比如
線性回歸裡超參數 normalize=True
K 均值裡超參數 n_clusters=3
在創建好的估計器 model 可以直接訪問這些超參數,用 . 符號。
model.normalize
model.n_clusters
但 model 中有很多超參數,你不可能一開始都知道要設置什麼值,沒設置的用 Sklearn 會給個合理的默認值,因此新手不用擔心。
擬合估計器:需要訓練集。在有監督學習中的代碼範式為
model.fit( X_train, y_train )
在無監督學習中的代碼範式為
model.fit( X_train )
擬合之後可以訪問 model 裡學到的參數,比如線性回歸裡的特徵前的係數 coef_,或 K 均值裡聚類標籤 labels_。
說了這麼多抽象的東西,現在展示有監督學習的「線性回歸」和無監督學習的「K 均值」的具體例子。
首先從 sklearn 下的 linear_model 中引入 LinearRegression,再創建估計器起名 model,設置超參數 normalize 為 True,指的在每個特徵值上做標準化,這樣會加速數值運算。
from sklearn.linear_model import LinearRegression
model = LinearRegression(normalize=True)model創建完後的估計器會顯示所有的超參數,比如我們設置好的 normalize=True,其他沒設置的都是去默認值,比如 n_jobs=None 是只用一個核,你可以將其設為 2 就是兩核並行,甚至設為 -1 就是電腦裡所有核並行。
自己創建一個簡單數據集 (沒有噪聲完全線性) 只為了講解估計器裡面的特徵。
x = np.arange(10)y = 2 * x + 1plt.plot( x, y, 'o' );還記得 Sklearn 裡模型要求特徵 X 是個兩維變量麼 (樣本數×特徵數)?但在本例中 X 是一維,因為我們用 np.newaxis 加一個維度,它做的事情就是把 [1, 2, 3] 轉成 [[1],[2],[3]]。再把 X 和 y 丟進 fit() 函數來擬合線性模型的參數。
X = x[:, np.newaxis]model.fit( X, y )擬合完後的估計器和創建完的樣子看起來一樣,但是已經用「model.param_」可以訪問到學好的參數了,展示如下。
print( model.coef_ )print( model.intercept_ )斜率為 2,截距為 1,沒毛病。和訪問超參數時不一樣,注意訪問參數要加一個下劃線 _。
首先從 sklearn 下的 cluster 中引入 KMeans,再創建估計器起名 model,設置超參數 n_cluster 為 3 (為了展示方便而我們知道用的 iris 數據集有 3 類,實際上應該選不同數量的 n_cluster,根據 elbow 圖來決定,下帖細講)。
再者,iris 數據裡是有標籤 y 的,我們假裝沒有 y 才能無監督的聚類啊,要不然應該做有監督的分類的。
from sklearn.cluster import KMeans
model = KMeans( n_clusters=3 )model創建完後的估計器會顯示所有的超參數,比如我們設置好的 n_cluster=3,其他沒設置的都是去默認值,比如 max_iter=300 是最多迭代次數為 300,算法不收斂也停了。
還記得 iris 裡的特徵有四個嗎 (萼片長、萼片寬、花瓣長、花瓣寬)?四維特徵很難可視化,因此我們只取兩個特徵 (萼片長、萼片寬) 來做聚類並且可視化結果。注意下面代碼 X = iris.data[:,0:2]。
X = iris.data[:,0:2]model.fit(X)擬合完後的估計器和創建完的樣子看起來一樣,但是已經用「model.param_」可以訪問到學好的參數了,展示如下。
print( model.cluster_centers_, '\n')print( model.labels_, '\n' )print( model.inertia_, '\n')print( iris.target )有點亂,解釋一下 KMeans 模型這幾個參數:
需要強調的是真實標籤 iris.label 和聚類標籤 model.labels_ 看起來差的很遠。類別 0 都一致,但是類別 1 和 2 弄反了,這是因為在 KMeans 算法裡標註的類別索引和真實類別索引不一樣 (我現在也沒找到什麼方法能夠讓它們一致)。
最後畫出兩幅圖,左圖是根據聚類得到的標籤畫出散點圖,而右圖是根據真實標籤畫出散點圖,對比兩幅圖看很像,聚類的效果還不錯是把。畫圖的代碼就不細說了,不懂的話看〖基本可視化之 Matplotlib〗帖子吧。
雖然上面以有監督學習的 LinearRegression 和無監督學習的 KMeans 舉例,但實際上你可以將它們替換成其他別的模型,比如有監督學習的 LogisticRegression 和無監督學習的 DBSCAN。它們都是「估計器」,因此都有 fit() 方法。使用它們的通用偽代碼如下:
# 有監督學習from sklearn.xxx import SomeModel# xxx 可以是 linear_model 或 ensemble 等
model = SomeModel( hyperparameter )model.fit( X, y )# 無監督學習from sklearn.xxx import SomeModel# xxx 可以是 cluster 或 decomposition 等
model = SomeModel( hyperparameter )model.fit( X )定義:預測器在估計器上做了一個延展,延展出預測的功能。
兩個核心點:1. 基於學到的參數預測,2. 預測有很多指標。最常見的就是 predict() 函數:
因為要做預測,首先將數據分成 80:20 的訓練集 (X_train, y_train) 和測試集 (X_test, y_test),在用從訓練集上擬合 fit() 的模型在測試集上預測 predict()。
from sklearn.datasets import load_irisiris = load_iris()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 )
print( 'The size of X_train is ', X_train.shape )print( 'The size of y_train is ', y_train.shape )print( 'The size of X_test is ', X_test.shape )print( 'The size of y_test is ', y_test.shape )The size of X_train is (120, 4)
The size of y_train is (120,)
The size of X_test is (30, 4)
The size of y_test is (30,)讓我們來看個有監督學習的「對率回歸」和繼續上節無監督學習的「K 均值」的例子。
首先從 sklearn 下的 linear_model 中引入 LogisticRegression,再創建估計器起名 model,設置超參數 mutli_class 為 multinomial 因為有三種鳶尾花,是個多分類問題。
接著再訓練集上擬合參數,這時估計器 model 裡面已經可以訪問這些參數了。
predict & predict_proba
對於分類問題,我們不僅想知道預測的類別是什麼,有時還想知道預測該類別的信心如何。前者用 predict(),後者用 predict_proba()。
代碼如下,在測試集上比較預測標籤 y_pred 和真實標籤 y_test 發現它們完全吻合,準確率 100% (iris 數據太簡單 )。
y_pred = model.predict( X_test )p_pred = model.predict_proba( X_test )print( y_test, '\n' )print( y_pred, '\n' )print( p_pred )解釋一下 p_pred - 測試集裡有 30 個數據,鳶尾花有 3 類,因此 predict_proba() 生成一個 30×3 的數組,每行的概率加起來為 1。
為了驗證我們的理解,我們看 Sklearn 是不是把「每行中最大概率值對應的那一類」作為預測結果。
s = ['Class 1 Prob', 'Class 2 Prob', 'Class 3 Prob']prob_DF = pd.DataFrame( p_pred, columns=s )prob_DF['Predicted Class'] = y_predprob_DF.head()是的!前三行 Class 1 Prob 最大,預測是第一類;第四行 Class 2 Prob 最大,預測是第二類;第四行 Class 3 Prob 最大,預測是第三類。
score & decision_function
預測器裡還有額外的兩個函數可以使用。在分類問題中
print( model.score( X_test, y_test ) )print( np.sum(y_pred==y_test)/len(y_test) )decision_score = model.decision_function( X_test )print( decision_score )為了驗證我們的理解,我們看 Sklearn 是不是把「每行中最高得分值對應的那一類」作為預測結果。
s = ['Class 1 Score', 'Class 2 Score', 'Class 3 Score']decision_DF = pd.DataFrame( decision_score, columns=s )decision_DF['Predicted Class'] = y_preddecision_DF.tail()是的!前兩行 Class 3 Score 最大,預測是第三類;後三行 Class 1 Score 最大,預測是第一類。
繼續上一節的 KMeans 模型,首先用 fit() 訓練。
再用 predict() 在測試集上預測出類別 inx_pred,和真實標籤 y_test 比對。再次強調,inx_pred 和 y_test 給三個類別的索引定義是不同的。
idx_pred = model.predict( X_test[:,0:2] )print( index_pred )print( y_test )最後畫出兩幅圖 (都是在測試集上),左圖是根據聚類預測的標籤畫出散點圖,而右圖是根據真實標籤畫出散點圖,對比兩幅圖看很像,聚類的效果也不錯。
KMeans 模型裡也有 score() 函數,輸出是值是它要優化的目標函數的對數。
model.score( X_test[:,0:2] )估計器都有 fit() 方法,預測器都有 predict() 和 score() 方法,言外之意不是每個預測器都有 predict_proba() 和 decision_function() 方法,這個在用的時候查查官方文檔就清楚了 (比如 RandomForestClassifier 就沒有 decision_function() 方法)。
使用它們的通用偽代碼如下:
# 有監督學習from sklearn.xxx import SomeModel# xxx 可以是 linear_model 或 ensemble 等
model = SomeModel( hyperparameter )model.fit( X, y )y_pred = model.predict( X_new )s = model.score( X_new )# 無監督學習from sklearn.xxx import SomeModel# xxx 可以是 cluster 或 decomposition 等
model = SomeModel( hyperparameter )model.fit( X )idx_pred = model.predict( X_new )s = model.score( X_new )定義:轉換器也是一種估計器,兩者都帶擬合功能,但估計器做完擬合來預測,而轉換器做完擬合來轉換。
核心點:估計器裡 fit + predict,轉換器裡 fit + transform。
本節介紹兩大類轉換器
將分類型變量 (categorical) 編碼成數值型變量 (numerical)
規範化 (normalize) 或標準化 (standardize) 數值型變量
LabelEncoder & OrdinalEncoder
LabelEncoder 和 OrdinalEncoder 都可以將字符轉成數字,但是
首先給出要編碼的列表 enc 和要解碼的列表 dec。
enc = ['win','draw','lose','win']dec = ['draw','draw','win']從 sklearn 下的 preprocessing 中引入 LabelEncoder,再創建轉換器起名 LE,不需要設置任何超參數。
from sklearn.preprocessing import LabelEncoderLE = LabelEncoder()
print( LE.fit(enc) )print( LE.classes_ )print( LE.transform(dec) )LabelEncoder()
['draw' 'lose' 'win']
[0 0 2]上面結果解釋如下
第 4 行轉換器 fit 之後還是轉換器,只不過從數據 enc 上學到了些東西
第 5 行的 LE.classes_ 就是學到的東西之一,系統把 'draw', 'lose', 'win' 分別賦予 0, 1, 2
第 6 行用學到的東西來解碼 ['draw','draw','win'] 得到 [0 0 2]
除了LabelEncoder 能編碼,OrdinalEncoder 也可以。首先從 sklearn 下的 preprocessing 中引入 OrdinalEncoder,再創建轉換器起名 OE,不需要設置任何超參數。 下面結果和上面類似,就不再多解釋了。
from sklearn.preprocessing import OrdinalEncoderOE = OrdinalEncoder()
enc_DF = pd.DataFrame(enc)dec_DF = pd.DataFrame(dec)
print( OE.fit(enc_DF) )print( OE.categories_ )print( OE.transform(dec_DF) )OrdinalEncoder(categories='auto', dtype=<class 'numpy.float64'>)
[array(['draw', 'lose', 'win'], dtype=object)]
[[0.]
[0.]
[2.]]上面這種編碼的問題是,機器學習算法會認為兩個臨近的值比兩個疏遠的值要更相似。顯然這樣不對 (比如,0 和 1 比 0 和 2 距離更近,難道 draw 和 win 比 draw 和 lose更相似?)。
要解決這個問題,一個常見的方法是給每個分類創建一個二元屬性,即獨熱編碼 (one-hot encoding)。如何用它看下段。
獨熱編碼其實就是把一個整數用向量的形式表現。下圖就是對數字 0-9 做獨熱編碼。
轉換器 OneHotEncoder 可以接受兩種類型的輸入:
用 LabelEncoder 編碼好的一維數組
DataFrame
一. 用 LabelEncoder 編碼好的一維數組 (元素為整數),重塑 (用 reshape(-1,1)) 成二維數組作為 OneHotEncoder 輸入。
from sklearn.preprocessing import OneHotEncoderOHE = OneHotEncoder()
num = LE.fit_transform( enc )print( num )OHE_y = OHE.fit_transform( num.reshape(-1,1) )OHE_y[2 0 1 2]
<4x3 sparse matrix of type
'<class 'numpy.float64'>'
with 4 stored elements
in Compressed Sparse Row format>上面結果解釋如下
想看該矩陣裡具體內容,用 toarray() 函數。
array([[0., 0., 1.],
[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])二. 用 DataFrame作為 OneHotEncoder 輸入。
OHE = OneHotEncoder()OHE.fit_transform( enc_DF ).toarray()array([[0., 0., 1.],
[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])和上面結果類似,不解釋了。
數據要做的最重要的轉換之一是特徵縮放 (feature scaling)。當輸入的數值的量剛不同時,機器學習算法的性能都不會好。
具體來說,對於某個特徵,我們有兩種方法:
整套轉換器「先創建再 fit 在 transform」的流程應該很清楚了。自己讀下面代碼看看是不是秒懂。唯一需要注意的就是輸入 X 要求是兩維。
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) )X_scalearray([[0. ],
[0.005],
[0.01 ],
[0.015],
[0.02 ],
[1. ]])牢記轉換器「先創建再 fit 在 transform」的流程就行了。
from sklearn.preprocessing import StandardScaler
X_scale = StandardScaler().fit_transform( X.reshape(-1,1) )X_scalearray([[-0.47424487],
[-0.46069502],
[-0.44714517],
[-0.43359531],
[-0.42004546],
[ 2.23572584]])警示: fit() 函數只能作用在訓練集上,千萬不要作用在測試集上,要不然你就犯了數據窺探的錯誤了!拿標準化舉例,用訓練集 fit 出來的均值和標準差參數,來對測試集做標準化。
Sklearn 裡核心 API 接口是估計器,那高級 API 接口就是元估計器 (meta-estimator),即由很多基估計器 (base estimator) 組合成的估計器。
類比〖Python 入門篇 (下)〗一貼裡的把函數當成參數的高階函數,元估計器把估計器當成參數。代碼範式大概如下:
meta_model( base_model )
本節討論五大元估計器,分別帶集成功能的 ensemble,多分類和多標籤的 multiclass,多輸出的 multioutput,選擇模型的 model_selection,和流水線的 pipeline。
ensemble.BaggingClassifier
ensemble.VotingClassifier
multiclass.OneVsOneClassifier
multiclass.OneVsRestClassifier
multioutput.MultiOutputClassifier
model_selection.GridSearchCV
model_selection.RandomizedSearchCV
pipeline.Pipeline
在下面五節,我們會用的鳶尾花數據 iris 和數字數據 digits,還有一些自己創建的數據。
Ensemble 估計器是用來做集成學習,該估計器裡面有若干個分類器 (classifier) 或回歸器 (regressor)。詳情參考〖集成學習前傳〗一貼。
最常用的 Ensemble 估計器排列如下:
AdaBoostClassifier: 逐步提升分類器
AdaBoostRegressor: 逐步提升回歸器
BaggingClassifier: 裝袋分類器
BaggingRegressor: 裝袋回歸器
GradientBoostingClassifier: 梯度提升分類器
GradientBoostingRegressor: 梯度提升回歸器
RandomForestClassifier: 隨機森林分類器
RandomForestRegressor: 隨機森林回歸器
VotingClassifier: 投票分類器
VotingRegressor: 投票回歸器
我們用鳶尾花數據 iris,拿
來舉例。首先將數據分成 80:20 的訓練集和測試集,並引入 metrics 來計算各種性能指標。
from sklearn.datasets import load_irisiris = load_iris()from sklearn.model_selection import train_test_splitfrom sklearn import metrics
X_train, X_test, y_train, y_test = train_test_split( iris['data'], iris['target'], test_size=0.2 )隨機森林 (random forest) 是決策樹 (decision tree) 的一種集成模型,每棵決策樹處理的數據用裝袋法 (bagging) 生成。隨機森林可以減小預測的方差,並且可以評估特徵重要性。詳情參考〖隨機森林和提升樹〗一貼。
RandomForestClassifier 通過控制 n_estimators 超參數來決定基估計器的個數,本例是 4 棵決策樹 (森林由樹組成);此外每棵樹的最大樹深為 5 (max_depth=5)。
from sklearn.ensemble import RandomForestClassifier
RF = RandomForestClassifier( n_estimators=4, max_depth=5 )RF.fit( X_train, y_train )估計器有 fit(),元估計器當然也有 fit()。在估計器那一套又可以照搬到元估計器 (起名 RF) 上了。看看 RF 裡包含的估計器個數和其本身。
print( RF.n_estimators )RF.estimators_擬合 RF 完再做預測,用 metrics 裡面的 accuracy_score 來計算準確率。訓練準確率 98.33%,測試準確率 100%。
print ( "RF - Accuracy (Train): %.4g" % metrics.accuracy_score(y_train, RF.predict(X_train)) )print ( "RF - Accuracy (Test): %.4g" % metrics.accuracy_score(y_test, RF.predict(X_test)) )RF - Accuracy (Train): 0.9833
RF - Accuracy (Test): 1和隨機森林由同質分類器「決策樹」不同,投票分類器由若干個異質分類器組成。下例用 VotingClassifier 建立個含有對率回歸 (LR)、隨機森林 (RF) 和高斯樸素貝葉斯 (GNB) 三個分類器的集成模型。
RandomForestClassifier 的基分類器只能是決策樹,因此只用通過控制 n_estimators 超參數來決定樹的個數,而 VotingClassifier 的基分類器要實實在在的輸入其本身。
看看 Ensemble 裡包含的估計器個數和其本身。
print( len(Ensemble.estimators_) )Ensemble.estimators_比如元估計器和它三個組成元素的表現。還是集成後的 Ensemble 表現最好。
LR.fit( X_train, y_train )RF.fit( X_train, y_train )GNB.fit( X_train, y_train )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): 1sklearn.multiclass 可以處理多類別 (multi-class) 的多標籤 (multi-label) 的分類問題。
從小節 4.2 到 4.4,我們都會使用數字數據集 digits。首先將數據分成 80:20 的訓練集和測試集。
from sklearn.datasets import load_digits
digits = load_digits()digits.keys()dict_keys(['data', 'target', 'target_names',
'images', 'DESCR'])X_train, X_test, y_train, y_test = train_test_split( digits['data'], digits['target'], test_size=0.2 )
print( 'The size of X_train is ', X_train.shape )print( 'The size of y_train is ', y_train.shape )print( 'The size of X_test is ', X_test.shape )print( 'The size of y_test is ', y_test.shape )The size of X_train is (1437, 64)
The size of y_train is (1437,)
The size of X_test is (360, 64)
The size of y_test is (360,)訓練集和測試集分別有 1437 和 360 張圖像。每張照片是包含 8×8 的像素,將其打平 (flatten) 把 2 維的 8×8 重塑成 1 維的 64。
看看訓練集中前 100 張圖片和對應的標籤 (左下角藍色小字)。像素很低 (為了我們跑模型快些),但基本上還是能看清。
手寫數字有 0-9 十類,但手頭上只有兩分類估計器 (比如像支撐向量機) 怎麼用呢?我們可以採取下面三種常見策略:
一對一 (One vs One, OvO):一個分類器用來處理數字 0 和數字 1,一個用來處理數字 0 和數字 2,一個用來處理數字 1 和 2,以此類推。N 個類需要 N(N-1)/2 個分類器。
一對其他 (One vs All, OvA):訓練 10 個二分類器,每一個對應一個數字,第一個分類 1 和「非1」,第二個分類 2 和「非2」,以此類推。N 個類需要 N 個分類器。
考慮一個具體天氣多分類問題,天氣可以是晴天、陰天和雨天,在 OvO 中,三個分類器為 f1 , f2 和 f3 。
f1 負責分類三角形和正方形
f2 負責分類三角形和圓形
f3 負責分類圓形和正方形
結果如下
根據多數原則得到的結合預測為 ●,如下圖所示。
回到數字分類問題上,代碼如下:
10 類 45 個 OvO 分類器,沒錯,10*9/2 = 45。
print( len(ovo_lr.estimators_) )ovo_lr.estimators_訓練集分類全對,測試集準確率 98%。
在 OvA 中,把數據分成「某個」和「其他」
圖一,某個 = 三角形,其他 = 正方形和圓形
圖二,某個 = 正方形,其他 = 三角形和圓形
圖三,某個 = 圓形,其他 = 三角形和正方形
三分類分解成三個二分類,對應的分類器為 f1 , f2 和 f3 。
f1 預測負類,即預測 ● 和 ◼
f2 預測負類,即預測 ▲ 和 ●
f3 預測正類,即預測 ●
三個分類器都預測了 ●,根據多數原則得到的預測是 ●。
回到數字分類問題上,代碼如下:
10 類 45 個 OvA 分類器,沒錯。
print( len(ova_lr.estimators_) )ova_lr.estimators_訓練集準確率幾乎 100%,測試集準確率 96%。
到目前為止,所有的樣例都總是被分配到僅一個類。有些情況下,你也許想讓分類器給一個樣例輸出多個類別。在無人駕駛的應用中,在下圖識別出有車和指示牌,沒有交通燈和人。
我們不打算深入物體識別。先看一個簡單點的例子,僅僅是為了闡明「多標籤分類」的原理。在手寫數字的例子上,我們特意為每個數字設計了多標籤:
標籤 1 - 奇數、偶數
標籤 2 - 小於等於 4,大於 4
再建立多標籤 y_train_multilabel,代碼如下 (OneVsRestClassifier 也可以用來做多標籤分類):
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]]看下圖訓練集第 1 和 2 個圖片是數字 4 和 5,對應上面兩標籤當然是
訓練模型,只不過這時用的是 y_train_multilabel。
有兩個估計器,每個對應一個標籤。
print( len(ova_ml.estimators_) )ova_ml.estimators_展示一下測試集上 100 張圖片。
第一張圖片是數字 2,它是偶數 (標籤 1 為 true),小於等於 4 (標籤 2 為 true)。
print( y_test[:1] )print( ova_ml.predict(X_test[:1,:]) )sklearn.multioutput 可以處理多輸出 (multi-output) 的分類問題。
多輸出分類是多標籤分類的泛化,在這裡每一個標籤可以是多類別 (大於兩個類別) 的。一個例子就是預測圖片每一個像素(標籤) 的像素值是多少 (從 0 到 255 的 256 個類別)。
Multioutput 估計器有兩個:
本節只關注多輸出分類。
首先引入 MultiOutputClassifier 和 RandomForestClassifier。你看,這兩個都是元估計器,因此在 Sklearn 裡面估計器可以隨意組合。
from sklearn.multioutput import MultiOutputClassifierfrom sklearn.ensemble import RandomForestClassifier在手寫數字的例子上,我們也為特意每個數字設計了多標籤而且每個標籤的類別都大於二。
代碼如下:
用含有 100 棵決策樹的隨機森林來解決這個多輸入分類問題。
看看這個模型在測試集前五張照片上的預測。
MO.predict( X_test[:5,:] )array([[0, 2],
[0, 2],
[0, 0],
[2, 9],
[1, 5]])這個 ndarray 第一列是標籤 1 的類別,第二列是標籤 2 的類別。預測結果是這五張照片分別顯示數字 2, 2, 0, 9, 5 (標籤 2),它們前三個數 2, 2, 0 都小於等於 4 (標籤 1 第一類),第四個數 9 大於等於 7 (標籤 1 第二類),而第五個數 5 在 4 和 7 之間 (標籤 1 第三類)。
再看看真實標籤。
y_test_1st = y_test.copy()y_test_1st[ y_test<=4 ] = 0y_test_1st[ np.logical_and(y_test>4, y_test<7) ] = 1y_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]])相當好!
模型選擇 (Model Selction) 在機器學習非常重要,它主要用於評估模型表現,常見的 Model Selection 估計器有以下幾個:
cross_validate: 評估交叉驗證的表現。
learning_curve: 建立學習曲線。
GridSearchCV: 用交叉驗證從網格中一組超參數搜索出最佳超參數。
RandomizedSearchCV: 用交叉驗證從一組隨機超參數搜索出最佳超參數。
本小節關注調節超參數的兩個估計器,即上面列出的最後兩個。它們都要用到交叉驗證,先來了解一下這個知識點。
K-折交叉驗證集 (K-fold cross validation set),就是把整個數據集平均但隨機分成 K 份,每份大概包含 m/K 個數據 (m 是總數據數)。
在這 K 份,每次選 1 份作為訓練集在擬合參數 wλ,把參數用在剩下 K-1 份驗證集上計算誤差。由於遍歷了這 K 份數據,因此該操作稱為交叉驗證。接下來我們來看這兩個調參的估計器,網格追蹤和隨機追蹤。
網格追蹤:參數 1 在 [1, 10, 100, 1000] 中取值,參數 2 在 [0.01, 0.1, 1 10] 中取值,注意並不是等間距取值。模型在所有 16 個組合跑,選取一對對應最小交叉驗證誤差的參數。
隨機追蹤:根據指定分布隨機搜索,可以選擇獨立於參數個數,比如 log(參數 1) 服從 0 到 3 的均勻分布, log(參數 2) 服從 -2 到 1 的均勻分布。此外,會設定一個預算參數。
原理講清楚了,看代碼吧。
解釋一下代碼:
解釋一下運行結果:
第一行輸出每種追蹤法運行的多少次和花的時間。
第二行輸出最佳超參數的組合。
第三行輸出最高得分。
由上面結果可知,隨機追蹤比網格追蹤用更短時間內找到一組超參數,獲得了更高的得分。
Pipeline 估計器又叫流水線,把各種估計器串聯 (Pipeline) 或並聯 (FeatureUnion) 的方式組成一條龍服務。用好了它真的能大大提高效率。
Pipeline 將若干個估計器按順序連在一起,比如
特徵提取 -> 降維 -> 擬合 -> 預測
在整個 Pipeline 中,它的屬性永遠和最後一個估計器屬性一樣
下面用一個簡單例子來說明如果用 Pipeline 來做「先填補缺失值-再標準化」這兩步的。先生成含缺失值 NaN 的數據 X。
首先引入 Pipeline,再引入
處理缺失值的轉換器 SimpleImputer
做規劃化的轉換器 MinMaxScaler
第 4-7 行創建了流水線,範式非常簡單,就在 Pipeline() 裡一個輸入「含名稱的估計器的列表」。SimpleImputer 起名叫 impute,MinMaxScaler起名叫 normalize。
由於最後一個估計器是轉換器,因此 pipe 也是個轉換器。寫好了就可以那它來做「先填補缺失值-再標準化」的重複工作了。
看看運行結果,值都被填滿了,而且兩列也被標準化了。
來驗證上面流水線的參數,我們可以按順序來運行這兩個轉換器,結果是一樣的。
如果我們想在一個節點同時運行幾個估計器,我們可用 FeatureUnion。下例首先建立一個 DataFrame,
我們現在按下列步驟來清洗數據。
上面兩步是平行進行的。
首先我們自己定義一個從 DataFrame 裡面獲取每列的類,起名叫 DataFrameSelector。
代碼不難,主要就是 transform 函數中,將輸入的 DataFrame X 根據屬性名稱來獲取其值。接下來建立一個流水線 full_pipe,它並聯著兩個流水線
categorical_pipe 處理分類型變量
numeric_pipe 處理數值型變量
DataFrameSelector 用來獲取
SimpleImputer 用均值來填充 NaN
normalize 來規範化數值
下面代碼非常漂亮。
將結果列印出來,齊活!
X_proc = full_pipe.fit_transform( X )print( X_proc )[[1. 0.12 0. 1. 0. 0. 1. ]
[0.77777778 0.72 1. 0. 0. 1. 0. ]
[0.55555556 0.48 1. 0. 0. 0. 1. ]
[0. 0.52 0. 0. 1. 1. 0. ]
[0.04444444 1. 0. 1. 0. 1. 0. ]
[0.11111111 0. 1. 0. 0. 1. 0. ]
[0.08888889 0.92 0. 1. 0. 1. 0. ]
[0.34166667 0.52 0. 1. 0. 1. 0. ]
[0.15555556 0.4 0. 1. 0. 1. 0. ]]Sklearn 裡面設計 API 遵循五大原則。
所有對象的接口一致且簡單,在「估計器」中
在「預測器」中
在「轉換器」中
所有估計器裡設置的超參數和學到的參數都可以通過實例的變量直接訪問來檢驗其值,區別是超參數的名稱最後沒有下劃線 _,而參數的名稱最後有下劃線 _。舉例如下:
通例:model.hyperparameter
特例:SVC.kernel
通例:model.parameter_
特例:SVC.support_vectors_
Sklearn 模型接受的數據集的格式只能是「Numpy 數組」和「Scipy 稀疏矩陣」。超參數的格式只能是「字符」和「數值」。
不接受其他的類!
模塊都能重複「連在一起」或「並在一起」使用,比如兩種形式流水線 (pipeline)
任意轉換器序列
任意轉換器序列 + 估計器
Sklearn 給大多超參數提供了合理的默認值,大大降低了建模的難度。
結合本帖講的總結一套機器學習的初級框架:
確定任務:是「有監督」的分類或回歸?還是「無監督」的聚類或降維?確定好後基本就能知道用 Sklearn 裡哪些模型了。
數據預處理:這步最繁瑣,要處理缺失值、異常值;要編碼分類型變量;要正規化或標準化數值型變量,等等。但是有了 Pipeline 神器一切變得簡單高效。
訓練和評估:這步最簡單,訓練用估計器 fit() 先擬合,評估用預測器 predict() 來評估。
選擇模型:啟動 Model Selection 估計器裡的 GridSearchCV 和 RandomizedSearchCV,選擇得分最高的那組超參數 (即模型)。
本帖講的東西有點抽象,但最核心的東西就是弄懂估計器以及元估計器的原理。剩下的就是 1) 了解各種模型,2) 知道模型中每個參數的含義,3) 查閱 Sklearn 官方文檔。非深度的機器學習不像深度學習有那麼多調參技巧 (tuning trick),按照上面那套框架足夠了。