Warning html
警告:有些沒能理解的句子,我以本身的理解意譯。 python
翻譯自:Scikit Learn:Machine Learning in Python git
做者: Fabian Pedregosa, Gael Varoquaux github
先決條件 算法
目錄 數組
警告:在0.9版中(2011年9月發行),scikit-learn的導入路徑從scikits.learn更改成sklearn 數據結構
首先咱們載入一些用來玩耍的數據。咱們將使用的數據是很是簡單的著名的花朵數據——安德森鳶尾花卉數據集。 app
咱們有一百五十個鳶尾花的一些尺寸的觀測值:萼片長度、寬度,花瓣長度和寬度。還有它們的亞屬:山鳶尾(Iris setosa)、變色鳶尾(Iris versicolor)和維吉尼亞鳶尾(Iris virginica) dom
向python對象載入數據: python2.7
In [1]: from sklearn import datasets In [2]: iris = datasets.load_iris()
數據存儲在.data項中,是一個(n_samples, n_features)數組。
In [3]: iris.data.shape Out[3]: (150, 4)
每一個觀察對象的種類存貯在數據集的.target屬性中。這是一個長度爲n_samples的整數一維數組:
In [5]: iris.target.shape Out[5]: (150,) In [6]: import numpy as np In [7]: np.unique(iris.target) Out[7]: array([0, 1, 2])
數碼數據集1包括1797個圖像,每個都是個表明手寫數字的8x8像素圖像
In [8]: digits = datasets.load_digits() In [9]: digits.images.shape Out[9]: (1797, 8, 8) In [10]: import pylab as pl In [11]: pl.imshow(digits.images[0], cmap=pl.cm.gray_r) Out[11]: <matplotlib.image.AxesImage at 0x3285b90> In [13]: pl.show()
爲了在scikit中使用這個數據集,咱們把每一個8x8圖像轉換成長度爲64的矢量。(譯者注:或者直接用digits.data)
In [12]: data = digits.images.reshape((digits.images.shape[0], -1))
如今咱們已經得到一些數據,咱們想要從中學習和預測一個新的數據。在scikit-learn中,咱們經過建立一個估計器(estimator)從已經存在的數據學習,而且調用它的fit(X,Y)方法。
In [14]: from sklearn import svm In [15]: clf = svm.LinearSVC() In [16]: clf.fit(iris.data, iris.target) # learn from the data Out[16]: LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True, intercept_scaling=1, loss='l2', multi_class='ovr', penalty='l2', tol=0.0001, verbose=0)
一旦咱們已經從數據學習,咱們可使用咱們的模型來預測未觀測數據最可能的結果。
In [17]: clf.predict([[ 5.0, 3.6, 1.3, 0.25]]) Out[17]: array([0], dtype=int32)
注意:咱們能夠經過它如下劃線結束的屬性存取模型的參數:
In [18]: clf.coef_ Out[18]: array([[ 0.18424352, 0.45122644, -0.8079467 , -0.45071302], [ 0.05190619, -0.89423619, 0.40519245, -0.93781587], [-0.85087844, -0.98667529, 1.38088883, 1.86538111]])
最簡單的可能的分類器是最近鄰:給定一個新的觀測值,將n維空間中最靠近它的訓練樣本標籤給它。其中n是每一個樣本中特性(features)數。
k最近鄰2分類器內部使用基於球樹(ball tree)3來表明它訓練的樣本。
KNN分類示例:
In [19]: # Create and fit a nearest-neighbor classifier In [20]: from sklearn import neighbors In [21]: knn = neighbors.KNeighborsClassifier() In [22]: knn.fit(iris.data, iris.target) Out[22]: KNeighborsClassifier(algorithm='auto', leaf_size=30, n_neighbors=5, p=2, warn_on_equidistant=True, weights='uniform') In [23]: knn.predict([[0.1, 0.2, 0.3, 0.4]]) Out[23]: array([0])
當驗證學習算法時,不要用一個用來擬合估計器的數據來驗證估計器的預測很是重要。確實,經過kNN估計器,咱們將老是得到關於訓練集完美的預測。
In [24]: perm = np.random.permutation(iris.target.size) In [25]: iris.data = iris.data[perm] In [26]: iris.target = iris.target[perm] In [27]: knn.fit(iris.data[:100], iris.target[:100]) Out[27]: KNeighborsClassifier(algorithm='auto', leaf_size=30, n_neighbors=5, p=2, warn_on_equidistant=True, weights='uniform') In [28]: knn.score(iris.data[100:], iris.target[100:]) /usr/lib/python2.7/site-packages/sklearn/neighbors/classification.py:129: NeighborsWarning: kneighbors: neighbor k+1 and neighbor k have the same distance: results will be dependent on data order. neigh_dist, neigh_ind = self.kneighbors(X) Out[28]: 0.95999999999999996
Bonus的問題:爲何咱們使用隨機的排列?
SVMs4嘗試構建一個兩個類別的最大間隔超平面。它選擇輸入的子集,調用支持向量即離分離的超平面最近的樣本點。
In [60]: from sklearn import svm In [61]: svc = svm.SVC(kernel='linear') In [62]: svc.fit(iris.data, iris.target) Out[62]: SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0, kernel='linear', probability=False, shrinking=True, tol=0.001, verbose=False)
scikit-learn中有好幾種支持向量機實現。最廣泛使用的是svm.SVC,svm.NuSVC和svm.LinearSVC;「SVC」表明支持向量分類器(Support Vector Classifier)(也存在迴歸SVMs,在scikit-learn中叫做「SVR」)。
練習
訓練一個數字數據集的svm.SVC。省略最後10%而且檢驗觀測值的預測表現。
類別不老是能夠用超平面分離,因此人們期望有些多是多項式或指數實例的非線性決策函數:
線性核
svc = svm.SVC(kernel=’linear’)
多項式核
svc = svm.SVC(kernel=’poly’, … degree=3) # degree: polynomial degree
RBF核(徑向基函數)5
svc = svm.SVC(kernel=’rbf’) # gamma: inverse of size of # radial kernel
練習
以上提到的哪些覈對數字數據集有更好的預測性能?(譯者:前兩個)
給定鳶尾花數據集,若是咱們知道這有三種鳶尾花,可是沒法獲得它們的標籤,咱們能夠嘗試非監督學習:咱們能夠經過某些標準聚類觀測值到幾個組別裏。
最簡答的聚類算法是k均值算法。這將一個數據分紅k個集羣,以最小化觀測值(n維空間中)到聚類中心的均值來分配每一個觀測點到集羣;而後均值從新被計算。這個操做遞歸運行直到聚類收斂,在max_iter回合內到最大值。6
(一個替代的k均值算法實如今scipy中的cluster包中。這個scikit-learn實現與之不一樣,經過提供對象API和幾個額外的特性,包括智能初始化。)
In [82]: from sklearn import cluster, datasets In [83]: iris = datasets.load_iris() In [84]: k_means = cluster.KMeans(k=3) In [85]: k_means.fit(iris.data) Out[85]: KMeans(copy_x=True, init='k-means++', k=3, max_iter=300, n_init=10, n_jobs=1, precompute_distances=True, random_state=<mtrand.RandomState object at 0x7f4d860642d0>, tol=0.0001, verbose=0) In [86]: print k_means.labels_[::10] [1 1 1 1 1 2 2 2 2 2 0 0 0 0 0] In [87]: print iris.target[::10] [0 0 0 0 0 1 1 1 1 1 2 2 2 2 2]
譯者注:Lena是經典的圖像處理實例圖像, 8位灰度色深, 尺寸512 x 512
聚類能夠被看做是一種從信息中選擇一小部分觀測值。例如,這個能夠被用來海報化一個圖像(將連續變化的色調轉換成更少幾個色調):
In [95]: from scipy import misc In [96]: lena = misc.lena().astype(np.float32) In [97]: X = lena.reshape((-1, 1)) # We need an (n_sample, n_feature) array In [98]: k_means = cluster.KMeans(5) In [99]: k_means.fit(X) Out[99]: KMeans(copy_x=True, init='k-means++', k=5, max_iter=300, n_init=10, n_jobs=1, precompute_distances=True, random_state=<mtrand.RandomState object at 0x7f4d860642d0>, tol=0.0001, verbose=0) In [100]: values = k_means.cluster_centers_.squeeze() In [101]: labels = k_means.labels_ In [102]: lena_compressed = np.choose(labels, values) In [103]: lena_compressed.shape = lena.shape
譯者注:想看效果?
In [31]: import matplotlib.pyplot as plt In [32]: plt.gray() In [33]: plt.imshow(lena_compressed) Out[33]: <matplotlib.image.AxesImage at 0x4b2c510> In [34]: plt.show()
原圖相似。
![Image]
以上根據觀測值標記的點雲在一個方向很是平坦,因此一個特性幾乎能夠用其它兩個確切地計算。PCA發現哪一個方向的數據不是平的而且它能夠經過在一個子空間投影來降維。
警告:PCA將在模塊decomposition或pca中,這取決於你scikit-learn的版本。
In [75]: from sklearn import decomposition In [76]: pca = decomposition.PCA(n_components=2) In [77]: pca.fit(iris.data) Out[77]: PCA(copy=True, n_components=2, whiten=False) In [78]: X = pca.transform(iris.data)
如今咱們能夠可視化(降維過的)鳶尾花數據集:
In [79]: import pylab as pl In [80]: pl.scatter(X[:, 0], X[:, 1], c=iris.target) Out[80]: <matplotlib.collections.PathCollection at 0x4104310>
PCA不只在可視化高維數據集時很是有用。它能夠用來做爲幫助加速對高維數據不那麼有效率的監督方法7的預處理步驟。
一個實例使用主成分分析來降維和支持向量機來分類進行人臉識別。
譯者注:讓程序自動下載(確保聯網,文件較大,要等待好久)或者手動下載數據並放到./scikit_learn_data/lfw_home/下。
""" Stripped-down version of the face recognition example by Olivier Grisel http://scikit-learn.org/dev/auto_examples/applications/face_recognition.html ## original shape of images: 50, 37 """ import numpy as np import pylab as pl from sklearn import cross_val, datasets, decomposition, svm # .. # .. load data .. lfw_people = datasets.fetch_lfw_people(min_faces_per_person=70, resize=0.4) perm = np.random.permutation(lfw_people.target.size) lfw_people.data = lfw_people.data[perm] lfw_people.target = lfw_people.target[perm] faces = np.reshape(lfw_people.data, (lfw_people.target.shape[0], -1)) train, test = iter(cross_val.StratifiedKFold(lfw_people.target, k=4)).next() X_train, X_test = faces[train], faces[test] y_train, y_test = lfw_people.target[train], lfw_people.target[test] # .. # .. dimension reduction .. pca = decomposition.RandomizedPCA(n_components=150, whiten=True) pca.fit(X_train) X_train_pca = pca.transform(X_train) X_test_pca = pca.transform(X_test) # .. # .. classification .. clf = svm.SVC(C=5., gamma=0.001) clf.fit(X_train_pca, y_train) # .. # .. predict on new images .. for i in range(10): print lfw_people.target_names[clf.predict(X_test_pca[i])[0]] _ = pl.imshow(X_test[i].reshape(50, 37), cmap=pl.cm.gray) _ = raw_input()
所有代碼:face.py
糖尿病數據集
糖尿病數據集包含442個病人的測量而得的10項生理指標(年齡,性別,體重,血壓),和一年後疾病進展的指示:
In [104]: diabetes = datasets.load_diabetes() In [105]: diabetes_X_train = diabetes.data[:-20] In [106]: diabetes_X_test = diabetes.data[-20:] In [107]: diabetes_y_train = diabetes.target[:-20] In [108]: diabetes_y_test = diabetes.target[-20:]
這個手頭的任務是用來從生理指標預測疾病。
爲了改善問題的條件(無信息變量,減小維度的不利影響,做爲一個特性(feature)選擇的預處理,等等),咱們只關注有信息的特性將沒有信息的特性設置爲0.這個罰則函數法8,叫做套索(Lasso)9,能夠將一些係數設置爲0.這些方法叫做稀疏方法(sparse method),稀疏化能夠被視做奧卡姆剃刀:相對於複雜模型更傾向於簡單的。
In [109]: from sklearn import linear_model In [110]: regr = linear_model.Lasso(alpha=.3) In [111]: regr.fit(diabetes_X_train, diabetes_y_train) Out[111]: Lasso(alpha=0.3, copy_X=True, fit_intercept=True, max_iter=1000, normalize=False, positive=False, precompute='auto', tol=0.0001, warm_start=False) In [112]: regr.coef_ # very sparse coefficients Out[112]: array([ 0. , -0. , 497.34075682, 199.17441034, -0. , -0. , -118.89291545, 0. , 430.9379595 , 0. ]) In [113]: regr.score(diabetes_X_test, diabetes_y_test) Out[113]: 0.55108354530029791
這個分數和線性迴歸(最小二乘法)很是類似:
In [114]: lin = linear_model.LinearRegression() In [115]: lin.fit(diabetes_X_train, diabetes_y_train) Out[115]: LinearRegression(copy_X=True, fit_intercept=True, normalize=False) In [116]: lin.score(diabetes_X_test, diabetes_y_test) Out[116]: 0.58507530226905713
同一數學問題能夠用不一樣算法解決。例如,sklearn中的Lasso對象使用座標降低(coordinate descent)方法10解決套索迴歸,這在大數據集時很是有效率。然而,sklearn也提供了LassoLARS對象,使用LARS這種在解決權重向量估計很是稀疏,觀測值不多的問題頗有效率的方法。
scikit-learn提供了一個對象,該對象給定數據,在擬合一個參數網格的估計器時計算分數,而且選擇參數最大化交叉驗證分數。這個對象在構建時採用一個估計器而且暴露一個估計器API:
In [117]: from sklearn import svm, grid_search In [118]: gammas = np.logspace(-6, -1, 10) In [119]: svc = svm.SVC() In [120]: clf = grid_search.GridSearchCV(estimator=svc, param_grid=dict(gamma=gammas),n_jobs=-1) In [121]: clf.fit(digits.data[:1000], digits.target[:1000]) Out[121]: GridSearchCV(cv=None, estimator=SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0, kernel='rbf', probability=False, shrinking=True, tol=0.001, verbose=False), fit_params={}, iid=True, loss_func=None, n_jobs=-1, param_grid={'gamma': array([ 1.00000e-06, 3.59381e-06, 1.29155e-05, 4.64159e-05, 1.66810e-04, 5.99484e-04, 2.15443e-03, 7.74264e-03, 2.78256e-02, 1.00000e-01])}, pre_dispatch='2*n_jobs', refit=True, score_func=None, verbose=0) In [122]: clf.best_score /usr/lib/python2.7/site-packages/sklearn/utils/__init__.py:79: DeprecationWarning: Function best_score is deprecated; GridSearchCV.best_score is deprecated and will be removed in version 0.12. Please use ``GridSearchCV.best_score_`` instead. warnings.warn(msg, category=DeprecationWarning) Out[122]: 0.98600097103091122 In [123]: clf.best_estimator.gamma /usr/lib/python2.7/site-packages/sklearn/utils/__init__.py:79: DeprecationWarning: Function best_estimator is deprecated; GridSearchCV.best_estimator is deprecated and will be removed in version 0.12. Please use ``GridSearchCV.best_estimator_`` instead. warnings.warn(msg, category=DeprecationWarning) Out[123]: 0.0021544346900318843
默認GridSearchCV使用三次(3-fold)交叉驗證。然而,若是它探測到一個分類器被傳遞,而不是一個迴歸量,它使用分層的3次。
交叉驗證在一個algorithm by algorithm基礎上能夠更有效地設定參數。這就是爲什麼,對給定的估計器,scikit-learn使用「CV」估計器,經過交叉驗證自動設定參數。
In [125]: from sklearn import linear_model, datasets In [126]: lasso = linear_model.LassoCV() In [127]: diabetes = datasets.load_diabetes() In [128]: X_diabetes = diabetes.data In [129]: y_diabetes = diabetes.target In [130]: lasso.fit(X_diabetes, y_diabetes) Out[130]: LassoCV(alphas=array([ 2.14804, 2.00327, ..., 0.0023 , 0.00215]), copy_X=True, cv=None, eps=0.001, fit_intercept=True, max_iter=1000, n_alphas=100, normalize=False, precompute='auto', tol=0.0001, verbose=False) In [131]: # The estimator chose automatically its lambda: In [132]: lasso.alpha Out[132]: 0.013180196198701137
這些估計器是類似的,以‘CV’爲它們名字的後綴。
練習
對糖尿病數據集,找到最優的正則化參數alpha。(0.016249161908773888)