天天看點

scikit_learn分類器詳解

1       分類

分類是将事物按特性進行分類,例如将手寫數字圖檔分類為對應的數字。

1.1  MINIST數字圖檔集分類

MINST就是一個70000張規格較小的手寫數字圖檔,如何将他們分類為對應的數字?MINIST這個資料集是由矩陣數組結構,70000個矩陣,每個矩陣28*28=784,每個點代表一個像素值,取值範圍在0-256之間。

scikit_learn分類器詳解

(1)擷取資料集

Scikit-Learn 提供了許多輔助函數,以便于下載下傳流行的資料集。

from      sklearn.datasets   import   fetch_mldata

>>> mnist     =     fetch_mldata('MNIST      original')#擷取數字資料集

>>> mnist {'COL_NAMES':    ['label',  'data'], 'DESCR': 'mldata.org       dataset:  mnist-original', 'data': array([[0,      0,    0,    ...,   0,    0,    0],                                                                               [0,   0,    0,    ...,   0,    0,       0],                                                                                       [0,   0,    0,       ...,   0,    0,    0],                                                                                                            ...,                                                                                                            [0,   0,    0,    ...,   0,    0,    0],                                                                                       [0,   0,    0,    ...,   0,    0,    0],                                                                                       [0,   0,    0,    ...,   0,    0,    0]],       dtype=uint8), 'target': array([   0.,   0.,   0.,   ...,   9.,   9.,   9.])}

data是資料集,target是目标數字,也就是每個圖檔矩陣代表的真實數字。

(2)擷取其中一個圖檔資料轉換後畫圖顯示

x,    y     =     mnist["data"],     mnist["target"] #擷取資料集中的資料

%matplotlib inline#聲明使用jupyter的後端渲染圖檔

 import matplotlib import       matplotlib.pyplot as    plt #引入畫圖

some_digit   =     X[36000] #取第36000個資料,是一個784的長形數組

some_digit_image     =     some_digit.reshape(28,    28) #轉換為28*28的矩陣

plt.imshow(some_digit_image,      cmap     =     matplotlib.cm.binary,       interpolation="nearest") plt.axis("off") plt.show()#畫出矩陣圖檔顯示數字

scikit_learn分類器詳解

(3)準備資料訓練

分成了一個訓練集(前  60000    張圖檔)和一個測試集(最後       10000    張圖檔),冒号在前表示取前60000之前的資料,冒号在後表示取60000之後的資料。

X_train, X_test,   y_train,  y_test    =     X[:60000],   X[60000:],       y[:60000],y[60000:]

打亂訓練集,洗牌,避免不均勻分布。

import   numpy   as    np

shuffle_index      =     np.random.permutation(60000) X_train,     y_train       =     X_train[shuffle_index],    y_train[shuffle_index]

1.2  二分類器訓練

二分類器就是是和否的分類,比較簡單。

(1)首先擷取訓練集和測試集中的為5的資料子集

y_train_5      =     (y_train ==  5)    #     True       for  all   5s,   False      for       all   other

digits. y_test_5    =     (y_test   ==  5)

(2)用Scikit-Learn       的   SGDClassifier分類器去訓練。這個分類器能夠高效地處理非常大的資料 集。可以一次隻處理一條資料,适合線上學習。

from      sklearn.linear_model import   SGDClassifier #引入

sgd_clf  =     SGDClassifier(random_state=42) #建立分類器對象

sgd_clf.fit(X_train,    y_train_5)#訓練

sgd_clf.predict([some_digit]) #測試

array([   True],    dtype=bool)#測試結果正确

1.3  性能評估

1.3.1         使用交叉驗證評估性能

讓我們使用 cross_val_score()       函數來評估 SGDClassifier     模型,同時使用K折交叉驗證,此 處讓    k=3 。即兩組訓練,一組測試,共測試三輪。

from      sklearn.model_selection   import   cross_val_score

cross_val_score(sgd_clf,  X_train, y_train_5,     cv=3,       scoring="accuracy")

