4.2 Scikit-Learn簡介(機器學習篇)

第四章 機器學習

4.1 機器學習簡介

機器學習是用數據科學的計算能力和算法能力去彌補統計學的不足。git

基本統計學概念:誤差(bias)、方差(variance)、過擬合(overfitting)和欠擬合(underfitting)算法

4.1.1 機器學習分類

機器學習通常分爲:有監督學習和無監督學習。
有監督學習分爲:分類和迴歸任務,分類任務中,標籤都是離散值;迴歸任務中標籤都是連續值。
無監督學習分爲:聚類和降維任何。聚類算法將數據分紅不一樣的組別;降維算法追求更簡潔的方式表現數據。
半監督學習,一般在標籤數據不完整時使用。api

4.2 Scikit-Learn簡介

4.2.1 Scikit-Learn的數據表示

機器學習是從數據建立模型的學問,所以你首先須要瞭解怎樣表示數據才能讓計算機理解。sklearn認爲數據表示最好的方法就是用數據表的形式。數組

1.數據表

# 基本的數據表示二維網格數據,其中每一行表示數據集的樣本,而列表示構成每一個樣本的相關特徵。
import seaborn as sns
iris = sns.load_dataset('iris')
iris.head()
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

2.特徵矩陣

# 這個表格經過二維數組或矩陣的形式將信息清晰底表達出來,咱們記此類矩陣爲特徵矩陣。特徵矩陣一般被簡記爲X。
# 它是維度爲[n_samples, n_features]的二維矩陣。samples--樣本(行數),features--特徵數(列數)
# 1、樣本(即每一行)一般是指數據集中的每個對象。
# 2、特徵(即每一列)一般是指每一個樣本都具備的某種量化觀測值。通常,特徵都是實數值,但有時也多是布爾值或離散值。

3.目標數組

# 除了特徵矩陣x以外,還須要一個標籤或標籤數組,記爲y。目標數組通常是一維數組,
# 長度就是樣本總數n_samples,一般用一維的NumPy數組或者Pandas的Series表示。
# 目標數組能夠是連續的數值類型,也能夠是離散的類型/標籤。
%matplotlib inline
sns.set()
sns.pairplot(iris,hue='species',size=1.5)
# 從iris數據集中抽取特徵矩陣和目標數組
X_iris = iris.drop('species',axis=1)
print("X_iris:",X_iris.shape)
y_iris = iris['species']
print("y_iris:",y_iris.shape)
X_iris: (150, 4)
y_iris: (150,)

4.2.2 Scikit-Learn的評估器API

sklearn api主要遵循如下設計原則:dom

統一性:全部對象使用共同接口鏈接一組方法和統一的文檔。
內省:全部參數都是公共屬性。
限制對象層級:只有算法才能用Python類表示。數據集都用標準的數據類型(NumPy數組、Pandas DataFrame、SciPy稀疏矩陣)表示,參數名稱用標準的Python字符串。
函數組合:許多機器學習任務均可以用一串基本算法實現,sklearn儘可能支持這種可能。
明智的默認值:當模型須要用戶設置參數時,sklearn預先設置合適的默認值。
sklearn中的全部機器學習算法都是用過評估器API實現的,它爲機器學習應用提供統一的接口機器學習

1.API基礎知識

sklearn評估器API的經常使用步驟以下:函數

(1)經過從sklearn中導入適當的評估器類,選擇模型類。
(2)用合適的數值對模型類進行實例化,配置模型超參數。
(3)整理數據,獲取特徵矩陣和目標數組。
(4)調用模型實例的fit()方法對數據進行擬合。
(5)對新數據應用模型:
在有監督學習模型中,一般使用predict()方法預測新數據的標籤;
在無監督學習模型中,一般使用transform()或predict()方法轉換或推斷數據的性質。學習

