機器學習與微博:TensorFlow在微博的大規模應用與實踐

作者|何滄平

編輯|Vincent

AI前線出品| ID:ai-front

TensorFlow 在微博業務中有豐富的應用場景,文字、圖片、視頻,各具特色。微博機器學習平台集成 TensorFlow 服務,支持分散式訓練,在廣告點擊預測應用中,本輪分享的主講人何滄平積累了一些 TensorFlow 優化經驗,在 8 月 3 日晚 AI 前線社群分享活動中,他將自己的這些經驗分享給了大家。本文首發於 InfoQ 垂直公眾號 AI 前線。

借 AI 前線提供的交流機會,我給各位彙報一下 TensorFlow 在微博的使用情況和在分散式計算上的一點經驗,錯誤疏漏不足之處,敬請批評指教。

TensorFlow 在微博的應用場景

今天的分享內容由虛到實,由概括到具體。

微博的日活和月活數量都在增長,移動端比例很高,占 91%。2017 年 4 月份的財報顯示,營收同比增漲 67%,一個重要原因就是移動端搶到了用戶的碎片時間。

微博里隨處可見推薦信息:推薦的新聞、推薦的視頻、推薦的新賬號。最重要還有推薦的廣告。

用戶登錄以後,立刻就要計算推薦什麼內容。拿推薦廣告來說,備選的廣告數以萬計,需要排序給出最可能被點擊的幾條廣告。

如果切中用戶的購買需要,廣告就不再是打擾。

垃圾嚴重影響用戶體驗,色情、暴力、反動、低俗,寧可錯殺不可漏網,十分嚴格。

人工智慧反垃圾的目標是提高準確度、降低成本。

圖像質量也是用戶體驗的基本要求。

用戶可以容忍不感興趣的圖片,但很難容雜亂的圖像。

例如左邊的美女圖,看起來賞心悅目,手機上刷過,即使不停下細看,也不會反感。

右邊的圖片,裡面也是美女,但加上文字之後,立刻變得雜亂,版式與酒店裡的小卡片相仿。很可能被認定為騙子。

明星是微博制勝的法寶。明星是公眾人物,話題多、熱度高、影響力大。明星粉絲狂熱,消費力強。

為粉絲推薦她他喜歡的明星的行程、事件、各種評價,粉絲愛看。甚至明星代言的廣告,粉絲可能都會喜歡。停留在微博的時間越長,有意無意瀏覽的廣告就越多。正確識別明星就很重要了,如果不巧推薦了用戶討厭的明星,可能就沒了刷微博的心情。

明星臉識別是微博的特色,有海量的明星圖片,也有巨大的識別需求。

明星臉識別有特別的困難:常用人臉識別研究所用的照片表情、造型較少,不同人之間的差別較大。而明星表情豐富,造型多變,無論男女都化妝!不少人妝容近似,有些整容臉連人腦都傻傻分不清,計算機就更難分清了。

上部的圖片可能歸屬兩個及以上類別,因此稱為「兼類」。

圖片、視頻分類的最終目的都是為了關聯廣告。喜歡旅遊的用戶就給她他推薦旅遊景點、線路、酒店、機票、戶外裝備等。

如果廣告能夠切中用戶本來就要買的物品,就不必費盡心機說服用戶購買不必要的商品,只需要將購買場所由一個地點(網站、實體店)轉移到另一個地點,將購買時間由將來轉移到現在,將商品品牌由 A 切換為 B。這樣廣告效果自然會好很多,點擊率高,用戶還不反感。

例如,印度電影《三個白痴》中幾次提到太空筆,我當時就特別想買一支,在京東上搜了半個小時。如果能夠提前識別到這個廣告點,並在播放過程中推薦購買鏈接,很可能立即就下單了。

但是,圖像分類難,視頻精細分類更難,又不得不分。短視頻(5 分鐘以內)方興未艾,變現模式還不成熟,處於燒錢階段。相對於文本、圖片,短視頻的帶寬成本更高,消耗的用戶時間更多。如果關聯廣告的轉化率不高,入不敷出,無法長久。

TensorFlow 在微博的應用技術 & 案例

