天天看點

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

.本節書摘來自華章出版社《機器學習系統設計:python語言實作》一書中的第2章,第2.8節,作者 [美] 戴維·朱利安(david julian),更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

scikit-learn包含了最常見的機器學習任務的算法,例如,分類、回歸、聚類、降維、模型選擇和預處理。

scikit-learn中有一些用于練習的真實世界的資料集。我們來看看其中之一,iris資料集:

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

該資料集包含了三種iris類型(setosa、versicolor和virginica)的150個樣本,每個樣本具有四個特征。我們可以擷取資料集的描述:

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

我們可以看到四個屬性或特征分别是,萼片寬度、萼片長度、花瓣長度和花瓣寬度,機關為厘米。每個樣本屬于三種類型之一。setosa、versicolor和virginica分别由0、1和2表示。

讓我們使用這一資料來觀察一個簡單的分類問題。我們期望根據萼片和花瓣的長度和寬度特征來預測iris的類型。通常,scikit-learn使用估計來實作fit(x, y)和predict(x)方法,其中fix(x, y)用于訓練分類器,predict(x)根據給定的無标簽觀察值x傳回預測的标簽y。fit()和predict()方法通常需要一個二維數組對象作為參數。

這裡我們将使用k近鄰(k-nn)算法來解決此分類問題。k-nn的原理比較簡單,即通過近鄰資料的類别來對無标簽樣本進行分類。對每個資料點的分類,首先找到少量的與其最為相鄰的k個資料點,然後根據k個資料點中占多數的類型來确定其類型。k-nn是一種基于執行個體的學習,其分類不是取決于其内在的模型,而是對有标簽測試集進行參考。k-nn隻是簡單地記住所有訓練資料,并與每個新樣本進行比較,是以它是一種非歸納方法。盡管k-nn顯得簡單,也許正是因為簡單,是以這是一種使用非常廣泛的技術,用于解決各種分類和回歸問題。

在scikit-learn中有兩種不同的k-nn分類器。kneighborsclassifier需要使用者來指定k,即近鄰資料的數量。radiusneighborsclassifier則不同,它對每個訓練資料點指定固定的半徑r,根據半徑r内的近鄰數量進行學習。kneighborsclassifier更為常用。k值的優化取決于資料,通常,噪聲資料較多時使用較大的k值,而這樣也犧牲了一些分類邊界的明确性。如果資料不是均勻采樣的,則radiusneighborsclassifier可能是更好的選擇。因為近鄰的數量取決于半徑,是以每個點的k值會不同,稀疏區域的k值要小于樣本密度高的區域:

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn
《機器學習系統設計:Python語言實作》一2.8 Scikit-learn
《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

以下是上面代碼的輸出如下圖所示:

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

現在,我們再來看看scikit-learn如何解決回歸問題。最簡單的方案是最小化誤差平方和。對此可以使用linearregression對象。該對象的fit()方法需要兩個向量參數:x是特征向量,y是目标向量。

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

linearregression對象有四個可選的參數:

fit_intercept:布爾值,如果設為false,則假設資料是居中的,模型在計算時不會使用截距。預設值是true。

normalize:如果為true,x将在回歸前以0為均值,1為方差進行歸一化。因為歸一化後能夠比較明确地解釋回歸系數,是以有時會有用。預設值是false。

copy_x:預設值為true。如果設為false,将會覆寫x。

n_jobs:計算時所用作業的數量,預設值為1。在多cpu的情況下,對于大型問題可以用來加速計算。

其輸出有如下屬性:

coef_:線性回歸問題的估計系數數組。如果y是多元的,即有多個目标變量,則coef_是以(n_targets, n_features)為形式的二維數組。如果隻傳入一個目标變量,則coef_将是長度為n_features的一維數組。

intercept_:線性模型中的截距或獨立項數組。

對于普通最小二乘法(ordinary least squares),我們假設特征是獨立的。當特征之間具有相關性時,則x矩陣會接近奇異性。這意味着估計将對輸入資料的微小變化高度敏感。這被稱為多重共線性(multicollinearity),它會導緻大的方差和最終不确定性。後續會深入讨論這一問題,但現在來看一個某種程度上可以解決該問題的算法。

