0. 前言
- “盡管新技術新算法層出不窮,但是掌握好基礎算法就能解決手頭 90% 的機器學習問題。”
- 本系列參考書 "Hands-on machine learning with scikit-learn and tensorflow"以及kaggle相關資料
1. MNIST 數據集
MNIST是最常用的用來實驗分類模型的數據集,有7w多張手寫0-9的白底黑字數字圖像,每張圖像大小 28*28,共784個像素,像素取值范圍為[0-255],0表示白色背景,255表示純黑,如下圖:
2. 二分類器
數字識別是個多分類問題,首先我們從兩分類問題開始入手,即判斷一張圖片是5或者非5。應用sklearn線性模型的SGDClassifier直接訓練,損失函數默認是 hinge loss,即SVM分類器,如果想用logistic regression來分類,可以選用 log loss。SGDClassifier 分類器還支持不同的損失函數,如 perceptron等,這里就不一一列舉了。由於SGD分類器對訓練樣本的順序是敏感的,所以在模型訓練之前需要shuffle訓練集。
用SVM訓練結束后,用模型預測得到測試集的預測結果,評估准確率(accuracy)大概是96%,看起來是一個不錯的結果,但是如果我們把所有的測試樣本都判定為非5,准確率也能有90%(十分之九都是對的)。看來光憑准確率,在這種情況下不能說明我們模型學習得很好,看來如何評價模型的學習能力不是件那么簡單的事情。
“觀察到的一個有意思的細節:一些喜好機器學習或者數據科學的初學工程師和有機器學習或者數據科學背景的科學家,在工作上的主要區別在於如何對待負面的實驗(包括線下和線上)結果。初學者往往就開始琢磨如何改模型,加Feature,調參數;思考如何從簡單模型轉換到復雜模型。有經驗的人往往更加去了解實驗的設置有沒有問題;實驗的Metrics的Comparison是到底怎么計算的;到真需要去思考模型的問題的時候,有經驗的人往往會先反思訓練數據的收集情況,測試數據和測試評測的真實度問題。初學者有點類似程咬金的三板斧,有那么幾個技能,用完了,要是還沒有效果,也就完了。而有經驗的數據科學家,往往是從問題出發,去看是不是對問題本質的把握(比如優化的目標是不是對;有沒有Counterfactual的情況)出現了偏差,最后再討論模型。”
—— by @洪亮劼
3. 效果評測
從源頭出發,如下圖,x、o分別表示label為負和正的樣本,划分為上下兩列,假設模型預測值是一個連續值(如為正的概率),把正負樣本按照預測值從低到高分別排列好。一個好的模型,應該是左上角分布較密集,表示很多負樣本預測值較小,右下角分布也很密集,表示為模型預測正樣本的概率值普遍偏高。當然,一般模型也無法做到百分之百的分類准確,所以存在少量的負樣本預測概率較高,正樣本預測概率偏低,如圖右上角和左下角。
Confusion Matrix
我們設定一個閾值,用圖中藍色的豎線表示,高於閾值的模型預測為正樣本,反之則為負樣本。這個閾值是我們可以自行設定的,藍色的豎線可以左右移動。紅色的橫線和藍色的豎線將整個測試集數據分成四個部分,TN(True Positive)、FP(False Positive)、FN(False Negative)、TP(True Positive)。TPR(TP rate)即recall= TP/(TP+FN),precision=TP/(TP+FP)。上面我們計算accuracy實際上是 (TN+TP)/ALL,對於一個測試集來說,底下分母是不變的,如果TN對比TP很大,TP的變動很難通過accuracy反映出來。一個好的分類器,應該TP包含大部分圓圈,FP和FN幾乎為空,所以很多比賽的評測指標是precision和recall的harmonic平均值,即:
harmonic平均比直接除以2更看重較小的那個值,只有兩個值都比較大,整體才會大。
PR曲線和ROC曲線
為了得到較好的F1,需要調節適當的閾值。藍色的線從最左往右滑動時,recall= TP/(TP+FN),分母不變,分子逐漸變小,從1單調遞減到0。precision=TP/(TP+FP),分子和分母同時變小,總體上,TP變小的速度慢很多,大體上是遞增的,但是並不絕對單調,尤其在靠近右側。經常可以看到TP-1,FP不變,則precision反而變小:
關於Recall和Precision的tradeoff,還可以畫一條PR 曲線:
ROC曲線是另外一種衡量二分類模型的方法,y軸是recall=TP/(TP+FN),x軸是FPR=FP/(FP+TN):
PR曲線與ROC曲線的區別在於,PR曲線不關心TN(x、y計算公式都沒有包含TN),所以在負樣本比例很高的時候,PR曲線波動比ROC曲線明顯,更能體現優化空間。另外,ROC曲線關心TN恰好也是它的優勢,比如在推薦、搜索等learn to rank 任務中,我們關心的是整個數據集的排序情況,TN也是需要考慮在內的,所以經常離線計算AUC(ROC曲線下方面積)來衡量rank model的優劣。
中場休息時間。。。喝口茶~ 歡迎關注公眾號:kaggle實戰,或博客:http://www.cnblogs.com/daniel-D/
4. 多分類器與誤差分析
多分類器是指能區別兩個以上類別的分類器,比如手寫數字識別這個數據集要區分0-9,像大型圖像數據集可能有幾萬個類別。有些算法可以直接區分多類,如softmax、RF或者貝葉斯,有些算法無法直接區分,比如上面用到的線性分類器等二分類器。二分類器也可以組合形成多分類器,常見的策略有 One vs All和 One vs One。
在數字識別這個任務中,One vs All(OVA) 一共要訓練10個分類器,分別是0 vs 非0,1 vs 非1……預測的時候,10個分類器依次輸出為0,為1等的概率,可直接取最大概率作為預測值。One vs One則需要10*(10-1)/ 2個分類器,依次是 0 vs 1,0 vs 2……8 vs 9。OVO和OVA在實際使用不多,這里就不贅述了。
用RF模型訓練后,在預測集上預測圖像屬於哪個類別,由於模型不是百分百准確的,會有0判定成1或者1判定成2的情況,用rowIndex表示實際的label,colIndex表示預測的label,統計預測的label落到實際label的個數,可以得到以下矩陣:
可視化之后得到下圖:
可以看到對角線方塊很亮,說明所有類別基本判定准確。但是“5”方塊較暗,可能是由於5的圖片數量較少,或者5的准確率偏低導致,要具體分析數據才能找到原因。除了對角線方塊,我們還想分析其余方塊的情況,可以把Confusion Matrix每個元素處理該行的總和,對角線置0,得到下圖:
可以看到3和5、7和9都容易混淆,想通過RF模型要提升效果的突破口可能就在這里。
5. Kaggle 實戰
實際上,3和5、7和9容易混淆的原因在於,他們形態較為相似,直接用像素作為特征,相同的數字,在圖像中旋轉微小角度或者平移,都會導致像素空間的巨大變化,kaggle上高分kernel普遍都用神經網絡里的CNN來提取特征,准確率可以輕松超過98%。預處理流程為:
- 把 label 從0-9的dense編碼轉化為 one hot encode編碼
- 分割出4w個訓練集和2k個驗證集
然后定義一個最常用CNN網絡結構和主要的超參數如下:
-
卷積參數:一般設置stride=1,卷積后保持原尺寸,用0填充,非線性變換采用relu;pooling大小2*2,stride=2,取maxPooling
-
網絡結構:
- input:(40000, 28, 28, 1)
- conv1:kernel [5, 5, 1, 32] => (40000, 28, 28, 32)
- maxPool1:kernel [1, 2, 2, 1] => (40000, 14, 14, 32)
- conv2:kernel [5, 5, 32, 64] => (40000, 14, 14, 64)
- maxPool2: kernel [1, 2, 2, 1] => (40000, 7, 7, 64)
- flat:(40000,7*7*64) => (40000, 3136)
- FC1: (40000, 1024),非線性變換仍然可以采用relu
- dropout: 0.5
- FC2:(40000, 10)
- Loss:cross-entropy
-
由於MNIST數據集各類分布都比較均勻,用准確率就能較好評估模型了,比其他指標更加直白
詳細代碼可以參考這個kernel:https://www.kaggle.com/kakauandme/tensorflow-deep-nn
參考資料
- Kaggle: TensorFlow deep NN
- Book: Hands-on machine learning with scikit-learn and tensorflow
- Code:03_classification.ipynb
附:公眾號
順便測試下贊賞碼