務虛內容結束,下面是具體點的技術。

微博機器學習平台承擔了離線訓練和在線預測任務。微博實時產生的文本、圖片、視頻顯示後轉入後台,用於提取特徵、離線訓練。

越來越多的業務使用深度學習方法,TensorFlow/Caffe 框架被集成進來。

離線訓練主要使用 GPU 機群。由於業務增長過快,計算機群有一部分來自阿里雲。

這一頁完全是個人理解。

對規模巨大的訓練任務,TensorFlow 提供了分散式的模式。

TensorFlow 分散式計算與 HPC 的 MPI(Message Passing Interface) 分布計算區別很大。用過 MPI 的人都知道,MPI 進程相互平等,保證沒有瓶頸進程。MPI-IO 也設計得每個主機都能均勻分擔 IO 壓力。MPI 進程上的計算任務也要求均勻劃分,保證各個進程的計算進度保持一致。MPI 進程之間也只交換數據塊的邊界,盡量減少網路流量,壓縮通信時間。

TensorFlow 的分散式計算設計得簡單粗暴。

若干參數伺服器 (parameter server) 和若干勞工 (worker) 組成一個機群 (cluster),勞工承擔運算任務,將每步運算得到的參數(權重和 bias)提交給參數伺服器,參數伺服器將來自所有 worker 的參數合併起來,得到全局參數,然後將全局參數發送給勞工。勞工在全局參數的基礎上繼續下一步運算。

TensorFlow 採用主從模式,參數伺服器是瓶頸。每步都要傳遞所有的參數,網路流量太大,假設每個勞工上參數佔用內存 1GB,機群包含 1 個參數伺服器和 10 個勞工,那麼每個迭代步將產生 20GB 的網路流量,按照 10GbE 網路計算,通信時間至少需 16 秒。而實際上,每個 batch 數據的運算時間可能還不足 1 秒,模型參數佔用的內存可能遠大於 1GB。從理論分析來看,TensorFlow 分散式運算的效率不如 MPI。

有人說深度學習只是高性能計算的一個特殊應用,我認為不是這樣。

如圖中表格所列,TensorFlow 機群就與 HPC 機群有重大區別。

HPC 機群的 3 大特點:高性能計算晶元(高端 CPU、GPU)、高速網路、並行存儲。TensorFlow 機群只需要其中的 1 個:高端 GPU。

勞工在一批數據上訓練得到?W 和?b(合稱為?P),稱為一步訓練。

如上圖所示,所有的勞工(Device A/B/C)在完成一步訓練後,暫停訓練,將自己得到的?P 發送到參數伺服器(Parameter Device)。參數伺服器一直等待,直到來自所有的勞工的參數變化量?P 都接收成功。參數伺服器將所有的?P 相加取平均,然後用這個均值更新舊參數(更新公式請參見隨機梯度演算法),得到新參數 P,接著將 P 發送給所有的勞工。勞工在接收到新參數 P 以後,才進行下一步的訓練。

與用 1 台伺服器訓練相比,用 N 台勞工同時訓練 + 同步更新參數等價於將 batch 的規模擴大了 N 倍。具體來說,如果用 1 台伺服器時,每步訓練採用 100 張數字圖片(batch=100), 那麼用 4 個勞工得到的參數變化量(即?P)同步更新,就相當於每步訓練採用 400 張數字圖片(batch=400)。從而,參數變化得更平穩,收斂更快。

同步更新也有缺點:整體速度取決於最慢的那個勞工。如果勞工之間的軟硬體配置差別較大,有明顯的速度差異,同步更新計算速度較慢。

為了避免勞工有快有慢造成的等待,TensorFlow 提供了非同步更新策略。

如圖下部所示,當有一個勞工訓練得到一個參數變化量?P 時,不妨假設是圖中的 Device A,該勞工立即將?P 發送給參數伺服器。參數伺服器接收到來自勞工 Device A 的?P 後,不等待其它的勞工,立即用?P 更新全局參數,得到全局參數 P,緊接著將 P 發送給勞工 Device A。勞工 Device A 接收到全局參數 P 後,立即開始下一步訓練。

