scikit-learn 框架
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 框架