2.有監督學習示例:簡單線性迴歸

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.RandomState(42)
x = 10 * rng.rand(50)
y = 2 * x - 1 + rng.randn(50)
# a.選擇模型類
from sklearn.linear_model import LinearRegression
# b.選擇模型超參數
# 問題:
#     咱們想要擬合偏移量(即直線的截距)嗎?
#     咱們須要對模型進行歸一化處理嗎?
#     咱們須要對特徵進行預處理以提升模型靈活性嗎?
#     咱們打算在模型中使用哪一種正則化類型?
#     咱們打算使用多少模型組件?
# 有一些重要的參數必須在選擇模型類時肯定好。這些參數一般被稱爲超參數,即在模型擬合以前必須肯定下來的參數。
model = LinearRegression(fit_intercept=True)  # 擬合直線截距
print("模型超參數:\n",model)
# c.抽取特徵矩陣和目標數據
X = x[:,np.newaxis]
print("特徵矩陣X:\n",X)
print("目標數組y:\n",y)
# d.擬合數據
model.fit(X,y)
# fit()方法會在模型內部進行大量運算,運算結果將存儲在模型屬性中,供用戶使用。
# 在sklearn中,全部經過fit()方法得到的模型參數都帶一條下劃線。如:線性模型中的模型參數以下:
print("模型的斜率:",model.coef_)
print("模型的截距:",model.intercept_)
# 模型訓練效果評價:
#     原數據由y = 2 * x - 1 + rng.randn(50)得到,從中看出直線斜率爲 2,截距爲 1
#     擬合模型的直線斜率爲 1.9776566,截距爲 -0.903310725531 偏差很小。
# e.預測新數據的標籤
xfit = np.linspace(-1,11)
Xfit = xfit[:,np.newaxis]
yfit = model.predict(Xfit)
plt.scatter(x,y)  # 散點圖
plt.plot(xfit,yfit)
模型超參數:
 LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
特徵矩陣X:
 [[ 3.74540119]
 [ 9.50714306]
 [ 7.31993942]
 [ 5.98658484]
 [ 1.5601864 ]
 [ 1.5599452 ]
 [ 0.58083612]
 [ 8.66176146]
 [ 6.01115012]
 [ 7.08072578]
 [ 0.20584494]
 [ 9.69909852]
 [ 8.32442641]
 [ 2.12339111]
 [ 1.81824967]
 [ 1.8340451 ]
 [ 3.04242243]
 [ 5.24756432]
 [ 4.31945019]
 [ 2.9122914 ]
 [ 6.11852895]
 [ 1.39493861]
 [ 2.92144649]
 [ 3.66361843]
 [ 4.56069984]
 [ 7.85175961]
 [ 1.99673782]
 [ 5.14234438]
 [ 5.92414569]
 [ 0.46450413]
 [ 6.07544852]
 [ 1.70524124]
 [ 0.65051593]
 [ 9.48885537]
 [ 9.65632033]
 [ 8.08397348]
 [ 3.04613769]
 [ 0.97672114]
 [ 6.84233027]
 [ 4.40152494]
 [ 1.22038235]
 [ 4.9517691 ]
 [ 0.34388521]
 [ 9.09320402]
 [ 2.58779982]
 [ 6.62522284]
 [ 3.11711076]
 [ 5.20068021]
 [ 5.46710279]
 [ 1.84854456]]
目標數組y:
 [  7.22926896  18.18565441  13.52423055  10.67206599   0.64185082
   1.4000462   -0.29896653  17.38064514  11.36591852  11.3984114
  -0.26422614  18.01311476  14.97193082   3.8584585    3.66749887
   3.59937032   4.24562734   9.18591626   7.9701638    5.80012793
  10.75788366   1.60421824   3.736558     5.13103024   8.93392551
  16.05975926   2.92146552  10.28822167  11.2099274   -0.7161115
  11.51229264   3.94851904   0.26520582  19.5423544   15.69289556
  15.98984947   5.17932245   0.65443493  12.77642131   5.81548096
   1.22109281   9.26065077   1.16566447  16.66813782   3.36710603
  11.74868864   6.14962364   9.73011153   9.40444538   3.21035654]
