機器學習法則:(Google)機器學習工程最佳實踐

  • 2019 年 10 月 28 日
  • 筆記

這是Martin Zinkevich在NIPS 2016 Workshop 分享的Google機器學習實踐的四十三條法則《Rules of Machine Learning:Best Practices for ML Engineering》

Martin Zinkevich google 研究科學家。

機器學習(ML)最優實踐方法,濃縮了其多年技術積累與經驗,尤其是YouTube、Google Play和Google+ 等平台背後的ML演算法開發、維護經歷。Google於白皮書中總結了四十三條ML黃金法則,旨在幫助已經掌握了基礎知識的開發者少走彎路。

術語

實體(Instance):要對其進行預測的事物

標籤(Label):預測任務的結果

特徵:在預測任務中用到的實體的一個屬性

特徵集(feature Column):相關特徵的一個集合

樣例(Example):實體(及它的特徵)和標籤的集合

模型(Model):關於一個預測任務的一個統計表示。在樣例中訓練一個模型,然後用這個模型來預測

指標(metric):你關心的一些東西。有可能直接優化。

目標(Objective):你的演算法嘗試去優化的一個指標

工作流(pipeline):關於一個機器學習演算法所有的基礎構件。包括從前端收集數據,將數據輸入訓練數據文件,訓練一個或者更多模型,以及將模型導出用於生產。

概述

要想創造出優秀的產品:

你需要以一位優秀工程師的身份去運用機器學習,而不是作為一位偉大的機器學習專家(而事實上你並不是)。

事實上,你所面臨的大多數問題都是技術性問題。即便擁有足以媲美機器學習專家的理論知識。要想有所突破,大多數情況下都在依賴示例良好特徵而非優秀的機器學習演算法。因此,基本方法如下:

1.確保你的 工作流 各連接端十分可靠

2. 樹立合理的目標

3. 添加的常識性特徵盡量簡單

4. 確保你的 工作流 始終可靠

這種方法能帶來相當多的盈利,也能在較長時間裡令許多人都滿意,甚至還可能實現雙贏。只有在簡單技巧不發揮任何作用的情況下,才考慮使用複雜的一些的方法。方法越複雜,產品最終輸出速度慢。

當所有的簡單技巧用完後,很可能就要考慮最前沿機器學習術了。

本文檔主要由四部分組成:

第一部分:幫助你明白是否到了需要構建一個機器學習系統

第二部分:部署你的第一個工作流

第三部分:往工作流增加新特徵時的發布和迭代,以及如何評價模型和訓練-服務傾斜(training-serving shew)

第四部分:達到穩定階段後該繼續做什麼。

在機器學習之前

法則1:不用害怕發布一款沒有用到機器學習的產品

機器學習很酷,但它需要數據。如果不是絕對需要機器學習,那在沒有數據前,不要使用它。

法則2:將度量標準的設計和執行置於首位

在定義你的機器學習系統將要做什麼前,儘可能的記錄你當前的系統「足跡」。原因:

1、在早期,獲得系統用戶的許可相對容易.

2、如果你認為某些事在將來會重要,那麼最好是從現在開始就收集歷史數據

3、如果你設計系統時,就已經在心裡有度量指標,那麼將來一切就會更加的順暢。特別是你肯定不想為了測量你的指標而需要在日誌中執行grep。

4、你能夠注意到什麼改變了,什麼沒有變。比如,假如你想要直接優化每日活躍用戶。但是,在你早期對系統的管理中,你可能注意到對用戶體驗的急劇改變,可能並不會明顯的改變這個指標。

Google Plus團隊測量「轉發數」(expands per read)、分享數(reshares per read)、點贊數(plus-ones per read)、評論/閱讀比(comments/read)、每個用戶的評論數、每個用戶的分享數等。這些用來在服務時間衡量一篇帖子的品質。同樣,有一個能夠將用戶聚成組,並實驗生成統計結果的實驗框架很重要。見法則12

法則3:在機器學習和啟發式方法中優先選擇機器學習。

機器學習模型更好更新和更容易管理

機器學習階段1:第一條工作流

認真對待第一條工作流的基礎架構建設。雖然發揮想像力構思模型很有意思,但首先得確保你的工作流是可靠的,這樣出了問題才容易發現

法則4:第一個模型要簡單,基礎架構要正確。

第一個模型對你的產品提高最大,因此它不需要有多神奇。相反,你會碰到比你想像的多的基礎架構方面的問題。在別人使用你的神奇的新機器學習系統前,你要決定:

1、如何為學習演算法得到樣本

2、對於你的系統,「好」、「壞」的定義是什麼

3、如何在你的應用中融入你的模型。你可以在線應用你的模型,也可以在離線預先計算好模型,然後將結果保存到表中。比如,你可能想要預分類網頁並將結果存入表,也有可能你想直接在線上分類聊天資訊。

選擇簡單的特徵,以能夠更容易確保:

1、這些特徵正確應用於學習演算法