array([   0.9502   ,      0.96565,       0.96495]

1.3.2         混淆矩陣

(1)混淆矩陣的定義

混淆矩陣是指列舉出判斷錯誤和判斷正确的次數的矩陣。例如上面的二分器,判斷為非5的正确的和錯誤,已經判斷為5的正确的和錯誤的。得到一個2*2的矩陣。為了計算混淆矩陣,首先你需要有一系列的預測值,這樣才能将預測值與真實值做比較。

(2)擷取預測值

from      sklearn.model_selection   import   cross_val_predict y_train_pred =     cross_val_predict(sgd_clf,     X_train, y_train_5,       cv=3)

cross_val_predict()    也使用  K折交叉驗證。傳回基于每一個測試折做出的一個預測值。

(3)根據預測值和實際值生成混淆矩陣

在使用         confusion_matrix()    函數,你将會得到一個混淆矩陣。傳遞目标類(y_train_5)和預 測類(       y_train_pred )給它。

>>> from      sklearn.metrics   import   confusion_matrix

>>> confusion_matrix(y_train_5, y_train_pred)

array([[53272,     1307],                                             

       [      1077,     4344]])

53272表示判斷為正确的非5(true negative),1307表示判斷為錯誤的非5(false negative)。1077表示判斷為錯誤的5(false positive),4344表示判斷為正确的5(true positive)。

(4)準确率和召回率定義

準确率(precision):true positive/( true positive+ false positive)=4344/(1077+4344)

召回率(recall):也叫做敏 感度(sensitivity)或者真正例率(true       positive rate,    TPR)

recall=ture positive/(true postive+false negative)=4344/(4344+1307)

(1)   準确率和召回率函數計算

Scikit-Learn 提供了一些函數去計算分類器的名額,包括準确率和召回率。

>>> from      sklearn.metrics   import   precision_score,  recall_score

>>> precision_score(y_train_5,      y_pred)  #     ==  4344      /      (4344       +     1307) 0.76871350203503808

>>> recall_score(y_train_5,     y_train_pred)      #     ==  4344      /       (4344     +     1077) 0.79136690647482011

(2)   調和平均值F1

常結合準确率和召回率來綜合的判斷算法的準确性。還需要綜合實際應用場景,綜合考慮采用哪種作為準确性的判斷的需要。當準确性和召回率都高的時候,調和平均值才會高。

scikit_learn分類器詳解

1.3.3         準确性和召回率的折中

(1)準确性和召回率不能同時提升?

通常情況下提高準确性會降低召回率,反之亦然,即他們是互斥的。為什麼準确性和召回率不能同時提升?按照公式将false positive和false negative值都減小不就可以同時提高準确性和召回率,理想情況下,false positive和false negative都為0,準确性和召回率都為100%,為什麼不能同時提高呢?

precision=true positive/( true positive+ false positive)=4344/(1077+4344)

recall=ture positive/(true postive+false negative)=4344/(4344+1307)

(2)原因分析

如下圖所示,    SGDClassifier分類器會對分析的資料進行評分,然後按照分數從小到大排列,設定一個門檻值,大于門檻值時判定為positive,小于門檻值判定為negative。門檻值越大準确性越高,但是同時有些是5的資料被判定到negative中,變成false negative,雖然準确性達到100%,但是false negative的數量也增加了,召回率變成50%。

scikit_learn分類器詳解

(3)擷取單個資料評分值

Scikit-Learn 不讓你直接設定門檻值,但是它給你提供了擷取決策分數的方法decision_function()。這個方法傳回每一個樣例的分數值,你自己設定門檻值去預測。

>>>some_digit   =     X[36000]#取一個資料

>>> y_score  =     sgd_clf.decision_function([some_digit])#擷取這個資料的評分值

 >>>     y_scores #顯示評分值

array([   161855.74572176])

>>> threshold      =     0 #設定門檻值為0

>>> y_some_digit_pred=(y_scores>threshold) #布爾值指派顯示y_score大于0是以為true

array([   True],    dtype=bool)

>>> threshold      =     200000#重新設定門檻值200000

 >>>     y_some_digit_pred    =(y_score     >threshold) # y_score小于門檻值

>>> y_some_digit_pred array([False],  dtype=bool)#得出false

(1)   擷取所有資料的評分值

用cross_val_predict()交叉預測方法,設定method="decision_function",得到的不是預測值,而是得到每一個樣例的分數值。

y_scores       =     cross_val_predict(sgd_clf,     X_train, y_train_5,       cv=3,     method="decision_function")

(5)根據評分調用函數precision_recall_curve計算準确率和召回率

現在有了這些分數值。對于任何可能的門檻值,使用       precision_recall_curve()  ,你都可以計算 準确率和召回率:

from      sklearn.metrics   import   precision_recall_curve

precisions,    recalls,  thresholds     =       precision_recall_curve(y_train_5,      y_scores)

(6)定義畫圖函數畫出準确率和召回率相對于不同門檻值的曲線

def  plot_precision_recall_vs_threshold(precisions,  recalls,  thresholds):                      plt.plot(thresholds,     precisions[:-1],    "b--",       label="Precision")                          plt.plot(thresholds,     recalls[:-1],       "g-",      label="Recall")                        plt.xlabel("Threshold")                        

plt.legend(loc="upper      left")                          

plt.ylim([0,   1])

 plot_precision_recall_vs_threshold(precisions, recalls,  thresholds) plt.show()

scikit_learn分類器詳解

你可以畫出準确率和召回率的曲線圖,在曲線圖上根據實際項目應用确定準确率和召回率。

scikit_learn分類器詳解

1.3.4         ROC曲線

(1)定義

ROC(Receiver Operating Characteristic)曲線是橫坐标為假正率,縱坐标為真正率的曲線圖。假正率是指判為真的當中假的數量,站總的假的數量的比值。真正率是指判為真的當中真的數量占總的真的數量的比值,和召回率意義一樣。還用之前的例子,如下圖所示,共有12個數字,其中6個是真5,其他6個是假5。左一位置處,真正率為6/6=100%,假正率為2/6的33.33%。中間位置,真正率為4/6=66.66%,假正率為1/6=16.67%。右側位置處,真正率為3/6=50%,假正率為0/6=0%。

scikit_learn分類器詳解

(2)    曲線下方面積比較分類器性能

scikit_learn分類器詳解

roc曲線下面的面積越大,或roc曲線越靠左上角,性能越好,測量ROC曲線下的面積(AUC)評估分類器的好壞。Scikit-Learn      提供了一個函 數來計算    ROC      AUC:

>>> from      sklearn.metrics   import   roc_auc_score

 >>>     roc_auc_score(y_train_5, y_scores)

0.97061072797174941

(3)畫出曲線圖比較性能

也可以畫出兩個分類器的ROC曲線,看誰更接近左上角。

1)計算SGDClassifier分類器