由非同步更新參數的過程可知,它等價於只用 1 台伺服器訓練:都是每次用一小批(batch)圖像訓練更新參數,只是各批數據的上場順序不能事先確定,上場順序由勞工的隨機運行狀態確定。

剛開始運算時,勞工 0(左邊) 先算了 10100 步(對應 localstep), 此後勞工 1(右邊)才開始運算。這說明,在非同步運算模式下,勞工之間確實不相互等待。勞工 0 和勞工 1 都運算了全局第 10100 步 (global_step_value),說明運算的剖分並不十分準確。

2 個勞工都執行了第 13142、13144、13146、13148 步,但都沒有執行 13143、13145、13147 這 3 步。這說明 Tensorflow 非同步更新的任務指派會隨機出錯,並不是絕對不重不漏。所幸隨機梯度法對更新順序沒有要求,少量的錯誤對最終計算結果影響不大。

同步更新模式不能真正地同步執行,將程序殺死的時候,2 個勞工執行完的步數相差很多。勞工 0 本地執行了 11023 步之後,全局步數竟然只有 7072,肯定出錯了。

網路上也有人報告了這個錯誤:

github.com/tensorflow/t

TensorFlow 開發者已經確認這是一個漏洞,但尚未修復。

公式預警。。。。

以 MNIST 手寫數字識別為例,上部分公式迭代一步就使用所有 n 個樣本。

下部公式將所有樣本分割成若干批次(batch)。

TensorFlow 的非同步更新,就是不同的勞工使用不同的小批訓練樣本來更新權重和 bias,不能事先確定每個勞工的更新順序。具體舉例:假設有 2 個勞工執行訓練任務,勞工 0 負責更新奇數批次樣本 b1/b3/b5…b499,勞工 1 負責更新偶批樣本 b2/b4,…,b500。

由於各種隨機因素,樣本的使用順序可能是 b1àb3àb5àb2àb7àb4à…因為樣本的批次劃分本身就是隨機的,這樣亂序更新仍然是隨機的,對最終結果沒有什麼影響。

TensorFlow 同步更新時,對所有勞工得到的梯度求平均,然後更新權重和截距。仍然假設有 2 個勞工,它們分別訓練第 1 批和第 2 批樣本得到梯度?w1 和?b1 截距分別為?w2 和?b2,同步之後的梯度如圖中所示。

從而,同步更新等價於一次使用 2m 個訓練樣本,正則化係數和 batch 大小都擴大為原來的 2 倍而已。如果勞工數量很多(例如 20 個),那麼同步更新就等價於一次使用 2000 個訓練樣本,與劃分 batch 的初衷不符。因此,建議不要使用同步更新。

注意公式里紅色的(2m)

下面是一個具體優化案例:

CTR(Click-Through-Rate,點擊通過率)是營收的關鍵。

對候選廣告按點擊可能性排序,然後插入到用戶信息流之中。

deepCTR 不完全是特徵工程,輸入層與隱層的連接關係也是不全連接。

千億樣本數據近百 TB,為提高效率,採用多人推薦過的 TensorFlow 隊列。

個人理解,隊列的設計初衷很好(如圖中表格所示),但實際性能很差,GPU 利用率只有 5%。查找原因發現,程序卡在線程同步操作上,而這個線程同步就來自於 TensorFlow 隊列。於是嘗試用別的方式讀取訓練樣本文件。

左圖橫軸採用對數坐標。

隊列讀以 CSV 帶寬只有極限帶寬的 1/467,隊列讀取 tfrecord 格式文件帶寬提升至 1.24MB/s,提高至 3.2 倍。由於 tfrecord 格式文件較小,讀完一個文件的耗時降低至 15%(272.6/1789.9)。

用 pandas 讀取文件帶寬達到極限帶寬的 35%。最終捨棄 TensorFlow 隊列,選用 pandas 讀 CSV 文件。

當 CSV 文件小於 1/3 內存時,直接用 pandas 一次性讀入內存。不用 tf 隊列,數據混洗就要程序員自己完成,所幸不麻煩。

對大於內存 1/3 的文件,直接拆分成多個小文件。需要程序員自行保證均勻使用各個小文件。