2、模型能夠學習到合理的權重

3、這些特徵正確應用於伺服器模型。

你的系統如果能夠可靠地遵守這三點,你就完成了大多數工作。你的簡單模型能夠提供基準指標和基準行為,你可以用來測量更加複雜的模型。

法則5:單獨測試基礎架構。

確保基礎架構是可測試的。系統的學習部分獨立封裝,因此所有圍繞它的都能測試。

法則6:複製工作流時留意丟失的數據

我們有時候會通過複製已經存在的工作流來創建一個新的工作流。在新的工作流中需要的數據,很可能在舊的數據流就丟棄了。比如,僅僅記錄那些用戶看到過的帖子的數據,那麼,如果我們想要建模「為什麼一篇特定的帖子沒有被用戶閱讀」時,這些數據就沒用了。

法則7:要麼把啟發式方法轉化為特徵,要麼在外部處理它們

機器學習嘗試解決的問題通常並不完全是新的。可以利用到很多已有的規則和啟發式方法。當你調整機器學習時,這些相同的啟發式方法能提供非常有用的幫助。

監控

一般來說,實施良好的警報監控,例如使警報可操作並具有報表頁面。

法則8:了解系統的新鮮度要求

如果系統是一天前的,性能會降低多少?如果是一個星期前,或者1個季度前的呢?知道這些能夠幫助你理解監控的優先順序。如果模型一天未更新,你的收入會下降10%,那最好是有個工程師持續不斷的關注。大多數廣告服務系統每天都有新廣告要處理,因此必須每日更新。有些需要頻繁更新,有些又不需要,這因不同的應用和場景而定。此外,新鮮度也會因時間而異,特別是你的模型會增加或移除特徵時。

法則9:導出(發布)你的模型前,務必檢查各種問題

將模型導出部署到線上服務。如果這個時候,你的模型出了問題,這就是一個用戶看到的問題。但如果是在之前出現問題,那就是一個訓練問題,用戶並不會發現。

在導出模型前務必進行完整性的檢查。特別是要確保對留存的數據,你的模型能夠滿足性能。如果對數據感覺有問題,就不用導出模型!很多持續部署模型的團隊都會在導出前檢測AUC。模型問題出現在導出前,會收到警告郵件,但如果模型問題讓用戶碰到,就可能需要一紙辭退信了。因此,在影響用戶前,最好先等一等,有確定把握後,在導出。

法則10:注意隱藏性失敗

相對其他類型的系統,機器學習系統出現這種問題的可能性更高。比如關聯的某張表不再更新。雖然機器學習還是會照樣調整,行為還是表現的很合適,但已經在逐漸衰落。有時候發現了那些已經數月沒有更新的表,那這個時候,一個簡單的更新要比其他任何改變都能更好的提高性能。比如,由於實現的改變,一個特徵的覆蓋率會變:比如,開始覆蓋90%的樣本,突然只能覆蓋60%了。google Play做過一個實驗,有張表6個月一直不變,僅僅是對這個表更新,就在安裝率方面提高了2%。跟蹤數據的統計,並且在必要的時候人工檢查,你就可以減少這樣的錯誤。

法則11:給特徵指定作者和文檔

如果系統很大,有很多的特徵,務必要知道每個特徵的創建者或者管理者。如果理解特徵的人要離職,務必確保有其他人理解這個特徵。儘管很多的特徵的名字已基本描述了特徵的意義,但對特徵有更新詳細的描述,比如,它的來源以及其他它能提供什麼幫助等,那就更好了。

你的第一個目標

對於你的系統,你有很多關心的指標。但對於你的機器學習演算法,通常你需要一個單一目標——你的演算法「嘗試」去優化的數字。指標和目標的區別是:指標是你的系統報告的任何數字。這可能重要,也可能不重要。

法則12:不要過分思考你選擇直接優化的目標

你有成千上萬關心的指標,這些指標也值得你去測試。但是,在機器學習過程的早期,你會發現,即使你並沒有直接去優化,他們也都會上升。比如,你關心點擊次數,停留時間以及每日活躍用戶數。如果僅優化了點擊次數,通常也會看到停留時間增加了。

所以,當提高所有的指標都不難的時候,就沒必要花心思來如何權衡不同的指標。不過過猶不及:不要混淆了你的目標和系統的整體健康度。

法則13:為你的第一個目標選擇一個簡單、可觀察以及可歸因的指標

有時候你自以為你清楚真實的目標,但隨著你對數據的觀察,對老系統和新的機器學習系統的分析,你會發現你又想要調整。而且,不同的團隊成員對於真實目標並不能達成一致。機器學習的目標必須是能很容易測量的,並且一定是「真實」目標的代言。因此,在簡單的機器學習目標上訓練,並創建一個「決策層」,以允許你在上面增加額外的邏輯(這些邏輯,越簡單越好)來形成最後的排序。

最容易建模的是那些可以直接觀察並可歸屬到系統的某個動作的用戶行為:

1.排序的鏈接被點擊了嗎?

2.排序的物品被下載了嗎?

3.排序的物品被轉發/回復/郵件訂閱了嗎?

4.排序的物品被評價了嗎?

5.展示的物品是否被標註為垃圾/色情/暴力?

最開始要避免對間接效果建模:

1.用戶第2天會來訪嗎?

2.用戶訪問時間是多長?

3.每日活躍用戶是什麼樣的?

間接效果是非常重要的指標,在A/B test和發布決定的時候可以使用。

最後,不要試圖讓機器學習來回答以下問題:

1.用戶使用你的產品是否開心

2.用戶是否有滿意的體驗

3.產品是否提高了用戶的整體幸福感

4.這些是否影響了公司的整體健康度

這些都很重要,但太難評估了。與其如此,不如考慮其他代替的:比如,用戶如果高興,那停留時間就應該更長。如果用戶滿意,他就會再次造訪。

法則14:從一個可解釋的模型開始,使調試更容易。

線性回歸,邏輯回歸和泊松回歸直接由概率模型激發。每個預測可解釋為概率或期望值。這使得他們比那些使用目標來直接優化分類準確性和排序性能的模型要更容易調試。比如,如果訓練時的概率和預測時的概率,或者生產系統上的查看到的概率有偏差,那說明存在某種問題。

比如在線性,邏輯或者泊松回歸中,存在數據子集,其中平均預測期望等於平均標記(1-力矩校準或剛剛校準)。如果有一個特徵對於每個樣例,取值要麼為1,有么為0,那為1的那些樣例就是校準的。同樣,如如果都為1,那所有樣例都是校準的。

通常我們會使用這些概率預測來做決策:比如,按期望值(比如,點擊/下載等的概率)對貼排序。但是,要記住,當到了要決定選擇使用哪個模型的時候,決策就不僅僅是關於提供給模型的數據的概率性了。

法則15:在決策層區分垃圾過濾和品質排名

品質排名是一門藝術,而垃圾過濾是一場戰爭。那些使用你系統的人非常清楚你採用什麼來評價一篇帖子的品質,所以他們會想盡辦法來使得他們的帖子具有這些屬性。因此,品質排序應該關注對哪些誠實發布的內容進行排序。如果將垃圾郵件排高名次,那品質排序學習器就大打折扣。同理也要將粗俗的內容從品質排序中拿出分開處理。垃圾過濾就是另外一回事。你必須考慮到要生成的特徵會經常性的改變。你會輸入很多明顯的規則到系統中。至少要保證你的模型是每日更新的。同時,要重點考慮內容創建者的信譽問題。

機器學習階段二:特徵工程

將訓練數據導入學習系統、完成相關感興趣指標的評估記錄以及搭建服務架構,這些都是機器學習系統生命周期的第一階段非常重要的任務。當已經具有一個可工作的端對端系統,並且構建了單元測試和系統測試,那麼,就進入階段二了。

在第二階段,有很多可以很容易就取得的成果。有很多明顯能加入系統的特徵。因此,在機器學習的第二階段會涉及到導入儘可能多的特徵,並且以最直觀地方式組合它們。在此階段,所有指標應該仍然在上升。將會經常性的發版。這將是一個偉大的時刻,在這個階段能夠吸引很多的工程師來融合所有想要的數據來創建一個了不起的學習系統

法則16:做好發布和迭代的計劃

不要期望現在發布的這個模型是最後。因此,考慮你給當前這個模型增加的複雜度會不會減慢後續的發布。很多團隊一個季度,甚至很多年才發布一個模型。以下是應該發布新模型的三個基本原因:

1.會不斷出現新的特徵

2..您正在以新的方式調整規則化和組合舊特徵,或者

3.你正在調整目標。