為了畫出     ROC      曲線,你首先需要計算各種不同門檻值下的       TPR、FPR,使用     roc_curve()  函 數:

from      sklearn.metrics   import   roc_curve

fpr,  tpr,  thresholds     =     roc_curve(y_train_5, y_scores)

2)計算RandomForestClassifier的TPR和FPR

RandomForestClassifier   不提供  decision_function()   方法。相反,它提供 predict_proba()方法,傳回一個數組,每一行代表一個數字記錄,每一列代表所屬于的類别,數組中數值含義是這一行這個數是這一列這個類的機率。例如數字判斷中,每一列是“是5”和“非5”,每一行是一個圖檔記錄,數組中的值是圖檔“是5”和“非5”的機率,把這個機率值作為評分值。

from      sklearn.ensemble import   RandomForestClassifier

forest_clf      =     RandomForestClassifier(random_state=42)

y_probas_forest  =     cross_val_predict(forest_clf,   X_train, y_train_5,       cv=3,method="predict_proba")

y_scores_forest   =     y_probas_forest[:,      1]    #     是5的機率值作為評分

 fpr_forest,  tpr_forest,    thresholds_forest =       roc_curve(y_train_5,y_scores_forest)

3)畫出曲線圖

plt.plot(fpr,   tpr,  "b:",       label="SGD") #SGD的ROC曲線圖

plot_roc_curve(fpr_forest,      tpr_forest,    "Random      Forest") #随機森林的ROC

plt.legend(loc="bottom    right")

 plt.show()

scikit_learn分類器詳解