模型的斜率: [ 1.9776566]
模型的截距: -0.903310725531
[<matplotlib.lines.Line2D at 0x1e13980d1d0>]

3.有監督學習示例:鳶尾花數據分類

# 咱們將使用高斯樸素貝葉斯方法來訓練鳶尾花數據集,這個方法假設每一個特徵中屬於每一類的觀測值都符合高斯分佈。
# 由於高斯樸素貝葉斯方法速度很快,並且不須要選擇超參數,因此一般適合做爲初步分類手段,在藉助複雜模型進行優化以前使用。
from sklearn.naive_bayes import GaussianNB                  # 1.選擇模型類
model = GaussianNB()                                        # 2.初始化模型
from sklearn.cross_validation import train_test_split 
Xtrain,Xtest,ytrain,ytest = train_test_split(X_iris,y_iris) # 3.分割數據集
model.fit(Xtrain,ytrain)                                    # 4.擬合數據集
ypredict = model.predict(Xtest)                             # 5.預測數據集
from sklearn.metrics import accuracy_score
print(accuracy_score(ypredict,ytest))                       # 6.模型準確率評估
print(accuracy_score(ytest,ypredict))
# 準確率高達97%
0.947368421053
0.947368421053

4.無監督學習示例:鳶尾花數據降維

# 對鳶尾花數據集進行降維,以便能更方便地對數據進行可視化
# 降維的任務是要找到一個能夠保留數據本質特徵的低維矩陣來表示高維數據。
# 降維一般用於輔助數據可視化的工做,畢竟二維數據畫圖比多維甚至更高維的數據畫圖更方便。
# 主成分分析(principal component analysis,PCA)方法,這一種快速線性降維技術。
from sklearn.decomposition import PCA                    # 1.選擇模型類
model = PCA(n_components=2)                               # 2.設置超參數,初始化模型
model.fit(X_iris)                                         # 3.擬合模型
x_2D = model.transform(X_iris)                            # 4.將數據轉換爲二維
iris['PCA1'] = x_2D[:,0]
iris['PCA2'] = x_2D[:,1]
sns.lmplot("PCA1","PCA2",hue='species',data=iris,fit_reg=False)
# 從二維數據標示圖能夠看出,雖然PCA算法根本不知道花的種類標籤,但不一樣種類的花仍是
# 被清晰地區分開來! 這代表用一種比較簡單的分類方法就可以有效地學習這份數據集。
<seaborn.axisgrid.FacetGrid at 0x1e139168198>

5.無監督學習示例:鳶尾花數據聚類

# 聚類方法是要對沒有標籤的數據集進行分組。
# 使用一個強大的聚類方法----高斯混合模型(Guassian mixture model,GMM)。
# GMM模型試圖將數據構形成若干服從高斯分佈的機率密度函數鏃。
from sklearn.mixture import GaussianMixture                         # 1.選擇模型類
model = GaussianMixture(n_components=3,covariance_type='full')       # 2.設置超參數,初始化模型     組件數量,協方差類型
model.fit(X_iris)                                                    # 3.擬合數據
y_predict = model.predict(X_iris)                                    # 4.預測簇標籤
iris['cluster'] = y_predict                                         
sns.lmplot("PCA1","PCA2",data=iris,hue='species',col='cluster',fit_reg=False)
# 根據簇數量對數據進行分割,就會清晰地看出GaussianMixture算法的訓練效果:setosa類的花在簇0中
# 被完美底區分出來,惟一的遺憾是第二幅圖中的versicolor和virginical還有一點混淆。
# 這就說明,即便沒有專家告訴完美每朵花的具體類型,但因爲每種花的特徵差別很大,
# 所以完美也能夠經過簡單的聚類算法自動識別出不一樣種類的花!
# 這種算法還能夠幫助專家們探索觀察樣本之間的關聯性。
<seaborn.axisgrid.FacetGrid at 0x1e13c455630>