無論如何,對一個模型多點投入總是好的:看看數據回饋示例可以幫助找到新的、舊的以及壞的訊號。因此,當你構建你的模型時,想想添加,刪除或重組特徵是不是很容易。想想創建工作流的新副本並驗證其正確性是不是很容易。考慮是否可能有兩個或三個副本並行運行。最後,不要擔心35的特徵16是否會進入此版本的工作流(Finally,don't worry about whether feature 16 of 35 makes it into this version of the pipeline.)。這些,你都會在下個季度得到。

法則17:優先考慮哪些直接觀察到和可記錄的特徵,而不是那些習得的特徵。

首先,什麼是習得特徵?所謂習得特徵,就是指外部系統(比如一個無監督聚類系統)生成的特徵,或者是學習器自己生成的特徵(比如,通過分解模型或者深度學習)。這些特徵都有用,但涉及到太多問題,因此不建議在第一個模型中使用。

如果你使用外部系統來創建一個特徵,切記這個系統本身是有自己目標的。而它的目標很可能和你目前的目標不相關。這個外部系統可能已經過時了。如果你從外部 系統更新特徵,很可能這個特徵的含義已經改變。使用外部系統提供的特徵,一定要多加小心。

分解模型和深度學習模型最主要的問題是它們是非凸的。因此不能找到最優解,每次迭代找到的局部最小都不同。這種不同讓人很難判斷一個對系統的影響到底是有意義的,還是只是隨機的。一個沒有深奧特徵的模型能夠帶來非常好的基準性能。只有當這個基準實現後,才考慮更深奧的方法。

法則18:從不同的上下文環境中提取特徵

通常情況下,機器學習只佔到一個大系統中的很小一部分,因此你必須要試著從不同角度審視一個用戶行為。比如熱門推薦這一場景,一般情況下論壇里「熱門推薦」里的帖子都會有許多評論、分享和閱讀量,如果利用這些統計數據對模型展開訓練,然後對一個新帖子進行優化,就有可能使其成為熱門帖子。另一方面,YouTube上自動播放的下一個影片也有許多選擇,例如可以根據大部分用戶的觀看順序推薦,或者根據用戶評分推薦等。總之,如果你將一個用戶行為用作模型的標記(label),那麼在不同的上下文條件下審視這一行為,可能會得到更豐富的特徵(feature),也就更利於模型的訓練。需要注意的是這與個性化不同:個性化是確定用戶是否在特定的上下文環境中喜歡某一內容,並發現哪些用戶喜歡,喜歡的程度如何。

法則19:盡量選擇更具體的特徵

在海量數據的支援下,即使學習數百萬個簡單的特徵也比僅僅學習幾個複雜的特徵要容易實現。由於被檢索的文本標識與規範化的查詢並不會提供太多的歸一化資訊,只會調整頭部查詢中的標記排序。因此你不必擔心雖然整體的數據覆蓋率高達90%以上,但針對每個特徵組裡的單一特徵卻沒有多少訓練數據可用的情況。另外,你也可以嘗試正則化的方法來增加每個特徵所對應的樣例數。

法則20:以合理的方式組合、修改現有的特徵

有很多組合和修改特徵的方式。類似TensorFlow的機器學習系統能夠通過『transformations』(轉換)來預處理數據。最基本的兩種方式是:「離散化」(discretizations)和「交叉」(crosses)

離散化:將一個值為連續的特徵拆分成很多獨立的特徵。比如年齡,1~18作為1個特徵,18~35作為1個特徵等等。不要過分考慮邊界,通常基本的分位點就能達到最好。

交叉:合併多個特徵。在TensorFlow的術語中,特徵欄是一組相似的特徵,比如{男性,女性},{美國,加拿大,墨西哥}等。這裡的交叉是指將兩個或多個特徵欄合併,例如{男性,女性}×{美國,加拿大,墨西哥}的結果就是一個交叉(a cross),也就構成了一個新的特徵欄。假設你利用TensorFlow框架創建了這樣一個交叉,其中也就包含了{男性,加拿大}的特徵,因此這一特徵也就會出現在男性加拿大人的樣例中。需要注意的是,交叉方法中合併的特徵欄越多,所需要的訓練數據量就越大。

如果通過交叉法生成的特徵欄特別龐大,那麼就可能引起過擬合。 例如,假設你正在進行某種搜索,並且在查詢請求和文檔中都具有一個包含關鍵字的特徵欄。那麼假如你選擇用交叉法組合這兩個特徵欄,這樣得到的新特徵欄就會非常龐大,它內部包含了許多特徵。當這種情況發生在文本搜索場景時,有兩種可行的應對方法。最常用的是點乘法(dot product),點乘法最常見的處理方式就是統計查詢請求和文檔中共同的所有特徵詞,然後對特徵離散化。另一個方法是交集(intersection),比如當且僅當關鍵詞同時出現在文檔和查詢結果中時,我們才能獲取所需的特徵。

法則21:通過線性模型學到的特徵權重的數目,大致與數據量成正比

許多人都認為從一千個樣例中並不能得到什麼可靠的訓練結果,或者由於選擇了某種特定的模型,就必須獲取一百萬個樣例,否則就沒法展開模型訓練。這裡需要指出的是,數據量的大小是和需要訓練的特徵數正相關的:

1) 假如你在處理一個搜索排名問題,文檔和查詢請求中包含了數百萬個不同的關鍵詞,並且有一千個被標記的樣例,那麼你應該用上文提到的點乘法處理這些特徵。這樣就能得到一千個樣例,對應了十幾個特徵。

2) 如你有一百萬個樣例,那麼通過正則化和特徵選擇的方式就可以交叉處理文檔和查詢請求中的特徵欄,這可能會產生數百萬的特徵數,但再次使用正則化可以大大減少冗餘特徵。這樣就可能得到一千萬個樣例,對應了十萬個特徵。

3) 如果你有數十億或數百億個樣例,那同樣可以通過特徵選擇或正則化的方法交叉處理文檔和查詢請求中的特徵欄。這樣就可能得到十億個樣例,對應了一千萬個特徵。

法則22:清理不再需要的特徵

