scikit_learn分類器詳解


1       分類

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

1.1  MINIST數字圖片集分類

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

 

 

 

(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()#畫出矩陣圖片顯示數字

 

 

 

(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

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

 

 

 

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%。

 

 

 

(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()

 

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

 

 

 

 

 

 

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%。

 

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

 

 

 

 

 

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()

 

 

 

 

如你所見, 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()

 

 

 

主對角線上意味着被分類 正確。數字    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()

 

 

 

第   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)

 

 

 

 

自己開發了一個股票智能分析軟件,功能很強大,需要的點擊下面的鏈接獲取:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM