本文以設(shè)計(jì)一個(gè)垃圾郵件過(guò)濾系統(tǒng)為例,談?wù)勅绾卧O(shè)計(jì)一個(gè)機(jī)器學(xué)習(xí)系統(tǒng)。同時(shí)介紹查準(zhǔn)率,召回率以及 F1Score 來(lái)評(píng)價(jià)算法的性能。
構(gòu)建垃圾郵件過(guò)濾系統(tǒng)
特征選擇
在實(shí)踐中,可以遍歷所有的訓(xùn)練數(shù)據(jù)集,即所有的垃圾郵件和所有的非垃圾郵件,找出出現(xiàn)頻率最高的 10,000 - 50,000 個(gè)單詞作為特征,假設(shè)特征數(shù)量記為 n。這樣一封郵件就可以用一個(gè) n 維向量來(lái)表示,即 n 個(gè)特征單詞是否出現(xiàn)在郵件里,如果出現(xiàn)記為 1 不出現(xiàn)記為 0 。
構(gòu)建步驟
- 收集盡量多的數(shù)據(jù),如 honeypot 項(xiàng)目
- 從郵件路由信息中提取出有效的特征來(lái)區(qū)分垃圾郵件,路由信息放在郵件頭部
- 從郵件的內(nèi)容中提取復(fù)雜特征
- 開(kāi)發(fā)一套算法來(lái)檢查拼寫錯(cuò)誤。因?yàn)楹芏嗨惴◤泥]件內(nèi)容中通過(guò)關(guān)鍵字為特征來(lái)區(qū)分垃圾郵件,垃圾郵件系統(tǒng)為了跳過(guò)這個(gè)檢查,故意把一些敏感詞拼錯(cuò),這樣規(guī)避垃圾郵件檢查機(jī)制
至于哪個(gè)方法是最有效的,需要頭腦風(fēng)暴或者事先詳細(xì)研究才能得出結(jié)論。當(dāng)然,在算法通過(guò)檢驗(yàn)之前,很難事先判斷哪個(gè)特征是最有效的。
錯(cuò)誤分析
用機(jī)器學(xué)習(xí)算法解決問(wèn)題時(shí),可以償試如下的策略
- 從簡(jiǎn)單的算法開(kāi)始,先實(shí)現(xiàn)出來(lái),然后使用交叉驗(yàn)證數(shù)據(jù)來(lái)驗(yàn)證結(jié)果。
- 畫出學(xué)習(xí)曲線,診斷算法的問(wèn)題和優(yōu)化方向,是需要去獲取更多訓(xùn)練數(shù)據(jù)還是要增加特征等。
- 錯(cuò)誤分析:針對(duì)交叉驗(yàn)證數(shù)據(jù)的錯(cuò)誤項(xiàng)進(jìn)行手動(dòng)分析,試圖從這些錯(cuò)誤結(jié)果里找出更多線索和特征。
錯(cuò)誤分析實(shí)例
假設(shè)我們實(shí)現(xiàn)的垃圾郵件過(guò)濾算法,針對(duì) 500 封交叉驗(yàn)證數(shù)據(jù)里有 100 封被錯(cuò)誤分類了,那么我們可以進(jìn)行
- 手動(dòng)檢查這些被錯(cuò)誤分類的郵件類型,比如釣魚(yú)郵件,賣藥的郵件等等,通過(guò)手動(dòng)分析總結(jié)出哪種類型的郵件被錯(cuò)誤地分類數(shù)量最多,然后先把精力花在這種類型的郵件上面。
- 有哪些線索或特征有助于算法正確鑒別這些郵件。比如通過(guò)分析,我們發(fā)現(xiàn)異常路由的郵件數(shù)量有多少,錯(cuò)誤拼寫的郵件有多少,異常標(biāo)點(diǎn)符號(hào)的郵件有多少。通過(guò)總結(jié)這些特征,決定我們應(yīng)該要把時(shí)間花在哪方面來(lái)改善算法性能。
比如,我們?cè)趯?shí)現(xiàn)垃圾郵件鑒別算法時(shí),我們需要決定 Dicount/Discounts/Discounted/Discouting 等單詞視為同一個(gè)單詞還是不同的單詞。如果要視為相同的單詞,可以使用詞干提取法 (Porter Stemmer) ,但使用詞干提取法一樣會(huì)帶來(lái)問(wèn)題,比如會(huì)錯(cuò)誤地把 universe/university 歸類為同一個(gè)單詞。這個(gè)時(shí)候如何決策呢?
一個(gè)可行的辦法是分別計(jì)算使用了詞干提取法和不使用時(shí)候的交叉驗(yàn)證數(shù)據(jù)集成本 $J_{cv}(\theta)$ 和測(cè)試數(shù)據(jù)集成本 $J_{test}(\theta)$ ,這樣來(lái)判斷到底是使用更好還是不使用性能更好。
實(shí)際上,優(yōu)化算法過(guò)程中的很多償試都可以使用這個(gè)方法來(lái)判斷是否是有效的優(yōu)化策略。
處理有傾向性的數(shù)據(jù)
比如針對(duì)癌癥篩查算法,根據(jù)統(tǒng)計(jì),普通腫瘤中癌癥的概率是 0.5% 。我們有個(gè)機(jī)器學(xué)習(xí)算法,在交叉驗(yàn)證數(shù)據(jù)時(shí)得出的準(zhǔn)確率是 99.2%,錯(cuò)誤率是 0.8% 。這個(gè)算法到底是好還是壞呢?如果努力改進(jìn)算法,最終在交叉驗(yàn)證數(shù)據(jù)集上得出的準(zhǔn)確率是 99.5%,錯(cuò)誤率是 0.5% 到底算法性能是提高了還是降低了呢?
坦白講,如果單純從交叉驗(yàn)證數(shù)據(jù)集上測(cè)試準(zhǔn)確率的方法很難進(jìn)行判斷到底算法是變好了還是變壞了。因?yàn)檫@個(gè)事情的先驗(yàn)概率太低了,假如我們寫了一個(gè)超級(jí)簡(jiǎn)單的預(yù)測(cè)函數(shù),總是返回 0,即總是認(rèn)為不會(huì)得癌癥,那么我們這個(gè)超級(jí)簡(jiǎn)單的預(yù)測(cè)函數(shù)在交叉驗(yàn)證數(shù)據(jù)集上得到的準(zhǔn)確率是 99.5%,錯(cuò)誤率是 0.5% 。因?yàn)榭傮w而言,只有那 0.5% 真正得癌癥的可憐蟲(chóng)被我們誤判了。
那么我們?cè)趺礃觼?lái)衡量分類問(wèn)題的準(zhǔn)確性能呢?我們引入了另外兩個(gè)概念,查準(zhǔn)率 (Precision) 和 召回率 (Recall)。還是以癌癥篩查為例:
| 預(yù)測(cè)數(shù)據(jù)/實(shí)際數(shù)據(jù) | 實(shí)際惡性腫瘤 | 實(shí)際良性腫瘤 |
|---|---|---|
| 預(yù)測(cè)惡性腫瘤 | TruePositive | FalsePositive |
| 預(yù)測(cè)良性腫瘤 | FalseNegative | TrueNegative |