不再使用的特徵,在技術上就是一個累贅。如果一個特徵不再使用,並且也沒辦法和其他的特徵組合,那就清理掉!你必須確保系統清潔,以滿足能儘可能快的嘗試最有希望得出結果的特徵。對於那些清理掉的,如果有天需要,也可以再加回來。

至於保持和添加什麼特徵,權衡的一個重要指標是覆蓋率。比如,如果某些特徵只覆蓋了8%的用戶,那保留還是不保留都不會帶來什麼影響。

另一方面,增刪特徵時也要考慮其對應的數據量。例如你有一個只覆蓋了1%數據的特徵,但有90%的包含這一特徵的樣例都通過了訓練,那麼這就是一個很好的特徵,應該添加。

對系統的人工分析

在進入機器學習第三階段前,有一些在機器學習課程上學習不到的內容也非常值得關註:如何檢測一個模型並改進它。這與其說是門科學,還不如說是一門藝術。這裡再介紹幾種要避免的反模式(anti-patterns)

法則23:你並不是一個典型的終端用戶

這可能是讓一個團隊陷入困境的最簡單的方法。雖然fishfooding(只在團隊內部使用原型)和dogfooding(只在公司內部使用原型)都有許多優點,但無論哪一種,開發者都應該首先確認這種方式是否符合性能要求。要避免使用一個明顯不好的改變,同時,任何看起來合理的產品策略也應該進一步的測試,不管是通過讓非專業人士來回答問題,還是通過一個隊真實用戶的線上實驗。這樣做的原因主要有兩點:

首先,你離實現的程式碼太近了。你只會看到帖子的特定的一面,或者你很容易受到情感影響(比如,認知性偏差)。

其次,作為開發工程師,時間太寶貴。並且有時候還沒什麼效果。

如果你真的想要獲取用戶回饋,那麼應該採用用戶體驗法(user experience methodologies)。在流程早期創建用戶角色(詳情見Bill Buxton的《Designing User ExperienCES》一書),然後進行可用性測試(詳情見Steve Krug的《Do not Make Me Think》一書)。這裡的用戶角色涉及創建假想用戶。例如,如果你的團隊都是男性,那設計一個35歲的女性用戶角色所帶來的效果要比設計幾個25~40歲的男性用戶的效果強很多。當然,讓用戶實測產品並觀察他們的反應也是很不錯的方法。

法則24:測量模型間的差異

在將你的模型發布上線前,一個最簡單,有時也是最有效的測試是比較你當前的模型和已經交付的模型生產的結果之間的差異。如果差異很小,那不再需要做實驗,你也知道你這個模型不會帶來什麼改變。如果差異很大,那就要繼續確定這種改變是不是好的。檢查對等差分很大的查詢能幫助理解改變的性質(是變好,還是變壞)。但是,前提是一定要確保你的系統是穩定的。確保一個模型和它本身比較,這個差異很小(理想情況應該是無任何差異)。

法則25:選擇模型的時候,實用的性能要比預測能力更重要

你可能會用你的模型來預測點擊率(CTR)。當最終的關鍵問題是你要使用你的預測的場景。如果你用來對文本排序,那最終排序的品質可不僅僅是預測本身。如果你用來排查垃圾文件,那預測的精度顯然更重要。大多數情況下,這兩類功能應該是一致的,如果他們存在不一致,則意味著系統可能存在某種小增益。因此,假如一個改進措施可以解決日誌丟失的問題,但卻造成了系統性能的下降,那就不要採用它。當這種情況頻繁發生時,通常應該重新審視你的建模目標。

法則26:從誤差中查找新模式、創建新特徵

假設你的模型在某個樣例中預測錯誤。在分類任務中,這可能是誤報或漏報。在排名任務中,這可能是一個正向判斷弱於逆向判斷的組。但更重要的是,在這個樣例中機器學習系統知道它錯了,需要修正。如果你此時給模型一個允許它修復的特徵,那麼模型將嘗試自行修復這個錯誤。

另一方面,如果你嘗試基於未出錯的樣例創建特徵,那麼該特徵將很可能被系統忽略。例如,假設在GooglePlay商店的應用搜索中,有人搜索「免費遊戲」,但其中一個排名靠前的搜索結果卻是一款其他App,所以你為其他App創建了一個特徵。但如果你將其他App的安裝數最大化,即人們在搜索免費遊戲時安裝了其他App,那麼這個其他App的特徵就不會產生其應有的效果。

所以,正確的做法是一旦出現樣例錯誤,那麼應該在當前的特徵集之外尋找解決方案。例如,如果你的系統降低了內容較長的帖子的排名,那就應該普遍增加帖子的長度。而且也不要拘泥於太具體的細節。例如你要增加帖子的長度,就不要猜測長度的具體含義,而應該直接添加幾個相關的特徵,交給模型自行處理,這才是最簡單有效的方法。

法則27:嘗試量化觀察到的異常行為

