本文以設計一個垃圾郵件過濾系統為例,談談如何設計一個機器學習系統。同時介紹查準率,召回率以及 F1Score 來評價算法的性能。
構建垃圾郵件過濾系統
特征選擇
在實踐中,可以遍歷所有的訓練數據集,即所有的垃圾郵件和所有的非垃圾郵件,找出出現頻率最高的 10,000 - 50,000 個單詞作為特征,假設特征數量記為 n。這樣一封郵件就可以用一個 n 維向量來表示,即 n 個特征單詞是否出現在郵件里,如果出現記為 1 不出現記為 0 。
構建步驟
- 收集盡量多的數據,如 honeypot 項目
- 從郵件路由信息中提取出有效的特征來區分垃圾郵件,路由信息放在郵件頭部
- 從郵件的內容中提取復雜特征
- 開發一套算法來檢查拼寫錯誤。因為很多算法從郵件內容中通過關鍵字為特征來區分垃圾郵件,垃圾郵件系統為了跳過這個檢查,故意把一些敏感詞拼錯,這樣規避垃圾郵件檢查機制
至于哪個方法是最有效的,需要頭腦風暴或者事先詳細研究才能得出結論。當然,在算法通過檢驗之前,很難事先判斷哪個特征是最有效的。
錯誤分析
用機器學習算法解決問題時,可以償試如下的策略
- 從簡單的算法開始,先實現出來,然后使用交叉驗證數據來驗證結果。
- 畫出學習曲線,診斷算法的問題和優化方向,是需要去獲取更多訓練數據還是要增加特征等。
- 錯誤分析:針對交叉驗證數據的錯誤項進行手動分析,試圖從這些錯誤結果里找出更多線索和特征。
錯誤分析實例
假設我們實現的垃圾郵件過濾算法,針對 500 封交叉驗證數據里有 100 封被錯誤分類了,那么我們可以進行
- 手動檢查這些被錯誤分類的郵件類型,比如釣魚郵件,賣藥的郵件等等,通過手動分析總結出哪種類型的郵件被錯誤地分類數量最多,然后先把精力花在這種類型的郵件上面。
- 有哪些線索或特征有助于算法正確鑒別這些郵件。比如通過分析,我們發現異常路由的郵件數量有多少,錯誤拼寫的郵件有多少,異常標點符號的郵件有多少。通過總結這些特征,決定我們應該要把時間花在哪方面來改善算法性能。
比如,我們在實現垃圾郵件鑒別算法時,我們需要決定 Dicount/Discounts/Discounted/Discouting 等單詞視為同一個單詞還是不同的單詞。如果要視為相同的單詞,可以使用詞干提取法 (Porter Stemmer) ,但使用詞干提取法一樣會帶來問題,比如會錯誤地把 universe/university 歸類為同一個單詞。這個時候如何決策呢?
一個可行的辦法是分別計算使用了詞干提取法和不使用時候的交叉驗證數據集成本 $J_{cv}(\theta)$ 和測試數據集成本 $J_{test}(\theta)$ ,這樣來判斷到底是使用更好還是不使用性能更好。
實際上,優化算法過程中的很多償試都可以使用這個方法來判斷是否是有效的優化策略。
處理有傾向性的數據
比如針對癌癥篩查算法,根據統計,普通腫瘤中癌癥的概率是 0.5% 。我們有個機器學習算法,在交叉驗證數據時得出的準確率是 99.2%,錯誤率是 0.8% 。這個算法到底是好還是壞呢?如果努力改進算法,最終在交叉驗證數據集上得出的準確率是 99.5%,錯誤率是 0.5% 到底算法性能是提高了還是降低了呢?
坦白講,如果單純從交叉驗證數據集上測試準確率的方法很難進行判斷到底算法是變好了還是變壞了。因為這個事情的先驗概率太低了,假如我們寫了一個超級簡單的預測函數,總是返回 0,即總是認為不會得癌癥,那么我們這個超級簡單的預測函數在交叉驗證數據集上得到的準確率是 99.5%,錯誤率是 0.5% 。因為總體而言,只有那 0.5% 真正得癌癥的可憐蟲被我們誤判了。
那么我們怎么樣來衡量分類問題的準確性能呢?我們引入了另外兩個概念,查準率 (Precision) 和 召回率 (Recall)。還是以癌癥篩查為例:
預測數據/實際數據 | 實際惡性腫瘤 | 實際良性腫瘤 |
---|---|---|
預測惡性腫瘤 | TruePositive | FalsePositive |
預測良性腫瘤 | FalseNegative | TrueNegative |
在處理先驗概率低的問題時,我們總是把概率較低的事件定義為 1 ,并且總是把 $y=1$ 作為 Positive 的預測結果。有了這個公式,如果一個簡單地返回 0 的預測函數,那么它的查準率和召回率都為 0。這顯然不是個好的預測模型。
TIPS
如何理解 True/False
和 Positive/Negative
?True/False
表示預測結果是否正確,而 Positive/Negative
表示預測結果是 1 (惡性腫瘤) 或 0 (良性腫瘤)。故,TruePositive 表示正確地預測出惡性腫瘤的數量;FalsePositive 表示錯誤地預測出惡性腫瘤的數量;FalseNegative 表示錯誤地預測出良性腫瘤的數量。
在查準率和召回率之間權衡
假設我們想提高癌癥的查準率,即只有在很有把握的情況下才預測為癌癥。回憶我們在邏輯回歸算法里,當 $h_\theta(x) >= 0.5$ 時,我們就預測 $y = 1$ ,為了提高查準率,可以把門限值從 0.5 提高到 0.8 之類的。這樣就提高了查準率,但這樣會降低召回率。同樣的道理,我們如果想提高召回率,可以降低門限值,從 0.5 降到 0.3 。這樣召回率就會提高,但查準率就會降低。所以在實際問題時,可以要接實際問題,去判斷是查準率重要還是召回率重要,根據重要性去調整門限值。
如何評價算法的好壞
由于我們現在有兩個指標,查準率和如回率,如果有一個算法的查準率是 0.5, 召回率是 0.4;另外一個算法查準率是 0.02, 召回率是 1.0;那么兩個算法到底哪個好呢?
為了解決這個問題,我們引入了 $F_1Score$ 的概念
其中 P 是查準率,R 是召回率。這樣就可以用一個數值直接判斷哪個算法性能更好。典型地,如果查準率或召回率有一個為 0,那么 $F_1Score$ 將會為 0。而理想的情況下,查準率和召回率都為 1 ,則算出來的 $F_1Score$ 為 1。這是最理想的情況。
自動選擇門限值
前文介紹過,門限值可以調節查準率和召回率的高低。那么如何自動選擇門限值以便讓算法的性能最優呢?我們可以使用交叉驗證數據,算出使 $F_1Score$ 最大的門限值。這個值就是我們自動選擇出來的最優的門限值。
使用大量的數據集
Michele Banko and Eric Brill 在 2011 年用四種算法進行了一個自然語言的機器學習訓練,結果發現,數據量越大,訓練出來的算法準確性越高。他們得出了下圖的結論。
然后這個結論是些前提:有足夠的特征進行機器學習。怎么樣判斷是否有足夠的特征呢?我們可以讓這個領域的專家來人工預測。比如給出一個房子的面積,讓房產經紀人預測其房價,他肯定無法正確地預測。因為特征不足,很難只根據房子的面積推算出房子的價格。
怎么樣從理論上證明這個結論呢?我們知道,如果我們有足夠的特征來進行預測,意味著我們可以構建足夠復雜的模型(比如神經網絡)來讓我們的預測函數有比較低的偏差 (Low Bais),即讓訓練數據集成本 $J_{train}(\theta)$ 的值很小。如果我們有足夠多的數據,就可以確保我們可以訓練出一個低方差 (Low Variance) 的算法,即我們可以讓交叉驗證數據集成本 $J_{cv}(\theta)$ 接近訓練數據集成本 $J_{train}(\theta)$ 。這樣最終我們的測試數據集成本 $J_{test}(\theta)$ 也會靠近訓練數據集成本 $J_{train}(\theta)$ 。