1. 程式人生 > >scikit-learn 框架

scikit-learn 框架

字符串 驗證 ros -i 而不是 knn valid 任務 二維

1 Introduction

1.1 Dataset

scikit-learn提供了一些標準數據集(datasets),比如用於分類學習的iris 和 digits 數據集,還有用於歸約的boston house prices 數據集。

其使用方式非常簡單如下所示:

$ python

>>> from sklearn import datasets

>>> iris = datasets.load_iris()

>>> digits = datasets.load_digits()

每個datasets對象(如iris或digits)都是一個類Dictionary,即是一個Map容器。同時datasets對象都有兩個重要屬性:

1) data:樣本空間

data屬性是一個二維的矩陣,每行表示一個測試的樣本(samples),每列表示樣本的特征值(feature),如下所示:

from sklearn import datasets

digits = datasets.load_digits()

print(digits.data)

輸出:

[[ 0. 0. 5. …, 0. 0. 0.]

[ 0. 0. 0. …, 10. 0. 0.]

[ 0. 0. 0. …, 16. 9. 0.]

…,

[ 0. 0. 1. …, 6. 0. 0.]

[ 0. 0. 2. …, 12. 0. 0.]

[ 0. 0. 10. …, 12. 1. 0.]]

2) target:標簽空間

target是測試樣本的真實標簽,如下所示:

from sklearn import datasets

digits = datasets.load_digits()

print(digits.target)

輸出:

[0 1 2 …, 8 9 8]

ps:

iris 和 digits 數據集還有一些不同的屬性,可以在datasets.load_XXX()函數源碼中查看詳細內容,如datasets.load_digits()函數內容如下:

Def load_digits(n_class=10, return_X_y=False):

return Bunch(data=flat_data,

target=target,

target_names=np.arange(10),

images=images,

DESCR=descr)

l 說明load_digits方法,返回的是Bunch對象,其有data、target、target_names、images和DESCR成員屬性。

1.2 Estimator

Estimator是scikit-learn實現的主要API,可以將其理解為模型(model),即是機器學習中的學習器(learner),通過estimator可以進行分類、回歸和聚合等操作。

對於監督學習的任務可以分如下步驟進行:

1) 模型選擇:選擇一個estimator對象;

2) 訓練模型:根據訓練數據集來訓練模型;

3) 泛化性能度量:測量模型的泛化能力,即對其評分;

4) 模型進行預測:進行實際預測或應用。

1.2.1 模型選擇

scikit-learn已經實現了非常多機器學習模型,用戶只需根據接口參數要求直接創建即可。

如下所示獲取一個支持向量機模型:

from sklearn import svm

clf = svm.SVC(gamma=0.001, C=100.)

1.2.2 訓練模型

每個scikit-learn模型都提供一個fit(X, y)方法,用於訓練模型,其中X參數是一個二維的矩陣,是指模型訓練的數據集;y是一個一維數組,是指訓練數據集的相應標簽。如下所示的使用方式:

clf.fit(digits.data[:-1], digits.target[:-1])

l digits.data[:-1]:data是一個二維的數組,[:-1]表示傳遞第一維數組從開始到最後所有內容;

l digits.target[:-1]:target是一個一維數組,[:-1]b表示傳遞數組所有內容。

1.2.3 性能度量

每個scikit-learn模型都提供一個score()方法用於估計模型的性能,在訓練完模型後,即可使用該方法進行估計性能。

如下所示的程序:

from __future__ import print_function

from sklearn.datasets import load_iris

from sklearn.cross_validation import train_test_split

from sklearn.neighbors import KNeighborsClassifier

iris = load_iris()

X = iris.data

y = iris.target

#0.獲取數據集,並將數據集分為訓練數據和測試數據

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=4)

#1.獲取模型

knn = KNeighborsClassifier(n_neighbors=5)

#2.訓練模型

knn.fit(X_train, y_train)

#3.度量性能

print(knn.score(X_test, y_test))

輸出:

0.973684210526

1.2.4 數據預測

在訓練完模型後,即可進行數據預測。每個scikit-learn模型都提供一個predict(X)方法,其功能是預測指定的數據。其中X是一個二維矩陣,即希望被預測的數據;同時該方法會返回一個一維的數組,每個元素對應矩陣X中每行的預測標簽。

如下所示的完整程序:

from sklearn import datasets

from sklearn import svm