有時候團隊成員會對一些沒有被現有的損失函數覆蓋的系統屬性感到無能為力,但這時抱怨是沒用的,而是應該盡一切努力將抱怨轉換成實實在在的數字。比如,如果應用檢索展示了太多的不好應用,那就應該考慮人工評審來識別這些應用。如果問題可以量化,接下來就可以將其用作特徵、目標或者指標。總之,先量化,再優化

法則28:注意短期行為和長期行為的差別

假設你有一個新系統,它可以查看每個doc_id和exact_query,然後根據每個文檔的每次查詢行為計算其點擊率。你發現它的行為幾乎與當前系統的並行和A/B測試結果完全相同,而且它很簡單,於是你啟動了這個系統。卻沒有新的應用顯示,為什麼?由於你的系統只基於自己的歷史查詢記錄顯示文檔,所以不知道應該顯示一個新的文檔。 要了解一個系統在長期行為中如何工作的唯一辦法,就是讓它只基於當前的模型數據展開訓練。這一點非常困難。

離線訓練和實際線上服務間的偏差

引起這種偏差的原因有:

1)訓練工作流和服務工作流處理數據的方式不一樣;

2)訓練和服務使用的數據不同;

3)演算法和模型間循的一個循環回饋。

法則29:確保訓練和實際服務接近的最好方式是保存服務時間時使用到的那些特徵,然後在後續的訓練中採用這些特徵

即使你不能對每個樣例都這樣做,做一小部分也比什麼也不做好,這樣你就可以驗證服務和訓練之間的一致性(見規則37)。在Google採取了這項措施的團隊有時候會對其效果感到驚訝。比如YouTube主頁在服務時會切換到日誌記錄特徵,這不僅大大提高了服務品質,而且減少了程式碼複雜度。目前有許多團隊都已經在其基礎設施上採用了這種策略。

法則30:給抽樣數據按重要性賦權重,不要隨意丟棄它們

當數據太多的時候,總會忍不住想要丟棄一些,以減輕負擔。這絕對是個錯誤。有好幾個團隊就因為這樣,而引起了不少問題(見規則6)。儘管那些從來沒有展示給用戶的數據的確可以丟棄,但對於其他的數據,最好還是對重要性賦權。比如如果你絕對以30%的概率對樣例X抽樣,那最後給它一個10/3的權重。使用重要性加權並不影響規則14中討論的校準屬性。

法則31:注意在訓練和服務時都會使用的表中的數據是可能變化的

因為表中的特徵可能會改變,在訓練時和服務時的值不一樣,這會造成,哪怕對於相同的文章,你的模型在訓練時預測的結果和服務時預測的結果都會不一樣。避免這類問題最簡單的方式是在服務時將特徵寫入日誌(參閱法則32)。如果表的數據變化的緩慢,你也可以通過每小時或者每天給表建快照的方式來保證儘可能接近的數據。但這也不能完全解決這種問題。

法則32:盡量在訓練工作流和服務工作流間重用程式碼

首先需要明確一點:批處理和在線處理並不一樣。在線處理中,你必須及時處理每一個請求(比如,必須為每個查詢單獨查找),而批處理,你可以合併完成。服務時,你要做的是在線處理,而訓練是批處理任務。儘管如此,還是有很多可以重用程式碼的地方。比如說,你可以創建特定於系統的對象,其中的所有聯結和查詢結果都以人類可讀的方式存儲,錯誤也可以被簡單地測試。然後,一旦在服務或訓練期間收集了所有資訊,你就可以通過一種通用方法在這個特定對象和機器學習系統需要的格式之間形成互通,訓練和服務的偏差也得以消除。因此,盡量不要在訓練時和服務時使用不同的變成語言,畢竟這樣會讓你沒法重用程式碼。

法則33:訓練採用的數據和測試採用的數據不同(比如,按時間上,如果你用1月5日前的所有的數據訓練,那測試數據應該用1月6日及之後的)

通常,在評測你的模型的時候,採用你訓練時用的數據之後生成的數據能更好反映實際線上的結果。因為可能存在每日效應(daily effects),你可能沒有預測實際的點擊率和轉化率。但AUC應該是接近的。

法則34:在二進位分類過濾的應用場景中(例如垃圾郵件檢測),不要為了純凈的數據做太大的性能犧牲

一般在過濾應用場景中,反面樣例並不會對用戶展示。不過假如你的過濾器在服務過程中阻止了75%的反面樣例,那麼你可能需要從向用戶顯示的實例中提取額外的訓練數據並展開訓練。比如說,用戶將系統認可的郵件標記為垃圾郵件,那麼你可能就需要從中學習。

但這種方法同時也引入了取樣偏差。如果改為在服務期間將所有流量的1%標記為「暫停」,並將所有這樣的樣例發送給用戶,那你就能收集更純凈的數據。現在你的過濾器阻止了至少74%的反面樣例,這些樣例可以成為訓練數據。

需要注意的是,如果你的過濾器阻止了95%或更多的反面樣例,那這種方法可能就不太適用。不過即使如此,如果你想衡量服務的性能,可以選擇做出更細緻的取樣(例如0.1%或0.001%),一萬個例子足以準確地估計性能。