在處理先驗(yàn)概率低的問(wèn)題時(shí),我們總是把概率較低的事件定義為 1 ,并且總是把 $y=1$ 作為 Positive 的預(yù)測(cè)結(jié)果。有了這個(gè)公式,如果一個(gè)簡(jiǎn)單地返回 0 的預(yù)測(cè)函數(shù),那么它的查準(zhǔn)率和召回率都為 0。這顯然不是個(gè)好的預(yù)測(cè)模型。
TIPS
如何理解 True/False 和 Positive/Negative ?True/False 表示預(yù)測(cè)結(jié)果是否正確,而 Positive/Negative 表示預(yù)測(cè)結(jié)果是 1 (惡性腫瘤) 或 0 (良性腫瘤)。故,TruePositive 表示正確地預(yù)測(cè)出惡性腫瘤的數(shù)量;FalsePositive 表示錯(cuò)誤地預(yù)測(cè)出惡性腫瘤的數(shù)量;FalseNegative 表示錯(cuò)誤地預(yù)測(cè)出良性腫瘤的數(shù)量。
在查準(zhǔn)率和召回率之間權(quán)衡
假設(shè)我們想提高癌癥的查準(zhǔn)率,即只有在很有把握的情況下才預(yù)測(cè)為癌癥?;貞浳覀?cè)谶壿嫽貧w算法里,當(dāng) $h_\theta(x) >= 0.5$ 時(shí),我們就預(yù)測(cè) $y = 1$ ,為了提高查準(zhǔn)率,可以把門限值從 0.5 提高到 0.8 之類的。這樣就提高了查準(zhǔn)率,但這樣會(huì)降低召回率。同樣的道理,我們?nèi)绻胩岣哒倩芈?,可以降低門限值,從 0.5 降到 0.3 。這樣召回率就會(huì)提高,但查準(zhǔn)率就會(huì)降低。所以在實(shí)際問(wèn)題時(shí),可以要接實(shí)際問(wèn)題,去判斷是查準(zhǔn)率重要還是召回率重要,根據(jù)重要性去調(diào)整門限值。
如何評(píng)價(jià)算法的好壞
由于我們現(xiàn)在有兩個(gè)指標(biāo),查準(zhǔn)率和如回率,如果有一個(gè)算法的查準(zhǔn)率是 0.5, 召回率是 0.4;另外一個(gè)算法查準(zhǔn)率是 0.02, 召回率是 1.0;那么兩個(gè)算法到底哪個(gè)好呢?
為了解決這個(gè)問(wèn)題,我們引入了 $F_1Score$ 的概念