嶺回歸不僅可以解決多重共線性問題,還可以用于輸入變量遠遠超出樣本數量的情形。linear_model.ridge()對象使用了l2正則化。直覺地講,我們可以将其了解為對權重向量的極值加以懲罰。這樣會使平均權重更小,是以有時也稱為收縮(shrinkage)。因為其減小了對極值的敏感度,是以會使模型更為穩定。

scikit-learn的linear_model.ridge對象增加了一個正則化參數alpha。通常,賦予alpha一個小的正值會提高模型的穩定性。alpha也可以是浮點數或數組。如果是數組,則假設數組對應于目标變量,是以,其大小與目标變量相同。我們可以嘗試下面的簡單函數:

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn
《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

接下來我們再看看scikit-learn中用于降維的算法。降維對于機器學習十分重要,因為這樣可以減少模型需要考慮的輸入變量或特征的數量。這樣會使模型更有效率,并且使結果更容易解釋。同時,這樣還能減少過度拟合而提高模型的普遍性。

當然,避免丢棄影響模型準确性的資訊也很重要。降維算法的主要工作就是确定哪些是備援或無關的資料。通常有兩種方法:特征提取和特征選擇。特征選擇是試圖在原始特征變量中找到子集。特征提取則不同,是指結合那些具有相關性的變量,在此之上建立新的特征變量。

讓我們先看看可能是最常用的特征提取算法,即主成分分析(pca)。pca使用正交變換将一組相關變量轉換為一組不相關變量。其中的重要資訊,如向量長度和向量之間的角度,保持不變。這些資訊由内積定義,并在正交變化中保持不變。pca構造特征向量的方式是,第一成分盡可能多地表示資料中的可變性,後續成分所表示的可變性則依次減少。這意味着,對于大多數模型,我們可以隻選擇少量的主要成分,隻要它們所表示的資料可變性能夠滿足實驗規格所要求的即可。

徑向基函數(rbf)大概是最為通用的、在大多數情況下都能給出良好結果的核函數。徑向基核函數采用參數gamma,可以粗略地了解為每個樣本的徑向作用範圍的逆。gamma值小則意味着對于模型所選擇的樣本,每個樣本的作用範圍半徑大。kernalpca的fit_transform方法接受一個訓練向量,對模型進行拟合,并變換為主成分。例如:

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn
《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

正如我們所見,有監督學習算法成功的主要障礙是,由訓練資料到測試資料的轉化。有标簽訓練集可能具有獨特的特點,而新的無标簽資料并沒有。我們可以看到,對于訓練資料,訓練的模型可以十分精确,然而這種精确性可能無法轉化到無标簽測試資料上。過度拟合是有監督學習的一個重要問題,而我們有很多技術可以用來最小化這一問題。一種方式是使用交叉驗證來對模型在訓練集上的估計性能進行評價。讓我們使用支援向量機在iris資料上對此進行嘗試。首先,我們需要将資料分割為訓練集和測試集。train_test_split方法接受兩個資料結構:資料本身和分割結果。這兩個結構可以是numpy數組、pandas的dataframes清單,或scipy矩陣。正如我們所期望的,分割結果的長度應該和資料一樣。test_size參數可以是0和1之間的浮點數,表示分割資料的比例,也可以是整數,表示測試樣本的數量。這裡,我們對test_size指派為0.3,表示我們将40%的資料用于測試。

在本例中,我們使用svm.svc類和.scores的方法來傳回測試資料在标簽預測中的平均精度:

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

我們可以觀察到如下輸出:

《機器學習系統設計:Python語言實作》一2.8 Scikit-learn

支援向量機有個penalty參數需要手工設定,我們很可能要調整這一參數并多次運作svc,直到獲得最優拟合。然而即使完成這一步,由于從訓練集到測試集存在資訊洩漏,我們可能還是存在過度拟合的問題。對于任何存在手工設定參數的估計都會有這個問題,我們将在第4章中進行探索。