digits = datasets.load_digits()

clf = svm.SVC(gamma=0.001, C=100.)

clf.fit(digits.data[:-1], digits.target[:-1])

y=clf.predict(digits.data[-1:])

print(y)

輸出:

[8]

l 最後輸出的是一個數組,因為我們進行預測的數據只有一行,所以只輸出一個元素。

1.3 Preprocessing

對於訓練數據集和預測數據常需要先進行預處理,使得訓練的模型泛化性能更高。其中本小結只簡單介紹“特征縮放”,更多功能可以參考[1]的預處理章節。

如下使用了preprocessing模塊scale()方法進行數據縮放:

from sklearn import preprocessing

a = np.array([[10, 2.7, 3.6],

[-100, 5, -2],

[120, 20, 40]],

dtype=np.float64)

print(a) #比較在預處理前的數據

print(preprocessing.scale(a)) #比較在預處理後的數據

輸出:

[[ 10. 2.7 3.6]

[-100. 5. -2. ]

[ 120. 20. 40. ]]

[[ 0. -0.85170713 -0.55138018]

[-1.22474487 -0.55187146 -0.852133 ]

[ 1.22474487 1.40357859 1.40351318]]

1.4 Cross-validated

scikit-learn的交叉驗證功能是通過model_selection模塊實現,

1.4.1 split

通常在(監督)學習實驗中,通常會將一部分數據獨立出來作為測試集合。scikit-learn的model_selection模塊有個輔助函數 train_test_split 可以快速地將數據劃分為訓練集合與測試結合。

如下將采樣到一個訓練集合同時保留 40% 的數據用於測試(評估):

from sklearn import datasets

from sklearn.model_selection import train_test_split

#0.獲取數據集

iris = datasets.load_iris()

print(iris.data.shape, iris.target.shape)

#1.進行原始數據集的分離操作

X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=4)

#2.分離後的數據集

print(X_train.shape, y_train.shape)

print(X_test.shape, y_test.shape)

輸出:

(150, 4) (150,)

(112, 4) (112,)

(38, 4) (38,)

PS:

在model_selection中還有其它多種函數能用於數據集分離操作,可以具體參考[1]的Model selection模塊。

1.4.2 score

Estimator對象已提供一個score函數能夠度量模型的性能,但是該方法需要先訓練模型,然後測量模型的性能。即將數據集分為兩部分,一部分先訓練模型;另一部分用於度量模型。

model_selection提供一種cross-validation(交叉驗證)的方式來度量模型的性能,這種方式不需要用戶手動分離數據集和訓練模型。用戶直接測量模型的泛化性能,該函數為:cross_val_score

def cross_val_score(estimator, X, y=None, groups=None, scoring=None, cv=None,

n_jobs=1, verbose=0, fit_params=None,

pre_dispatch=‘2*n_jobs‘):

l estimator:為創建的模型;

l X:為數據集,為矩陣類型;

l y:為標簽數,為向量類型;

l cv:為交叉驗證的組數,每組都會產生一個評分結果,為整數類型;

l return:為每組驗證的評分,為向量類型;

下面的例子演示了如何評估一個線性支持向量機在 iris 數據集上的精度,通過劃分數據,可以連續5次評分:

from sklearn import datasets

from sklearn import svm

from sklearn.model_selection import cross_val_score

iris = datasets.load_iris()

clf = svm.SVC(kernel=‘linear‘, C=1)

scores = cross_val_score(clf, iris.data, iris.target, cv=5)

print(scores)

輸出:

[ 0.96666667 1. 0.96666667 0.96666667 1. ]

通過cross_val_score方法獲取的是一個向量,用戶可以對向量取平均分數和具有 95% 置信區間,如下所示的分數估計:

print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

輸出:

Accuracy: 0.98 (+/- 0.03)

1.4.3 Learning curve

一個模型(Estimator)的泛化能力與它的訓練數據集有很直接的關系,若訓練數據集樣本數少了則會出現“欠擬合”的模型,如圖 1?1所示的第一個圖;若訓練數據集樣本數多了則會出現“過擬合”的模型,如圖 1?1所示的第三個圖;如圖 1?1所示的第二個圖是數據集剛剛好的情況。

技術分享

圖 1?1

對於一維的特征向量可以圖形化來描述過擬合和欠擬合的情況,若特征向量是多維的,則很難用圖形化來評估數據集數量對模型的影響。