4.2.3 應用:手寫數字探索

1.加載並可視化手寫數字

from sklearn.datasets import load_digits
digits = load_digits()
digits.images.shape
# 這份圖像數據是一個三維矩陣:共有1797個樣本,每張圖像都是8 × 8 像素。對前100張圖進行可視化:
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')
    
# 爲了在sklearn中使用數據,須要一個維度爲[n_samples, n_features]的二維特徵矩陣
# 能夠將每一個樣本圖像的全部像素都做爲特徵,也就是將每一個數字的8 × 8像素平鋪成長度爲64的一維數組。
# 另外,還須要一個目標數組,用來表示每一個數字的真實值(標籤)。這兩份數據已經放在手寫數字數據集
# 的data與target屬性中,直接使用便可:
X = digits.data
y = digits.target
print("X的形狀:",X.shape,"\n",X)
print("y的形狀:",y.shape,"\n",y)
# 從上面能夠看出,一共有1797個樣本和64個特徵。
X的形狀: (1797, 64) 
 [[  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.]]
y的形狀: (1797,) 
 [0 1 2 ..., 8 9 8]

2.無監督學習:降維

# 雖然咱們想對具備64維參數控件的樣本進行可視化,可是咋如此高緯度的控件中進行可視化十分困難。
# 所以,咱們須要藉助無監督學習方法將維度降到二維。
# 此次試試流行學學習算法中的isomap算法對數據域進行降維:
from sklearn.manifold import Isomap            # 1.選擇模型類
model = Isomap(n_components=2)                  # 2.設置超參數,模型初始化
model.fit(X)                                    # 3.擬合模型
data_projected = model.transform(X)             # 4.將數據轉爲二維
print(data_projected.shape)                 
# 如今數據已經投影到二維。把數據畫出來,看看從結構中能發現什麼:
plt.scatter(data_projected[:,0],data_projected[:,1],c=y,
           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)

# 這幅圖呈現除了很是直觀的效果,讓咱們知道數字在64維空間中的分離(可識別)程度。
# 例如,在參數空間中,數字0和數字1基本不會重疊。
# 另外,從圖中會發現,數字1和數字4好像有點兒混淆---也許有人寫數字1時喜歡在上面加個「帽子」,所以看起來像數字4.
# 雖然有些瑕癖,但從整體上看,各個數字在參數空間中的分離程度仍是使人滿意的。
# 這其實告訴完美;用一個很是簡單的有監督分類算法就能夠完成任務。
(1797, 2)

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_predict = model.predict(Xtest)
from sklearn.metrics import accuracy_score
print(accuracy_score(y_predict,ytest))
# 能夠看出,經過一個很是簡單的模型,數字識別率就能夠達到80%以上!但僅依靠這個指標,
# 咱們沒法知道模型哪裏作的很差,解決這個問題的辦法就是用混淆矩陣。
# 能夠用sklearn計算混淆矩陣,而後用seaborn畫出來:
from sklearn.metrics import confusion_matrix
mat = confusion_matrix(ytest,y_predict)
sns.heatmap(mat,square=True,annot=True,cbar=False)
plt.xlabel('predicted value')
plt.ylabel('true value')
# 從圖中能夠看出,誤判的主要緣由是許多數字2被誤判成了數字1和數字8.
0.833333333333
<matplotlib.text.Text at 0x1e13b0dccc0>

# 另外一種顯示模型特徵的直觀方式是將樣本畫出來,而後把預測標籤放在左下角,用綠色表示預測正確,用紅色表示預測錯誤:
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_predict[i]),
           transform=ax.transAxes,
           color='green' if (ytest[i] == y_predict[i]) else 'red')
# 經過觀察這部分樣本數據,咱們能自動模型哪裏的學習不夠好。若是但願分類準確率達到90%以上
# 可能須要藉助更加複雜的算法,例如支持向量機、隨機森林,或者其餘分類算法。

相關文章
相關標籤/搜索