1. 程式人生 > >機器學習 Python scikit-learn 中文文件(3)使用 scikit-learn 介紹機器學習

機器學習 Python scikit-learn 中文文件(3)使用 scikit-learn 介紹機器學習

與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn

與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn

Logo
首頁 安裝 文件 案例
Fork me on GitHub
Previous
scikit-learn 教程
Next
用於科學資料處理的統計學習教程
Up
scikit-learn 教程
scikit-learn v0.20.1
其他版本

該中文文件由人工智慧社群的Antares翻譯!

使用 scikit-learn 介紹機器學習
機器學習:問題設定
載入示例資料集
學習和預測
模型持久化
規定或約定(Conventions)
型別轉換
再次訓練和更新引數
多分類擬合 vs. 多標籤擬合

使用 scikit-learn 介紹機器學習
內容提要

在本節中,我們介紹一些在使用 scikit-learn 過程中用到的 機器學習<https://en.wikipedia.org/wiki/Machine_learning>_ 詞彙, 並且給出一些例子闡釋它們。

機器學習:問題設定
通常,我們的學習問題(learning problem)要考慮一個包含n個樣本 (samples) 的資料集合,然後嘗試預測未知資料的某個或某些屬性。 如果每個樣本不止一個數字,則稱其具有若干屬性(attributes)或特徵(features)。例如,一個多維條目, 又稱多變數資料 (multivariate data)。

學習問題(learning problem)可以被劃分為幾個大類:

監督學習 (supervised learning), 其中資料帶有我們想要預測的附加屬性 (單擊這裡 跳轉到 scikit-learn 的監督學習頁面). 監督學習又可以分為兩類:

分類 (Classification): 樣本屬於兩個或多個類,我們希望從已經標記的資料中學習如何預測未標記的資料所屬的類。 分類問題的一個例子就是手寫數字識別,其目的是將每個輸入向量分配給有限數量的離散類別之一。 另一種考慮分類的方法是將其作為一種離散的(與連續的相對應)監督學習形式,其中,我們有有限數量的類別, 對於所提供的n個樣本中的每一個,我們試圖用正確的類別來標記樣本。
迴歸 (Regression): 如果需要的輸出由一個或多個連續變數構成,那麼這樣的任務就被稱為 regression。 迴歸問題的一個例子是預測鮭魚的長度與其年齡和體重的關係。
無監督學習 (unsupervised learning), 其中,訓練資料由一組輸入向量 x 組成,沒有任何對應的目標值。此類問題的目標可能是在資料中發現一組相似的樣本, 被稱為聚類(clustering), 或者是決定資料在輸入空間中的分佈, 被稱為密度估計(density estimation), 或者是將高維資料投影到低維空間進行降維以達到視覺化的效果visualization

(單擊這裡 跳轉到 scikit-learn 的無監督學習頁面).

訓練集和測試集

機器學習就是學習資料集的一些屬性,然後根據另一個數據集測試這些屬性。機器學習中的一個常見實踐是 通過將資料集分成兩個來評估演算法。 我們稱其中一個集合為訓練集,我們在其上學習一些屬性; 我們稱另一個集合為測試集,我們在其上測試所學習的屬性。

載入示例資料集
scikit-learn 附帶了幾個標準資料集,例如用於分類的虹膜(iris)和 數字(digits)資料集以及 用於迴歸的波士頓房價(boston house prices dataset)資料集。

下面,我們從shell啟動一個Python直譯器,然後載入虹膜 iris 和數字 digits 資料集。 我們的符號約定是 $ 表示shell提示,而 >>> 表示Python直譯器的提示:

$ python

from sklearn import datasets
iris = datasets.load_iris()
digits = datasets.load_digits()
資料集是類似於字典的物件,它儲存所有資料和關於資料的一些元資料。資料部分被儲存在 .data 成員中, 它是一個 n_samples, n_features 的陣列。 在監督學習問題中,一個或多個響應變數(response variables)被儲存在 .target 成員中. 更多關於資料集的詳細資訊請參考 dedicated section.

比如, 在手寫字元資料集中, digits.data 可以讓我們訪問特徵然後用於分類識別不同的字元樣本:

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.]]
而 digits.target 則給出了每一個手寫字元樣本的真實類別標籤, 而這正是我們想要讓學習器學習的類標籤:

digits.target
array([0, 1, 2, …, 8, 9, 8])
data陣列的形狀(Shape of the data arrays)

儘管原始資料可能有各種不同的shape,但是一旦load完畢,data成員 總是一個2D陣列, shape 為 (n_samples, n_features) 。 在 digits 這個資料集中,每個原始樣本是一個shape為 (8, 8) 的影象,而且可以用以下方式訪問:

