scikit-learn__02.2__Basic-Principles

機器學習的基本原則

在這裏,我們將深入探討機器學習的基本原理,以及如何通過Scikit-Learn API使用它們。

在簡要介紹scikit-learn的Estimator對象之後,我們將介紹有監督的學習,包括分類和迴歸問題,以及無監督的學習,包括降維和聚類問題。

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn')

The Scikit-learn Estimator Object

每種算法都通過“ Estimator”對象在scikit學習中公開。 例如,線性迴歸是這樣實現的:

from sklearn.linear_model import LinearRegression

估計器參數:估計器的所有參數都可以在實例化時設置,並具有合適的默認值:

model = LinearRegression(normalize=True)
print(model.normalize)
>>True
print(model)
>>LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=True)

估計的模型參數:當數據與估計器擬合時,將從手頭的數據估計參數。 所有估計的參數都是估計對象的屬性,其下劃線結尾:

x = np.arange(10)
y = 2 * x + 1
print(x)
print(y)
>>[0 1 2 3 4 5 6 7 8 9]
[ 1  3  5  7  9 11 13 15 17 19]
plt.plot(x, y, 'o');

在這裏插入圖片描述

# The input data for sklearn is 2D: (samples == 10 x features == 1)
X = x[:, np.newaxis]
print(X)
print(y)
>>[[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]]
[ 1  3  5  7  9 11 13 15 17 19]
# fit the model on our data 使模型適合我們的數據
model.fit(X, y)
>>LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=True)
# underscore at the end indicates a fit parameter 末尾的下劃線表示一個合適的參數
print(model.coef_)#參數
print(model.intercept_)#截距
>>[2.]
1.0

這個模型找到了一條斜率爲2、截距爲1的直線,正如我們所期望的那樣。

監督學習:分類和迴歸

