天天看點

學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

此前小天分享了PyTorc幹貨的Scikit-Learn上篇(點選藍字可直接閱讀),看完下篇希望你能馬上學溜PyTorch!(萬一這回就學以緻用了呢,我先收藏為敬)

講完Scikit-Learn的資料表示和評估器API的基礎知識、簡單線性回歸,小天将在本文中為大家帶來鸢尾花資料的分類、降維和聚類,還有手寫資料的探索,耐心往下看吧~

學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

Scikit-Learn·下篇

有監督學習示例:鸢尾花資料分類

如何為鸢尾花資料集建立模型,先用一部分資料進行訓練,再用模型預測出其他樣本的标簽?

我們将使用非常簡單的高斯樸素貝葉斯(Gaussian naive Bayes)方法完成這個任務,這個方法假設每個特征中屬于每一類的觀測值都符合高斯分布。因為高斯樸素貝葉斯方法速度很快,而且不需要選擇超參數,是以通常很适合作為初步分類手段,再借助更複雜的模型進行優化之前使用。

先将資料分割成訓練集(training set)和測試集(testing set),借助train_test_split 函數

from sklearn.cross_validation import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(X_iris, y_iris,
                                                random_state=1)           

用下面的模型來預測标簽

from sklearn.naive_bayes import GaussianNB      #1.選擇模型類
model = GaussianNB()                          #2.初始化模型
model.fit(Xtrain, ytrain)                      #3.用模型拟合資料
y_model = model.predict(Xtest)                 #4.對新資料進行預測           

用accuracy_score 工具驗證模型預測結果的準确率(預測的所有結果中,正确結果占總預測樣本數的比例)

from sklearn.metrics import accuracy_score
accuracy_score(ytest, y_model)           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

準确率竟然高達97%,常簡單的分類算法也可以有效地學習這個資料集!

無監督學習示例:鸢尾花資料降維

無監督學習問題——對鸢尾花資料集進行降維,以便能更友善地對資料進行可視化。鸢尾花資料集由四個次元構成,即每個樣本都有四個次元。

降維的任務是要找到一個可以保留資料本質特征的低維矩陣來表示高維資料。降維通常用于輔助資料可視化的工作,畢竟用二維資料畫圖比用四維甚至更高維的資料畫圖更友善!

使用主成分分析(principal component analysis,PCA)方法,這是一種快速線性降維技術。

from sklearn.decomposition import PCA  # 1.選擇模型類
model = PCA(n_components=2)            # 2.設定超參數,初始化模型
model.fit(X_iris)                      # 3.拟合資料,注意這裡不用y變量
X_2D = model.transform(X_iris)         # 4. 将資料轉換為二維           

畫出結果,将二維資料插入到鸢尾花的DataFrame 中,然後用 Seaborn 的lmplot 方法畫圖。

iris['PCA1'] = X_2D[:, 0]
iris['PCA2'] = X_2D[:, 1]
sns.lmplot("PCA1", "PCA2", hue='species', data=iris, fit_reg=False);           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

二維資料表示圖可以看出,雖然PCA 算法根本不知道花的種類标簽,但不同種類的花還是被很清晰地區分開來。

無監督學習示例:鸢尾花資料聚類

對鸢尾花資料進行聚類。聚類算法是要對沒有任何标簽的資料集進行分組。我們将用一個強大的聚類方法——高斯混合模型(Gaussian mixture model,GMM)

from sklearn.mixture import GaussianMixture       #1.選擇模型類

model = GaussianMixture(n_components=3,
                      covariance_type='full')
#SK-Learn 0.18
#model = GMM(n_components=3,
#            covariance_type='full')   #2.設定超參數,初始化模型
model.fit(X_iris)                    #3.拟合資料,注意不需要y變量
y_gmm = model.predict(X_iris)         #4. 确定簇标簽           

用Seaborn畫出結果

iris['cluster'] = y_gmm
sns.lmplot("PCA1", "PCA2", data=iris, hue='species',
           col='cluster', fit_reg=False);           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

GMM 算法的訓練效果:setosa(山鸢尾花)類的花在簇0 中被完美地區分出來,唯一的遺憾是第三幅圖中versicolor(變色鸢尾 花)和virginicaI(維吉尼亞鸢尾花)還有一點混淆。

1.3 應用:手寫數字探索

手寫數字識别:簡單點說,這個問題包括圖像中字元的定位和識别兩部分。為了示範友善,我們選擇使用Scikit-Learn 中自帶的手寫數字資料集。

加載并可視化手寫數字

from sklearn.datasets import load_digits
digits = load_digits()
digits.images.shape           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