digits.images[0]
array([[ 0., 0., 5., 13., 9., 1., 0., 0.],
[ 0., 0., 13., 15., 10., 15., 5., 0.],
[ 0., 3., 15., 2., 0., 11., 8., 0.],
[ 0., 4., 12., 0., 0., 8., 8., 0.],
[ 0., 5., 8., 0., 0., 9., 8., 0.],
[ 0., 4., 11., 0., 1., 12., 7., 0.],
[ 0., 2., 14., 5., 10., 12., 0., 0.],
[ 0., 0., 6., 13., 10., 0., 0., 0.]])
案列連結 simple example on this dataset 舉例說明了如何從原始問題出發,形成用於scikit-learning中的資料。

從外部資料載入

要想從外部資料集載入資料,請看 loading external datasets.

學習和預測
對於 digits 資料集,任務是根據影象預測它代表哪個數字。我們給出10個可能的類(從0到9的數字)中的每個類的樣本, 我們在這些類上擬合(fit)一個估計器(estimator), 以便能夠預測(predict)未知樣本所屬的類。

在 scikit-learn 中, 一個用於分類的估計器(estimator)是一個 Python 物件,該物件實現了成員方法 fit(X, y) 和 predict(T).

分類估計器的一個例子是類 sklearn.svm.SVC, 它實現了支援向量分類器 (support vector classification)。 該 estimator 的建構函式(constructor)接受模型引數(model’s parameters)作為建構函式的輸入引數(arguments)。

現在, 我們例項化SVC的estimator,把它看成個黑盒子:

from sklearn import svm
clf = svm.SVC(gamma=0.001, C=100.)
選擇合適的模型引數(model’s parameters)

在本例中,我們手動設定了模型引數 gamma 的值。如果你想找到一個更合理的模型引數的話,請使用sklearn提供的工具,比如 網格搜尋 和 交叉驗證.

上面建立的估計器例項 clf 首先適合於模型;也就是說,它必須從模型中學習。這是通過把我們的訓練集傳遞給擬合方法 fit 完成的。 對於訓練集,我們將使用資料集中的所有影象,除了最後一個影象,我們將保留這個影象用於預測。我們使用Python語法 [:-1] 來獲取訓練集, 該切片操作將返回一個新的array,它包含了來自於 digits.data 的所有樣本除了最後一個

clf.fit(digits.data[:-1], digits.target[:-1])
SVC(C=100.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=‘ovr’, degree=3, gamma=0.001, kernel=‘rbf’,
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
現在我們可以預測(predict)新的值了。 在這個案例中,我們預測一下 digits.data 中的最後一張影象的類標籤。 By predicting, you’ll determine the image from the training set that best matches the last image.

clf.predict(digits.data[-1:])
array([8])
對應的影象是:

…/…/images/sphx_glr_plot_digits_last_image_001.png
正如您所看到的,這是一個具有挑戰性的任務:畢竟,影象的解析度很差。你同意分類器的結果嗎?

一個分類問題的完整案列: Recognizing hand-written digits.

模型持久化
通過使用Python的內建永續性模組 pickle, 可以在scikit-learning中儲存模型

from sklearn import svm
from sklearn import datasets
clf = svm.SVC(gamma=‘scale’)
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf.fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=‘ovr’, degree=3, gamma=‘scale’, kernel=‘rbf’,
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)

import pickle
s = pickle.dumps(clf)
clf2 = pickle.loads(s)
clf2.predict(X[0:1])
array([0])

y[0]
0
對於某些具體情況,使用joblib替代pickle(joblib.dump & joblib.load)可能更有趣, 這對於大資料更有效,但是它只能對磁碟進行pickle而不能對字串進行pickle:

from joblib import dump, load
dump(clf, ‘filename.joblib’)
稍後,您可以重新載入pickle模型(可能在另一個Python程序中):

clf = load(‘filename.joblib’)
Note joblib.dump and joblib.load functions also accept file-like object instead of filenames. More information on data persistence with Joblib is available here.
Note that pickle has some security and maintainability issues. Please refer to section 模型持久化(Model persistence) for more detailed information about model persistence with scikit-learn.

規定或約定(Conventions)
scikit-learning估計器遵循某些規則以使其行為更具預測性。我們可以在這個章節裡面看到scikit-learn對機器學習術語的定義 機器學習和API元素的通用術語表。

型別轉換
除非特別指出,輸入將會被轉成 float64:

import numpy as np
from sklearn import random_projection