在“監督學習”中,我們有一個既包含要素又包含標籤的數據集。
任務是構造一個能夠預測對象標籤的估計器
給定的功能集。 一個相對簡單的例子是預測
虹膜給出了一組其花朵的尺寸。 這是一個相對簡單的任務。
一些更復雜的示例是:
-通過望遠鏡獲得物體的多色圖像,確定
該物體是恆星,類星體還是星系。
-給定某人的照片,在照片中標識該人。
-給出一個人觀看過的電影列表及其個人評價
電影中,推薦他們想要的電影列表
(所謂的“推薦系統”:一個著名的例子是[Netflix獎](http://en.wikipedia.org/wiki/Netflix_prize))。
這些任務的共同點是存在一個或多個未知數
與對象相關的數量需要從其他對象確定
觀察到的數量。
監督學習被進一步分爲兩類,“分類”和“迴歸”。
在分類中,標籤是離散的,而在迴歸中,標籤是連續的。 例如,
在天文學中,確定物體是恆星,星系還是類星體的任務是
分類問題:標籤來自三個不同的類別。 另一方面,我們可能
希望基於這樣的觀察來估計物體的壽命:這將是一個迴歸問題,
因爲標籤(年齡)是連續的數量。

分類的例子

K最近鄰居(kNN)是最簡單的學習策略之一:給定一個新的未知觀察值,在您的參考數據庫中查找具有最接近特徵並指定主要類別的參考。
讓我們嘗試一下鳶尾花分類問題:

from sklearn import neighbors, datasets

iris = datasets.load_iris()
X, y = iris.data, iris.target

# create the model
knn = neighbors.KNeighborsClassifier(n_neighbors=5)

# fit the model
knn.fit(X, y)

# What kind of iris has 3cm x 5cm sepal and 4cm x 2cm petal?
# call the "predict" method:
result = knn.predict([[3, 5, 4, 2],])

print(iris.target_names[result])
>>['versicolor']

您還可以進行概率預測:

knn.predict_proba([[3, 5, 4, 2],])
>>array([[0. , 0.8, 0.2]])
from fig_code import plot_iris_knn
plot_iris_knn()

在這裏插入圖片描述

練習

對同一問題使用不同的估計:sklearn.svm.SVC。
請注意,你不必知道它是什麼,使用它。我們只是在嘗試這裏的界面
如果你提前完成,試着用奇異值分解估計器創建一個類似的圖。

from sklearn.svm import SVC

迴歸示例

最簡單的迴歸問題之一是將一條線擬合到數據,正如我們在上面看到的。
Scikit-learn還包含更復雜的迴歸算法

# Create some simple data
import numpy as np
np.random.seed(0)
X = np.random.random(size=(20, 1))
y = 3 * X.squeeze() + 2 + np.random.randn(20)

plt.plot(X.squeeze(), y, 'o');

在這裏插入圖片描述

model = LinearRegression()
model.fit(X, y)

# Plot the data and the model prediction
X_fit = np.linspace(0, 1, 100)[:, np.newaxis]
y_fit = model.predict(X_fit)

plt.plot(X.squeeze(), y, 'o')
plt.plot(X_fit.squeeze(), y_fit);

在這裏插入圖片描述
Scikit-learn還具有一些更復雜的模型,它們可以響應數據中的更精細功能:

# Fit a Random Forest
from sklearn.ensemble import RandomForestRegressor
model = RandomForestRegressor()
model.fit(X, y)

# Plot the data and the model prediction
X_fit = np.linspace(0, 1, 100)[:, np.newaxis]
y_fit = model.predict(X_fit)

plt.plot(X.squeeze(), y, 'o')
plt.plot(X_fit.squeeze(), y_fit);

在這裏插入圖片描述
這些因素是否適合,取決於許多因素。 在本教程的後面,我們將討論如何選擇模型的詳細信息。


Exercise

使用IPython的幫助功能探索``RandomForestRegressor’'對象(即在該對象之後添加一個問號)。

``RandomForestRegressor’'可以使用哪些參數?

如何上面的情節變化,如果你改變這些參數呢?

這些類級參數稱爲* hyperparameters *,稍後我們將在模型驗證部分討論如何選擇超參數。


機器學習:降維和聚類

機器學習 解決一種不同的問題。這裏的數據沒有標籤,我們感興趣的是找出這些物體之間的相似之處。從某種意義上說,您可以將無監督學習視爲從數據本身中發現標籤的一種手段。機器學習包括諸如降維聚類密度估計。例如,在上面討論的虹膜數據中,我們可以在無監督的情況下使用方法來確定最能顯示數據。正如我們將在下面看到的,這樣的數據投影可以用來可視化二維四維數據集。一些更復雜的無監督學習問題是:

  • 根據對遙遠星系的詳細觀察,確定哪些特徵或特徵組合最能概括信息。
  • 給定兩個聲源的混合(例如,一個人邊聽音樂邊講話),將這兩個聲源分開(這稱爲[盲源分離])(http://en.wikipedia.org/wiki/Blind_signal_separation) problem).
  • 給定視頻,請隔離運動對象並根據已看到的其他運動對象進行分類。

有時甚至可以將兩者結合起來: 無監督學習可用於發現有用的東西異構數據中的特徵,然後可以在監督下使用這些特徵框架。

Dimensionality Reduction: PCA

主成分分析(PCA)是一種降維技術,可以找到解釋最大方差的變量組合。
以iris數據集爲例。因爲它有4個特徵,所以它不能在一個2D圖中被可視化。我們將提取兩個組合的萼片和花瓣的規模,以可視化它

X, y = iris.data, iris.target

from sklearn.decomposition import PCA
pca = PCA(n_components=0.95)
pca.fit(X)
X_reduced = pca.transform(X)
print("Reduced dataset shape:", X_reduced.shape)
>>Reduced dataset shape: (150, 2)

import pylab as plt
plt.scatter(X_reduced[:, 0], X_reduced[:, 1], c=y,
           cmap='RdYlBu')

print("Meaning of the 2 components:")
for component in pca.components_:
    print(" + ".join("%.3f x %s" % (value, name)
                     for value, name in zip(component,
                                            iris.feature_names)))
>>Meaning of the 2 components:
0.361 x sepal length (cm) + -0.085 x sepal width (cm) + 0.857 x petal length (cm) + 0.358 x petal width (cm)
0.657 x sepal length (cm) + 0.730 x sepal width (cm) + -0.173 x petal length (cm) + -0.075 x petal width (cm)

在這裏插入圖片描述

集羣:k - means

聚類將相對於給定標準而言均一的觀察分組在一起,從而在數據中找到“簇”。
請注意,只有使用的標準突出顯示這些簇時,它們纔會發現數據的相關隱藏結構。

from sklearn.cluster import KMeans
k_means = KMeans(n_clusters=3, random_state=0) # Fixing the RNG in kmeans
k_means.fit(X)
y_pred = k_means.predict(X)

plt.scatter(X_reduced[:, 0], X_reduced[:, 1], c=y_pred,
           cmap='RdYlBu');

在這裏插入圖片描述

概述:Scikit-learn的estimator接口

Scikit-learn努力爲所有方法提供統一的界面,我們將在下面看到這些示例。 給定一個scikit學習估算器對象名爲“模型”,可以使用以下方法:

  • Available in all Estimators
    • model.fit() : fit training data.
      對於監督學習應用, 這有兩個參數: the data X and the labels y (e.g. model.fit(X, y)).
      對於非監督學習應用,只有一個參數 the data X (e.g. model.fit(X)).
  • Available in supervised estimators
    • model.predict() : given a trained model, predict the label of a new set of data.
      This method accepts one argument, the new data X_new (e.g. model.predict(X_new)),
      並返回數組中每個對象的學習標籤.
    • model.predict_proba() : For classification problems, some estimators also provide
      this method, which returns the probability that a new observation has each categorical label.
      In this case, the label with the highest probability is returned by model.predict().
    • model.score() : for classification or regression problems, most (all?) estimators implement
      a score method. Scores are between 0 and 1, with a larger score indicating a better fit.
  • Available in unsupervised estimators
    • model.predict() : predict labels in clustering algorithms(聚類算法).
    • model.transform() : given an unsupervised model, transform new data into the new basis.
      This also accepts one argument X_new, and returns the new representation of the data based
      on the unsupervised model.
    • model.fit_transform() : some estimators implement this method,
      which more efficiently performs a fit and a transform on the same input data.

Model Validation

An important piece of machine learning is model validation: that is, determining how well your model will generalize from the training data to future unlabeled data. Let’s look at an example using the nearest neighbor classifier. This is a very simple classifier: it simply stores all training data, and for any unknown quantity, simply returns the label of the closest training point.

With the iris data, it very easily returns the correct prediction for each of the input points:

from sklearn.neighbors import KNeighborsClassifier
X, y = iris.data, iris.target
clf = KNeighborsClassifier(n_neighbors=1)
clf.fit(X, y)
y_pred = clf.predict(X)
print(np.all(y == y_pred))
>>True

A more useful way to look at the results is to view the confusion matrix(混淆矩陣), or the matrix showing the frequency (頻率矩陣)of inputs and outputs:

from sklearn.metrics import confusion_matrix
print(confusion_matrix(y, y_pred))
>>[[50  0  0]
 [ 0 50  0]
 [ 0  0 50]]

For each class, all 50 training samples are correctly identified. But this does not mean that our model is perfect! In particular(在特別情況下), such a model generalizes extremely poorly to new data. We can simulate this by splitting our data into a training set and a testing set. Scikit-learn contains some convenient routines to do this:

from sklearn.model_selection import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(X, y,test_size=0.3)
clf.fit(Xtrain, ytrain)
ypred = clf.predict(Xtest)
print(confusion_matrix(ytest, ypred))
>>[[12  0  0]
[ 0 17  0]
[ 0  1 15]]

This paints a better picture of the true performance of our classifier: apparently there is some confusion between the second and third species, which we might anticipate given what we’ve seen of the data above.

This is why it’s extremely important to use a train/test split when evaluating your models. We’ll go into more depth on model evaluation later in this tutorial.

Flow Chart: How to Choose your Estimator

這是由scikit-learn超級貢獻者[Andreas Mueller](https://github.com/amueller)創建的流程圖,它很好地總結了在各種情況下選擇哪種算法。 隨身攜帶以備參考!
在這裏插入圖片描述

Quick Application: Optical Character Recognition(光學字符識別)

爲了在一個更有趣的問題上演示上述原則,讓我們考慮OCR(光學字符識別),即識別手寫數字。在野外,這個問題涉及到定位和識別圖像中的字符。在這裏,我們將使用一個快捷方式,並使用scikit-learn的一組預格式化的數字,這是內置到庫中的。

加載和顯示數字數據

我們將使用scikit-learn的數據訪問界面,並查看以下數據:

from sklearn import datasets
digits = datasets.load_digits()
digits.images.shape
>>(1797, 8, 8)

Let’s plot a few of these:

fig, axes = plt.subplots(10, 10, figsize=(8, 8))
fig.subplots_adjust(hspace=0.1, wspace=0.1)

for i, ax in enumerate(axes.flat):
    ax.imshow(digits.images[i], cmap='binary', interpolation='nearest')
    ax.text(0.05, 0.05, str(digits.target[i]),
            transform=ax.transAxes, color='green')
    ax.set_xticks([])
    ax.set_yticks([])

在這裏插入圖片描述
這裏的數據只是8x8網格內的每個像素值:

# The images themselves
print(digits.images.shape)
print(digits.images[0])
>>(1797, 8, 8)
[[ 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.]]
# The data for use in our algorithms
print(digits.data.shape)
print(digits.data[0])
>>(1797, 64)
[ 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.]
# The target label
print(digits.target)
>>[0 1 2 ... 8 9 8]

無監督學習:降維

我們想在64維參數空間中可視化我們的點,但是很難在64維中繪製點!
相反,我們將使用無監督方法將尺寸減小到2。
在這裏,我們將使用稱爲Isomap的流形學習算法,並將數據轉換爲二維。

from sklearn.manifold import Isomap
iso = Isomap(n_components=2)
data_projected = iso.fit_transform(digits.data)
data_projected.shape
>>(1797, 2)
plt.scatter(data_projected[:, 0], data_projected[:, 1], c=digits.target,
            edgecolor='none', alpha=0.5, cmap=plt.cm.get_cmap('nipy_spectral', 10));
plt.colorbar(label='digit label', ticks=range(10))
plt.clim(-0.5, 9.5)

在這裏插入圖片描述
我們在這裏看到,數字在參數空間中是相當分開的。 這告訴我們,監督分類算法應能表現良好。 試一試吧。

數字分類

讓我們嘗試對數字進行分類任務。 我們要做的第一件事是將數字分成訓練和測試樣本:

from sklearn.model_selection import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(digits.data, digits.target,
                                                random_state=2)
print(Xtrain.shape, Xtest.shape)
>>(1347, 64) (450, 64)
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(penalty='l2')
clf.fit(Xtrain, ytrain)
ypred = clf.predict(Xtest)
from sklearn.metrics import accuracy_score
accuracy_score(ytest, ypred)
>>0.9466666666666667

這個數字並不能告訴我們我們出了什麼問題:一種不錯的方法是使用混淆矩陣

from sklearn.metrics import confusion_matrix
print(confusion_matrix(ytest, ypred))
>>[[42  0  0  0  0  0  0  0  0  0]
 [ 0 45  0  1  0  0  0  0  3  1]
 [ 0  0 47  0  0  0  0  0  0  0]
 [ 0  0  0 42  0  2  0  3  1  0]
 [ 0  2  0  0 36  0  0  0  1  1]
 [ 0  0  0  0  0 52  0  0  0  0]
 [ 0  0  0  0  0  0 42  0  1  0]
 [ 0  0  0  0  0  0  0 48  1  0]
 [ 0  2  0  0  0  0  0  0 38  0]
 [ 0  0  0  1  0  1  0  1  2 34]]
plt.imshow(np.log(confusion_matrix(ytest, ypred)),
          cmap='Blues', interpolation='nearest')
plt.grid(False)
plt.ylabel('true')
plt.xlabel('predicted');

在這裏插入圖片描述

fig, axes = plt.subplots(10, 10, figsize=(8, 8))
fig.subplots_adjust(hspace=0.1, wspace=0.1)

for i, ax in enumerate(axes.flat):
    ax.imshow(Xtest[i].reshape(8, 8), cmap='binary')
    ax.text(0.05, 0.05, str(ypred[i]),
            transform=ax.transAxes,
            color='green' if (ytest[i] == ypred[i]) else 'red')
    ax.set_xticks([])
    ax.set_yticks([])

在這裏插入圖片描述
有趣的是,即使使用這種簡單的邏輯迴歸算法,許多錯誤貼標籤的案例也是我們自己可能會出錯的案例!
有很多方法可以改進此分類器,但是我們在這裏沒有時間。 更進一步,我們可以使用更復雜的模型,使用交叉驗證或應用其他技術。 在本教程的後面,我們將介紹其中一些主題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章