作者|何滄平
編輯|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,肯定出錯了。
網路上也有人報告了這個錯誤:
https://github.com/tensorflow/tensorflow/issues/9596,
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 理論與實踐案例相關的文章,這是第一篇,敬請期待。