rng = np.random.RandomState(0)
X = rng.rand(10, 2000)
X = np.array(X, dtype=‘float32’)
X.dtype
dtype(‘float32’)

transformer = random_projection.GaussianRandomProjection()
X_new = transformer.fit_transform(X)
X_new.dtype
dtype(‘float64’)
在這個例子中, X 是 float32, 但是被函式 fit_transform(X)轉換成float64.

迴歸目標值轉換為 float64 以及 分類器的目標值保持不變:

from sklearn import datasets
from sklearn.svm import SVC
iris = datasets.load_iris()
clf = SVC(gamma=‘scale’)
clf.fit(iris.data, iris.target)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=‘ovr’, degree=3, gamma=‘scale’, kernel=‘rbf’,
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)

list(clf.predict(iris.data[:3]))
[0, 0, 0]

clf.fit(iris.data, iris.target_names[iris.target])
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=‘ovr’, degree=3, gamma=‘scale’, kernel=‘rbf’,
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)

list(clf.predict(iris.data[:3]))
[‘setosa’, ‘setosa’, ‘setosa’]
這裡, 第一個 predict() 返回一個 integer array, 因為 iris.target (an integer array) 被用在 fit. 第二個 predict() 返回一個 string array, since iris.target_names was for fitting.

再次訓練和更新引數
當 Estimator 構造好後,它的 Hyper-parameters 還可以用 set_params() 方法更新。 不止一次的呼叫 fit() 將會重新覆蓋掉之前學習到的模型

import numpy as np
from sklearn.svm import SVC

rng = np.random.RandomState(0)
X = rng.rand(100, 10)
y = rng.binomial(1, 0.5, 100)
X_test = rng.rand(5, 10)

clf = SVC()
clf.set_params(kernel=‘linear’).fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=‘ovr’, degree=3, gamma=‘auto_deprecated’,
kernel=‘linear’, max_iter=-1, probability=False, random_state=None,
shrinking=True, tol=0.001, verbose=False)

clf.predict(X_test)
array([1, 0, 1, 1, 0])

clf.set_params(kernel=‘rbf’, gamma=‘scale’).fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=‘ovr’, degree=3, gamma=‘scale’, kernel=‘rbf’,
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)

clf.predict(X_test)
array([1, 0, 1, 1, 0])
上面的程式碼中, 在Estimator建立好以後,預設核函式 rbf 第一次通過 SVC.set_params() 被修改成 linear, 然後又改回了預設的 rbf 進行再次重新擬合 estimator, 然後做第二次預測.

多分類擬合 vs. 多標籤擬合
當使用多類分類器 multiclass classifiers 時, 所執行的學習和預測任務取決於符合以下條件的目標資料的格式:

from sklearn.svm import SVC
from sklearn.multiclass import OneVsRestClassifier
from sklearn.preprocessing import LabelBinarizer

X = [[1, 2], [2, 4], [4, 5], [3, 2], [3, 1]]
y = [0, 0, 1, 1, 2]

classif = OneVsRestClassifier(estimator=SVC(gamma=‘scale’,
… random_state=0))

classif.fit(X, y).predict(X)
array([0, 0, 1, 1, 2])
In the above case, the classifier is fit on a 1d array of multiclass labels and the predict() method therefore provides corresponding multiclass predictions. It is also possible to fit upon a 2d array of binary label indicators:

y = LabelBinarizer().fit_transform(y)
classif.fit(X, y).predict(X)
array([[1, 0, 0],
[1, 0, 0],
[0, 1, 0],
[0, 0, 0],
[0, 0, 0]])
Here, the classifier is fit() on a 2d binary label representation of y, using the LabelBinarizer. In this case predict() returns a 2d array representing the corresponding multilabel predictions.

Note that the fourth and fifth instances returned all zeroes, indicating that they matched none of the three labels fit upon. With multilabel outputs, it is similarly possible for an instance to be assigned multiple labels:

from sklearn.preprocessing import MultiLabelBinarizer
y = [[0, 1], [0, 2], [1, 3], [0, 2, 3], [2, 4]]
y = MultiLabelBinarizer().fit_transform(y)
classif.fit(X, y).predict(X)
array([[1, 1, 0, 0, 0],
[1, 0, 1, 0, 0],
[0, 1, 0, 1, 0],
[1, 0, 1, 0, 0],
[1, 0, 1, 0, 0]])
In this case, the classifier is fit upon instances each assigned multiple labels. The MultiLabelBinarizer is used to binarize the 2d array of multilabels to fit upon. As a result, predict() returns a 2d array with multiple predicted labels for each instance.

© 2007 - 2018, scikit-learn developers (BSD License). Show this page source
Previous
Next