model_selection提供一個工具函數learning_curve來幫助用戶了解數據集的樣本數對模型泛化性能的影響,通過這個函數能夠顯示不同數量訓練樣本下模型的訓練和驗證分數。這裏的訓練分數是指進行訓練模型的數據集來評估模型性能的分數;而驗證分數是指在通過測試數據集對評估模型性能的分數。

如圖 1?1所示是一個SVM模型在不同數據集樣本數下,訓練分數和交叉驗證分數的學習曲線,通過兩者分數的差異可以評估模型的擬合程度:

1) 若出現Training分數和Cross-validation分數都一樣低,那說明模型為欠擬合情況;

2) 若出現Training分數高,而Cross-validation分數低,則說明模型出現了過擬合情況;

3) 而Training分數低,而Cross-validation分數高的情況是不可能出現的情況;

4) 只有Training分數和Cross-validation分數一樣高才說明模型是擬合適中。

技術分享

圖 1?2

我們使用learning_curve函數的目標是獲取使得Training分數和Cross-validation分數一樣高的數據樣本數。其中learning_curve函數聲明頭如下所示:

def learning_curve(estimator, X, y, groups=None,

train_sizes=np.linspace(0.1, 1.0, 5), cv=None, scoring=None,

exploit_incremental_learning=False, n_jobs=1,

pre_dispatch="all", verbose=0):

l estimator為評估的模型;

l X為數據集,為矩陣類型;

l y為標簽數,為向量類型;

l train_sizes訓練數據集的大小,為向量類型,每個元素表示進行訓練的數據樣本數;若元素為浮點類型,則訓練數是整個樣本集的比例;若元素為整數類型,則訓練數就是所指定的固定數量。

l cv為交叉驗證的組數,每組都會產生一個評分結果,為整數類型;

l return會一個元祖,該元祖有三個元素:

a) train_sizes_abs:為每組訓練的樣本數,其為一個向量類型;

b) train_scores:為每組訓練數據集的評分,為矩陣類型;

c) test_scores:為交叉驗證的測試評分,也為矩陣類型。

如下的使用示例:

from sklearn.model_selection import learning_curve

from sklearn.svm import SVC

from sklearn.datasets import load_iris

iris = load_iris()

X = iris.data

y = iris.target

train_sizes, train_scores, valid_scores = learning_curve(SVC(kernel=‘linear‘), X, y, train_sizes=[0.40, 0.80, 1], cv=5)

print(train_sizes)

print(train_scores)

print(valid_scores)

輸出:

[ 48 96 120]

[[ 1. 1. 1. 1. 1. ]

[ 0.98958333 0.97916667 0.97916667 1. 0.97916667]

[ 0.975 0.975 0.99166667 0.98333333 0.98333333]]

[[ 0.66666667 0.66666667 0.66666667 0.66666667 0.66666667]

[ 0.96666667 1. 0.93333333 0.9 1. ]

[ 0.96666667 1. 0.96666667 0.96666667 1. ]]

PS

scikit-learn的model_selection模塊還提供另一個評估函數:Validation curve,該函數功能與learning_curve功能類似,不過Validation_curve函數支持調節不同模型的參數來驗證性能。

1.5 Persistence

scikit-learn提供模型持久化功能,即能夠將訓練好的模型保存起來,後續可以直接獲取模型不需要重復訓練,從而節約預測的時間。

Python提供了一個模塊 pickle,能夠實現模型持久化功能。其使用方式如下所示:

from sklearn import svm

from sklearn import datasets

clf = svm.SVC()

iris = datasets.load_iris()

X, y = iris.data, iris.target

clf.fit(X, y)

import pickle

s = pickle.dumps(clf)

clf2 = pickle.loads(s)

y_predit = clf2.predict(X[0:1])

print(y_predit) #預測標簽

print(y[0]) #真實標簽

輸出:

[0]

0

在特殊情況下,可以使用joblib代替pickle模塊,特別是在大數據集下效率更高,但只有pickle將模型保存到磁盤中,而不是保存為字符串形式,如下所示的使用:

from sklearn.externals import joblib

joblib.dump(clf, ‘filename.pkl‘)

clf = joblib.load(‘filename.pkl‘)

2 參考文獻

[1]. scikit-learn官方網站;

[2]. scikit-learn中文版網站;

[3].

scikit-learn 框架