如你所見, RandomForestClassifier   的   ROC      曲線比       SGDClassifier     的好得多:它更靠近左上 角。是以,它的       ROC      AUC      也會更大。

>>> roc_auc_score(y_train_5, y_scores_forest)

0.99312433660038291

1.4  多分類器

1.4.1         定義

二分類器隻能區分兩個類,而多類分類器(也被叫做多項式分類器)可以區分多于兩個類。如随機森林分類器或者樸素貝葉斯分類器可以直接處理多類分類。(比如   SVM      分類器或者線性分類器)則是嚴格的二分類器。

一對所有(ONE VS ALL):例如訓練0~9共10個分類器,你想對某張 圖檔進行分類的時候,讓每一個分類器對這個圖檔進行分類,選出決策分數最高的那個分類 器。

一對1=一(ONE VS ONE)0,1之間,0,2之間……,共N(N-1)/2分類器,當你想對一張圖檔進行分類,你必須将這張圖檔跑在全部45個二分類器上。然後 看哪個類勝出。

1.4.2         SGDClassifier實作多分類

>>> sgd_clf.fit(X_train,    y_train) #     訓練

 >>>     sgd_clf.predict([some_digit])#預測輸出是 array([  5.])

>>> some_digit_scores     =       sgd_clf.decision_function([some_digit]) >>>   some_digit_scores array([[-311402.62954431,      -363517.28355739,    -446449.5306454       ,                                                       -183226.61023518,    -414337.15339485,     161855.74572176,                                                      -452576.39616343,    -471957.14962573,    -518542.33997148,                                                     -536774.63961222]])#擷取評分

>>> np.argmax(some_digit_scores) #輸出評分最大的結果是5

1.4.3         OneVsOneClassifier 類 或者OneVsRestClassifier類

>>> from      sklearn.multiclass      import   OneVsOneClassifier

>>> ovo_clf  =       OneVsOneClassifier(SGDClassifier(random_state=42)) >>>       ovo_clf.fit(X_train,   y_train)

 >>>     ovo_clf.predict([some_digit])

array([   5.])

>>> len(ovo_clf.estimators_) 45

1.4.4         RandomForestClassifier多分類

随機森林分類器能夠直接将一個樣例 分到多個類别。你可以調用       predict_proba()   ,得到樣例對應的類别的機率值的清單。

>>> forest_clf.fit(X_train, y_train)

>>> forest_clf.predict([some_digit])

array([   5.])

>>> forest_clf.predict_proba([some_digit]) array([[  0.1, 0.    ,      0.    ,       0.1, 0.    ,      0.8, 0.    ,      0.    ,      0.    ,      0.    ]])

1.5  誤差分析

探索方案,嘗試多種模型,選擇最好的模型,用GridSearchCV調試超參數優化模型。要使用     cross_val_predict()    做出預測,然後調 用   confusion_matrix()函數。

>>> y_train_pred =     cross_val_predict(sgd_clf,      X_train_scaled,       y_train,  cv=3)

>>> conf_mx       =     confusion_matrix(y_train, y_train_pred) >>>       conf_mx array([[5725,      3,    24,  9,    10,  49,  50,  10,  39,  4],                                                    [      2,    6493,     43,  25,  7,    40,  5,    10,       109,       8],                                                    [      51,  41,  5321,    104,       89,  26,  87,  60,  166,       13],                                                  [      47,       46,  141,       5342,     1,    231,       40,  50,  141,       92],                                                  [      19,  29,  41,  10,  5366,     9,    56,  37,  86,       189],                                                       [      73,  45,  36,  193,       64,       4582,     111, 30,  193,       94],                                                  [      29,       34,  44,  2,    42,  85,  5627,     10,  45,  0],                                                    [      25,  24,  74,  32,  54,  12,  6,    5787,     15,  236],                                                       [      52,  161,       73,  156,       10,  163,       61,       25,  5027,     123],                                                       [      43,  35,  26,       92,  178,       28,  2,    223,       82,  5240]])

       Matplotlib    的   matshow()  函數,将混淆矩陣以圖像的方式呈現,将會更 加友善。

plt.matshow(conf_mx,      cmap=plt.cm.gray)