其中 P 是查準(zhǔn)率,R 是召回率。這樣就可以用一個(gè)數(shù)值直接判斷哪個(gè)算法性能更好。典型地,如果查準(zhǔn)率或召回率有一個(gè)為 0,那么 $F_1Score$ 將會(huì)為 0。而理想的情況下,查準(zhǔn)率和召回率都為 1 ,則算出來(lái)的 $F_1Score$ 為 1。這是最理想的情況。
自動(dòng)選擇門限值
前文介紹過(guò),門限值可以調(diào)節(jié)查準(zhǔn)率和召回率的高低。那么如何自動(dòng)選擇門限值以便讓算法的性能最優(yōu)呢?我們可以使用交叉驗(yàn)證數(shù)據(jù),算出使 $F_1Score$ 最大的門限值。這個(gè)值就是我們自動(dòng)選擇出來(lái)的最優(yōu)的門限值。
使用大量的數(shù)據(jù)集
Michele Banko and Eric Brill 在 2011 年用四種算法進(jìn)行了一個(gè)自然語(yǔ)言的機(jī)器學(xué)習(xí)訓(xùn)練,結(jié)果發(fā)現(xiàn),數(shù)據(jù)量越大,訓(xùn)練出來(lái)的算法準(zhǔn)確性越高。他們得出了下圖的結(jié)論。

然后這個(gè)結(jié)論是些前提:有足夠的特征進(jìn)行機(jī)器學(xué)習(xí)。怎么樣判斷是否有足夠的特征呢?我們可以讓這個(gè)領(lǐng)域的專家來(lái)人工預(yù)測(cè)。比如給出一個(gè)房子的面積,讓房產(chǎn)經(jīng)紀(jì)人預(yù)測(cè)其房?jī)r(jià),他肯定無(wú)法正確地預(yù)測(cè)。因?yàn)樘卣鞑蛔?,很難只根據(jù)房子的面積推算出房子的價(jià)格。
怎么樣從理論上證明這個(gè)結(jié)論呢?我們知道,如果我們有足夠的特征來(lái)進(jìn)行預(yù)測(cè),意味著我們可以構(gòu)建足夠復(fù)雜的模型(比如神經(jīng)網(wǎng)絡(luò))來(lái)讓我們的預(yù)測(cè)函數(shù)有比較低的偏差 (Low Bais),即讓訓(xùn)練數(shù)據(jù)集成本 $J_{train}(\theta)$ 的值很小。如果我們有足夠多的數(shù)據(jù),就可以確保我們可以訓(xùn)練出一個(gè)低方差 (Low Variance) 的算法,即我們可以讓交叉驗(yàn)證數(shù)據(jù)集成本 $J_{cv}(\theta)$ 接近訓(xùn)練數(shù)據(jù)集成本 $J_{train}(\theta)$ 。這樣最終我們的測(cè)試數(shù)據(jù)集成本 $J_{test}(\theta)$ 也會(huì)靠近訓(xùn)練數(shù)據(jù)集成本 $J_{train}(\theta)$ 。