最後給各位彙報一個小遊戲。

用 MNIST 訓練得到的 CNN 網路來識別漢字,「霸」字被識別為 1。這點很容易理解,得到的 CNN 網路只有 10 個類別,不得不在 0~9 個數字中選一個。

因為「霸」字與任何數字都不像,識別為任何數字的「概率」應該都不太大吧,例如都小於 0.2(隨便說的數值)。可是實際情況卻是這樣:0~9 分類對應的概率差別很大,最大接近 0.8,最小接近 0,卷積網路識別漢字的時候不會猶豫不決,錯得十分堅定。

從這個小實驗里可以發現幾個問題:

圖像的特徵究竟是什麼?如果有,如何用這些特徵來區分不認識的圖像(比如這個例子里的漢字)?

如何控制一個網路的泛化能力?這個例子中的泛化能力看起來太強了,以致於把漢字都識別成數字了。目前看來,CNN 的泛化能力幾乎是聽天由命。

softmax 後的值真的代表概率嗎?看起來它們僅僅是和為 1 正數。概率本質的隨機性體現在哪裡呢?

這些問題,我還沒有想明白,這裡提出來,請各位朋友批評指教。

問答環節

問題 1:隊列讀取性能差是否是由於設置 cache 的樣本數問題?回答:cache 基本沒有影響。batch_size 會有影響,最關鍵還是線程鎖的問題。

問題 2:(反垃圾)這一步的準確率怎麼算的?是模型準確率嗎?

回答:這個涉及到業務,不便透露。可以私下交流。

問題 3:千億級別 feature 沒有模型並行嗎?感覺模型單機放不了,不能數據並行。

回答:數據並行,因此研究分散式運算。

問題 4:1 億條評論的話,你怎麼判斷分類器是否分正確了?還是說這裡的準確率只是在測試集上的準確率?

回答:業務上具體做法不便透露。這裡提醒一下,微博有舉報、屏蔽功能。

問題 5:微博的 TensorFlow 環境配置,資源管理和分散式計算是用的第三方平台嗎?還是自己封裝的

回答:資源管理和分散式計算嘗試過幾種方案,開源軟體 + 自行定製。多種機群,安全級別和管理方式不完全一樣,因此資源管理方式(網路、存儲、許可權)也不一樣。

問題 6:會考慮評價 GPU 的利用率嗎?比如用 deepbench 測?有什麼 GPU 提升利用率的經驗分享?

回答:GPU 利用率是成本核算的重要指標,很重視。查看 GPU 利用率比較簡單:命令行 nvidia-smi,英偉達還有專門的庫,提供輕量級的 C、JAVA 等介面。

提高 GPU 利用率經驗:如果顯存能裝得下,盡量使用 1 個模型訓練;設定顯存使用量(例如 0.5),將 2 個及以上作業放在同一個 GPU 上。IO 性能差的話,會導致數據供應不上,從而 GPU 利用低。PPT 中 deepCTR 優化案例就是這個情況。batch 太小、權重矩陣過小,都會導致不能充分利用 GPU 的大量核心(通常有 4000-5000 個),利用率低。

問題 7:如果在龐大的 csv 上訓練, 用 tf 隊列和用 spark df 製作生成器的效果有比對過么?

回答:目前沒有對比過 tf 隊列和 spark df。

作者介紹

何滄平,微博研發中心演算法工程師,目前負責建設深度學習平台。對高性能計算(HPC)較熟悉,著有《OpenACC 並行編程實戰》一書。如有相關技術問題可以私下與講師討論,講師微信:272702575

全文完

AI前線提供最新最全AI領域技術資訊、一線業界實踐案例、搜羅整理業界技術分享乾貨、最新AI論文解讀。歡迎關注我們的專欄:AI前線

接下來會陸續更新一系列與 TensorFlow 理論與實踐案例相關的文章,這是第一篇,敬請期待。


推薦閱讀:

編程是大眾化需求嗎?關於設計和編程的思考
Object Detection(1):R-CNN實踐
透過認知智能剖析商業本質(iPIN CEO楊洋)丨硬創公開課

TAG:TensorFlow | 机器学习 | 人工智能 |