圖像資料是一個三維矩陣:共有1797個樣本,每張圖像都是8像素×8像素

import matplotlib.pyplot as plt

fig, axes = plt.subplots(10, 10, figsize=(8, 8),
                         subplot_kw={'xticks':[], 'yticks':[]},
                         gridspec_kw=dict(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')
           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

在Scikit-Learn 中使用資料,需要一個次元為[n_samples, n_features] 的二維特征矩陣——可以将每個樣本圖像的所有像素都作為特征,也就是将每個數字的8 像素×8 像素平鋪成長度為64 的一維數組。另外,還需要一個目标數組,用來表示每個數字的真實值(标簽)。這兩份資料已經放在手寫數字資料集的data 與target 屬性中,直接使用即可:

X = digits.data
X.shape           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】
y = digits.target
y.shape           

無監督學習:降維

想對具有64 維參數空間的樣本進行可視化,但是在如此高次元的空間中進行可視化十分困難;借助無監督學習方法将次元降到二維。這次試試流形學習算法中的Isomap算法對資料進行降維。

from sklearn.manifold import Isomap
iso = Isomap(n_components=2)
iso.fit(digits.data)
data_projected = iso.transform(digits.data)
data_projected.shape
           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

資料已經投影到二維,把資料畫出來;

plt.scatter(data_projected[:, 0], data_projected[:, 1], c=digits.target, s=20,
            edgecolor='none', alpha=0.5,
            cmap=plt.cm.get_cmap('Spectral', 10))
plt.colorbar(label='digit label', ticks=range(10))
plt.clim(-0.5, 9.5);           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

這幅圖呈現出了非常直覺的效果,讓我們知道數字在64 維空間中的分離(可識别)程度。

例如,在參數空間中,數字0和數字1基本不會重疊。根據常識也是如此:數字0 是中間一片空白,而數字1 是中間一片黑。另外,從圖中會發現,數字1 和數字4 好像有點兒混淆——也許是有些人寫數字1 的時候喜歡在上面加個“帽子”,是以看起來就像是數字4。

數字分類

我們需要找到一個分類算法,對手寫數字進行分類。

将資料分成訓練集和測試集,然後用高斯樸素貝葉斯模型來拟合:

Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, random_state=0)
from sklearn.naive_bayes import GaussianNB
model = GaussianNB()
model.fit(Xtrain, ytrain)
y_model = model.predict(Xtest)           

獲得模型的準确率

from sklearn.metrics import accuracy_score
accuracy_score(ytest, y_model)
           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

一個非常簡單的模型,數字識别率就可以達到80%以上!但僅依靠這個名額,我們無法知道模型哪裡做得不夠好,解決這個問題的辦法就是用混淆矩陣(confusionmatrix)。可以用Scikit-Learn 計算混淆矩陣,然後用Seaborn畫出來。

from sklearn.metrics import confusion_matrix

mat = confusion_matrix(ytest, y_model)

sns.heatmap(mat, square=True, annot=True, cbar=False)
plt.xlabel('predicted value')
plt.ylabel('true value');           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

從圖中可以看出,誤判的主要原因在于許多數字2 被誤判成了數字1或數字8。另一種顯示模型特征的直覺方式是将樣本畫出來,然後把預測标簽放在左下角,用綠色表示預測正确,用紅色表示預測錯誤

fig, axes = plt.subplots(10, 10, figsize=(8, 8),
                         subplot_kw={'xticks':[], 'yticks':[]},
                         gridspec_kw=dict(hspace=0.1, wspace=0.1))

test_images = Xtest.reshape(-1, 8, 8)

for i, ax in enumerate(axes.flat):
    ax.imshow(test_images[i], cmap='binary', interpolation='nearest')
    ax.text(0.05, 0.05, str(y_model[i]),
            transform=ax.transAxes,
            color='green' if (ytest[i] == y_model[i]) else 'red')           
學好Scikit-Learn,于是你默默地推了一下酷酷的墨鏡【下篇】

通過觀察這部分樣本資料,我們能知道模型哪裡的學習不夠好。如果希望分類準确率達到80% 以上,可能需要借助更加複雜的算法,例如支援向量機、随機森林,或者其他分類算法。

1.4 小結

本節介紹了Scikit-Learn 中資料表示方法和評估器API 的基本特征。除了評估器的類型不同,導入模型/ 初始化模型/ 拟合資料/ 預測資料的步驟是完全相同的。對評估器API 有了基本認識之後,你可以參考Scikit-Learn 文檔繼續學習更多知識,并在你的資料上嘗試不同的模型哦~

繼續閱讀