plt.show()

scikit_learn分類器詳解

主對角線上意味着被分類 正确。數字    5     對應的格子看起來比其他數字要暗淡許多。資料集當中數字      5     的圖檔 比較少,又或者是分類器對于數字   5的表現不如其他數字那麼好。

将混淆矩陣的每一個值除以相應類别的 圖檔的總數目。這樣子,你可以比較錯誤率,而不是絕對的錯誤數(這對大的類别不公平)。用       0     來填充對角線正确的分類。最後得到的就是錯誤率的矩陣和圖像。

row_sums     =     conf_mx.sum(axis=1, keepdims=True)

norm_conf_mx   =     conf_mx       /      row_sums

np.fill_diagonal(norm_conf_mx,   0)

plt.matshow(norm_conf_mx,  cmap=plt.cm.gray)

plt.show()

scikit_learn分類器詳解

第   8、9      列相當亮,這告訴你許多圖檔被誤分成數字 8     或者數字   9,第一行很暗,這意味着大部分的數字       1     被正确分類。分析混淆矩陣通常可以給你提供深刻的見解去改善你的分類器。回顧這幅圖,看樣子你應該 努力改善分類器在數字      8     和數字  9     上的表現,和糾正       3/5  的混淆

1.6  多标簽分類KNeighborsClassifier

(1)分類實作

讓你的分類器給 一個樣例輸出多個類别。例如一個人臉識别分類器,這個分類 器被訓練成識别三個人臉,Alice,Bob,Charlie;然後當它被輸入一張含有       Alice     和   Bob 的 圖檔,它應該輸出    [1,   0,       1]    。(意思是:Alice    是,Bob      不是,Charlie    是)。這種輸出多個二 值标簽的分類系統被叫做多标簽分類系統。例如要對數字進行分類,兩個要求(1)大于等于7;(2)是奇數。

from      sklearn.neighbors       import   KNeighborsClassifier #引入分類器

y_train_large      =     (y_train >=  7)#大于7的目标值

 y_train_odd       =     (y_train %    2     ==  1) #是奇數的目标值

y_multilabel =     np.c_[y_train_large,  y_train_odd] #組合兩種分類值

knn_clf  =     KNeighborsClassifier()#建立分類器對象

 knn_clf.fit(X_train, y_multilabel)#進行分類訓練

>>> knn_clf.predict([some_digit]) #輸出5的預測值

array([[False,      True]],   dtype=bool)#結果為小于7,是奇數

(2)F1值評估分類器

       y_train_knn_pred      =     cross_val_predict(knn_clf,      X_train,       y_train,  cv=3)

>>> f1_score(y_train, y_train_knn_pred,     average="macro") #平均

0.96845540180280221

,如果你的 Alice     的照片比 Bob   或者      Charlie  更多的時候,也許你想讓分類器在   Alice     的照片上具有更大的權重。設定       average="weighted"  。

1.7  多輸出分類

是多标簽分類的簡單泛化,在這裡每一個标簽可以是多類别的(比如說,它可以有多于兩個可能值)。例如去除噪音的系統,輸入是含有噪音的圖檔,輸出是一個幹淨的數字圖檔,由像素強度數組表示,一個像素是一個标簽,每個标簽的取值是 0~255。标簽的取值多範圍就是多輸出分類。

我們先給訓練資料加上噪音,然後再進行降噪處理。

noise      =     rnd.randint(0,      100,       (len(X_train),      784)) #制造噪音

noise      =     rnd.randint(0,      100,       (len(X_test), 784))

X_train_mod       =     X_train  +     noise #加上噪音

X_test_mod =     X_test    +     noise

y_train_mod =     X_train

y_test_mod  =     X_test

knn_clf.fit(X_train_mod, y_train_mod) #訓練KNeighborsClassifier分類器

clean_digit   =     knn_clf.predict([X_test_mod[some_index]]) #輸出降噪預測值

plot_digit(clean_digit)

scikit_learn分類器詳解

自己開發了一個股票智能分析軟體,功能很強大,需要的點選下面的連結擷取:

https://www.cnblogs.com/bclshuai/p/11380657.html