法則35:注意排序問題的固有偏差

當你徹底改變排序演算法時,一方面會引起完全不同的排序結果,另一方面也可能在很大程度上改變演算法未來可能要處理的數據。這會引入一些固有偏差,因此你必須事先充分認識到這一點。以下這些方法可以有效幫你優化訓練數據。

1.對涵蓋更多查詢的特徵進行更高的正則化,而不是那些只覆蓋單一查詢的特徵。這種方式使得模型更偏好那些針對個別查詢的特徵,而不是那些能夠泛化到全部查詢的特徵。這種方式能夠幫助阻止非常流行的結果進入不相關查詢。這點和更傳統的建議不一樣,傳統建議應該對更獨特的特徵集進行更高的正則化。

2.只允許特徵具有正向權重,這樣一來就能保證任何好特徵都會比未知特徵合適。

3.不要有那些僅僅偏文檔(document-only)的特徵。這是法則1的極端版本。比如,不管搜索請求是什麼,即使一個給定的應用程式是當前的熱門下載,你也不會想在所有地方都顯示它。沒有僅僅偏文檔類特徵,這會很容易實現。

法則36:避免具有位置特徵的回饋迴路

內容的位置會顯著影響用戶與它交互的可能性。很明顯,如果你把一個App置頂,那它一定會更頻繁地被點擊。處理這類問題的一個有效方法是加入位置特徵,即關於頁面中的內容的位置特徵。假如你用位置類特徵訓練模型,那模型就會更偏向「1st-position」這類的特徵。因而對於那些「1st-position」是True的樣例的其他因子(特徵),你的模型會賦予更低的權重。而在服務的時候,你不會給任何實體位置特徵,或者你會給他們所有相同的默認特徵。因為在你決定按什麼順序排序展示前,你已經給定了候選集。

切記,將任何位置特徵和模型的其他特徵保持一定的分離是非常重要的。因為位置特徵在訓練和測試時不一樣。理想的模型是位置特徵函數和其他特徵的函數的和。比如,不要將位置特徵和文本特徵交叉。

法則37:測量訓練/服務偏差

很多情況會引起偏差。大致上分為一些幾種:

1.訓練數據和測試數據的性能之間的差異。一般來說,這總是存在的,但並不總是壞事。

2.測試數據和新時間生成數據之間的性能差異。同樣,這也總是存在的。你應該調整正則化來最大化新時間數據上的性能。但是,如果這種性能差異很大,那可能說明採用了一些時間敏感性的特徵,且模型的性能下降了。

3.新時間數據和線上數據上的性能差異。如果你將模型應用於訓練數據的樣例,也應用於相同的服務樣例,則它們應該給出完全相同的結果(詳見規則5)。因此,如果出現這個差異可能意味著出現了工程上的異常。

機器學習第三階段

有一些資訊暗示第二階段已經結束。首先,月增長開始減弱。你開始要考慮在一些指標間權衡:在某些測試中,一些指標增長了,而有些卻下降了。這將會變得越來越有趣。增長越來越難實現,必須要考慮更加複雜的機器學習。

警告:相對於前面兩個階段,這部分會有很多開放式的法則。第一階段和第二階段的機器學習總是快樂的。當到了第三階段,團隊就不能不去找到他們自己的途徑了。

法則38:如果目標不協調,並成為問題,就不要在新特徵上浪費時間

當達到度量瓶頸,你的團隊開始關注 ML 系統目標範圍之外的問題。如同之前提到的,如果產品目標沒有包括在演算法目標之內,你就得修改其中一個。比如說,你也許優化的是點擊數、點贊或者下載量,但發布決策還是依賴於人類評估者。

法則39:模型發布決策是長期產品目標的代理

艾麗斯有一個降低安裝預測邏輯損失的想法。她增加了一個特徵,然後邏輯損失下降了。當線上測試的時候,她看到實際的安裝率增加了。但當她召集發布復盤會議時,有人指出每日活躍用戶數下降了5%。於是團隊決定不發布該模型。艾麗斯很失望,但意識到發布決策依賴於多個指標,而僅僅只有一些是機器學習能夠直接優化的。

真實的世界不是網路遊戲:這裡沒有「攻擊值」和「血量」來衡量你的產品的健康狀況。團隊只能靠收集統計數據來有效的預測系統在將來會如何。他們必須關心用戶粘性、1 DAU,30 DAU,收入以及廣告主的利益。這些 A/B 測試中的指標,實際上只是長期目標的代理:讓用戶滿意、增加用戶、讓合作方滿意還有利潤;即便這時你還可以考慮高品質、有使用價值的產品的代理,以及五年後一個繁榮的企業的代理。

做出發布決策唯一容易的是當所有指標都變好的時候(或者至少沒有變化)。當團隊在複雜 ML 演算法和簡單啟發式演算法之間有選擇時;如果簡單的啟發式演算法在這些指標上做得更好;那麼應當選擇啟發式。另外,所有指標數值並沒有明確的孰重孰輕。考慮以下更具體的兩種情形:

如果現有系統是 A ,團隊不會想要轉移到 B。如果現有系統是 B,團隊也不會想要轉到 A。這看起來與理性決策相抵觸:但是,對指標變化的預期情形或許會發生,或許不會。因此任意一種改變都有相當大的風險。每一個指標覆蓋了一些團隊所關注的風險。但沒有指標能覆蓋團隊的首要關切——「我的產品在五年後會怎樣?」

另一方面,個體更傾向於那些他們能夠直接優化的單一目標。大多數機器學習工具也如此。在這樣的環境下,一個能夠創造新特徵的工程師總能夠穩定的輸出產品發布。有一種叫做多目標學習的機器學習類型開始處理這類問題。比如,給每個目標設定最低界限,然後優化指標的線性組合。但即便如此,也不是所有指標都能輕易表達為 ML 目標:如果一篇文章被點擊了,或者一個app被安裝了,這可能是只是因為這個內容被展示了。但要想搞清楚為什麼一個用戶訪問你的網站就更難了。如何完整預測一個網站將來是否能成功是一個AI完全(AI-complete)問題。就和電腦視覺或者自然語言處理一樣難。

法則40:保證集成模型(ensemble)的簡潔

接收原始特徵、直接對內容排序的統一模型,是最容易理解、最容易修補漏洞的模型。但是,一個集成模型(一個把其他模型得分組合在一起的「模型」)的效果會更好。為保持簡潔,每個模型應該要麼是一個只接收其他模型的輸入的集成模型,要麼是一個有多種特徵的基礎模型,但不能兩者皆是。如果你有單獨訓練、基於其它模型的模型,把它們組合到一起會導致不好的行為。

只使用簡單模型來集成那些僅僅把你的基礎模型輸出當做輸入。你同樣想要給這些集成模型加上屬性。比如,基礎模型生成得分的提高,不應該降低集成模型的分數。另外,如果連入模型在語義上可解釋(比如校準了的)就最好了,這樣其下層模型的改變不會影響集成模型。此外,強行讓下層分類器預測的概率升高,不會降低集成模型的預測概率。

法則41:當碰到性能瓶頸,與其精鍊已有的資訊,不如尋找有品質的新資訊源

你已經給用戶增加了人工統計屬性資訊,給文本中的詞增加了一些資訊,經歷了模板探索並且實施了正則化。然後,幾乎有好幾個季度你的關鍵指標都沒有過提高超過1%了。現在該怎麼辦?

現在是到了為完全不同的特徵(比如,用戶昨天,上周或者去年訪問過的文檔,或者來自不同屬性的數據)構建基礎架構的時候了。為你的公司使用維基數據(wikidata)實體或者一些內部的東西(比如Google的知識圖,Google』s knowledge graph)。你或許需要使用深度學習。開始調整你對投資回報的期望,並作出相應努力。如同所有工程項目,你需要平衡新增加的特徵與提高的複雜度。

法則42:不要期望多樣性、個性化、相關性和受歡迎程度之間有緊密聯繫

一系列內容的多樣性能意味著許多東西,內容來源的多樣性最為普遍。個性化意味著每個用戶都能獲得它自己感興趣的結果。相關性意味著一個特定的查詢對於某個查詢總比其他更合適。顯然,這三個屬性的定義和標準都不相同。

問題是標準很難打破。

注意:如果你的系統在統計點擊量、耗費時間、瀏覽數、點贊數、分享數等等,你事實上在衡量內容的受歡迎程度。有團隊試圖學習具備多樣性的個性化模型。為個性化,他們加入允許系統進行個性化的特徵(有的特徵代表用戶興趣),或者加入多樣性(表示該文檔與其它返迴文檔有相同特徵的特徵,比如作者和內容),然後發現這些特徵比他們預想的得到更低的權重(有時是不同的訊號)。

這不意味著多樣性、個性化和相關性就不重要。就像之前的規則指出的,你可以通過後處理來增加多樣性或者相關性。如果你看到更長遠的目標增長了,那至少你可以聲稱,除了受歡迎度,多樣性/相關性是有價值的。你可以繼續使用後處理,或者你也可以基於多樣性或相關性直接修改你的目標。

法則43:不同產品中,你的朋友總是同一個,你的興趣不會如此

Google的 ML 團隊 常常把一個預測某產品聯繫緊密程度(the closeness of a connection in one product)的模型,應用在另一個產品上,然後發現效果很好。另一方面,我見過好幾個在產品線的個性化特徵上苦苦掙扎的團隊。是的,之前看起來它應該能奏效。但現在看來它不會了。有時候起作用的是——用某屬性的原始數據來預測另一個屬性的行為。即便知道某用戶存在另一個屬性能湊效的歷史,也要記住這一點。比如說,兩個產品上用戶活動的存在或許就自身說明了問題。