追一科技機器學習平臺技術專家王達,為大家分享追一科技技術同仁在機器學習平臺建設的實踐經驗。本文根據當天分享整理。
機器學習作為人工智慧的一個子集,隨著 AI 概念逐漸被大眾所認知、認可,也越來越受到企業的關注。除了追隨前沿技術的網際網路公司之外,很多來自傳統行業的公司也分別設立了 AI 相關的部門,希望能夠趕上人工智慧這趟快車。
隨著 AlphaGo 的橫空出世,越來越多的應用開始採用深度學習的方案。在大資料逐漸與深度學習融合的階段,由於資料量越來越大,模型訓練的流程越來越長,越來越複雜,對於通用的大規模機器學習平臺的需求也因此應運而生。到底怎麼樣的平臺才是一個好平臺,才能真正做到易用好用?
王達帶來了關於“如何構建全流程機器學習平臺”的實踐與思考。從對機器學習平臺的認識和理解、構建機器學習平臺的關鍵技術以及機器學習平臺具體落地和最佳化的方案三個方面進行講解,分享了他們是如何去構建一個滿足開發、業務、運維、客戶四方需求的機器學習平臺。
機器學習的需求一直存在,不同的公司裡也有著各種各樣的相關平臺,藉著深度學習的東風,傳統的機器學習平臺需要結合新技術開出新花朵,而新的平臺則想要藉此機會去撼動原有的格局。一時間群雄並起,都希望能夠逐鹿中原。
目前市面上的機器學習平臺在介面上基本上大同小異,都是採取四欄的設計,其中 A 區域是一級功能的選擇,就是跟機器學習最相關的頂級概念。比如工作流、資料及演算法和模型,對於資料和模型來說,都可以納入一個統一的資源管理系統來進行管理。需要處理的大部分是資料庫的增刪改查,這裡不再贅述。我們主要來聊聊最重要的工作臺介面。
介面設計的原則是一定要簡化操作,把所有操作都放到同一個介面中,讓使用者以最自然的方式去使用。對於工作臺來說,有幾個部分必不可少。第一個是專案管理區域和運算元的區域,即圖中 B 區域。第二個是實際用來拖拽、構造工作流的畫布區域,即 C 區域。D 區域是不同的運算元的配置區域。
總體來說這種整合開發環境 IDE 有一些類似,只是我們不在 IDE 裡寫程式碼,而是把所需要的演算法和資料集拖到 C 的區域,然後連線構造成一個工作流。
針對機器學習平臺,基本上可以分為資源、平臺、應用三個切入點。透過雷達圖來看他們各自的強項。
從資源切入,在傳統機器學習上,因為繼承了原來的 hadoop 和 spark 生態的基礎,比較佔優勢,對業務和運維也會比較友好。
從平臺切入的這種方式在服務釋出及學習以及資料探勘的方向表現的會更好。
如果從應用切入,主要發力點有兩個,一個是對深度學習很充分的支援,還有一個就是平臺本身的擴充套件性。
這三種平臺的切入方向也代表著不同的設計思路,各有側重點。從資源和平臺切入,是在大資料生態的基礎上改造升級,以支援深度學習這一最新潮流。而從應用切入則一開始就是圍繞著深度學習的工作流展開。
今天就結合追一科技在機器學習平臺上的實踐來說說如何從應用的角度切入,來構建一個滿足開發、運維、業務和客戶需求的機器學習平臺。構建平臺會涉及到方方面面的技術,我們從中挑選了五個最關鍵的跟大家分享。
第一個關鍵點是如何透過工程設計,讓平臺能夠擁有一定程度的智慧,而不只是一個資源排程和程式執行的平臺。這裡涉及到兩個要點,一個是平臺後設資料和平臺所管理的資料的收集與整合,二是如何在這些資料的基礎上為平臺本身賦能。
第二個關鍵點是關於平臺底層的架構,在深度學習的大背景下,如何能夠儘可能地提高硬體資源的利用率,加快模型的訓練過程。
第三個關鍵點是如何能夠做到閉環,即從離線到線上再反饋回來到離線這樣一個閉環,讓模型擁有自學習、自動更新的能力。這部分無論是對平臺還是應用本身,都是有一定要求的。
第四個關鍵點是如何透過容器的形式來支援各種程式語言和框架,核心的思路是面向規範程式設計,只要符合我們定義好的介面規範,並且能夠放到容器中,就可以放到平臺中去使用。
最後一個關鍵點是平臺的大腦——排程器,面對不同型別的應用,如何設計排程器來支援各類不同的需求。
通往平臺智慧之路並不是一蹴而就的,而是需要一層一層構建的。所謂平臺,其實是一種規範,這種規範本身就是一種專業化的表現,像一隻看不見的手,最終會體現到我們的產品中。
需要注意的是,定規範是為了真正用起來,這就引申出來三個要點:第一個要點就是這個規範要以夠用為原則,一定是簡約而不簡單的,要學會抓大放小,當然也要留意長尾的問題;第二個就是一定要小心過度設計的陷阱,避免欄位的線性相關;最後是我們在配合規範的時候,是採用這種資源描述的檔案,而不是這種固定的欄位來去做的,為未來留下更大的擴充套件空間。
確定了底層最基本的資源描述之後,就可以在此之上開發更加高階的應用了。比如演算法推薦和自動調參。
對於演算法推薦來說,我們把原來極其依賴開發人員經驗的問題轉化成一個目標為所使用演算法的多分類問題,以及一個推薦系統機制的問題。因為有了演算法,資料和工作流的統一描述,相當於把不同場景的不同任務放到了同一個座標系中。那麼就可以根據資料演算法和工作流本身的特性去做智慧推薦和分類。
自動調參也是如此,除了可以提供一些初始的搜尋條件,供使用者選擇外,還可以根據以前的相似任務來進行智慧的引數選擇。
平臺智慧存在的最終意義就是讓沒有太多機器學習經驗的使用者,能夠解決那些原本只能由經驗豐富的演算法研發人員完成的任務。從這個角度來看,演算法推薦自動調參,都是為了通向這個目標的一步。這裡還有很多工作需要我們去探索和挑戰。
除了平臺智慧外,機器學習平臺的另一個重要指標就是硬體資源的使用效率。對於 CPU 和記憶體來說,無論是基於 docker 還是基於虛擬化的方案,都已經有了比較好的支援。而針對深度學習所必需的 GPU 資源,因為與 CPU 的計算模式有比較大的差別,目前還沒有一個非常完美的方案。
針對 GPU 資源的高效利用,必須要解決以下三個問題:第一個就是如何利用多張顯示卡加速模型的訓練。第二個是如何解決叢集中 GPU 資源異構的問題。第三個是如何最佳化 GPU 資源叢集的計算效率。
第一個是多卡加速的問題。目前有兩種思路,一個是資料並行,一個是模型並行,這兩種方式各有其優劣,但是目前的主流來說是用資料並行的方式來做,因為資料並行的方式更加簡單,也更加穩定。模型並行無法知道全域性的特性,而資料並行的主要問題在於網路和 IO 的消耗巨大,但是可以採用一些工程上的最佳化,基本達到接近於線性的加速比。另外目前主要的深度學習框架都有支援多卡訓練的機制。
第二個是叢集異構的問題。在這裡指的是計算資源並不一致的問題。除了 GPU 的差異之外,在容器的解決方案中,CPU 和記憶體的差異同樣是需要考慮的。這個問題有兩種解決方法。一種是將全部硬體更換至最新,這樣就沒有不一樣的情況。另一種經濟實惠的方式是結合排程器,透過給不同的 GPU 打上標籤,在任務派發的時候儘可能地分配到同一組同一型號的 GPU 上,這樣能更高效的利用好資源。
第三個是如何最佳化 GPU 資源叢集的計算效率的問題。這裡主要解決的問題有四個,分別是算力問題、大 batchsize 問題、擴充套件效率問題以及 IO 問題,下面分別來說一下簡單的解決思路。
算力的問題,可以透過用 16 位來計算,32 位來更新的方法,這樣計算量會小很多,更新的時候也不會降低它的精度,變相提高了計算量。大 batchsize 問題,主要用的是 lars(層次自適應速率縮放)的演算法,即對不同的神經網路層用不同的學習率,配合上對應的引數,調整學習率,這樣可以把大 batchsize 所帶來的問題降到最低。擴充套件的問題,採用的是去中心化方案,透過環狀的方式,就可以保證我們去掉了網路結構中的瓶頸,這樣它的擴充套件效率會得到一個很大的提升。IO 問題,則可以把一些資料預存取到 GPU 裡,減少了資料載入的時間。透過以上最佳化,可以對深度學習的任務在多卡執行的效率上有非常大的一個提升。
全流程閉環是著眼於構建圖中所說的從離線到線上再回到離線這一流程,讓模型和服務擁有越來越智慧的能力。那麼如何去構建這樣一個全流程的流水線閉環,關鍵還是在第一步所說的規範。
對於傳統的 spark 任務來說,我們可以利用 spark 本身對全流程進行釋出,釋出之後我們對線上的日誌以及處理好的資料做一個收集處理,然後再由資料倉儲重新滾動到下一次的訓練中,這樣就完成了一個閉環。
而對於深度學習的任務來說,在基於容器的方案下,可以透過微服務的形式,把整個工作流釋出成一個線上的流程,讓每一個步驟都可以在 K8S 裡進行監控和擴充套件。
接下來看如何利用容器的優勢來構建完整的計算任務執行機制。
Docker 自 2013 年問世以來,已經在諸多場景凸顯出自己的優勢,而 google 開源的 kubernetes 為機器學習平臺提供了一個穩定的任務執行環境,使得整個平臺的擴充套件性和通用性非常好。
kubernetes 的 Job 機制為單次的計算任務執行提供了完整的支援,這種 service 的機制則為模型上線提供了支援。對於每一個 Job 來說,因為我們把計算環境以及所用的演算法以及對應的資料都已經完全解耦了,每次執行的時候,只要從對應的映象倉庫演算法倉庫和資料倉儲中拉取所需要的資源,統一放到這樣一個容器裡,然後去執行就可以。
自定義新增到平臺的演算法,只要滿足規範,就可以享受和系統演算法一樣的待遇,極大的擴充套件了平臺能力。
最後是最核心的排程器的模組,作為整個平臺的大腦,平臺的高階特性都離不開排程器的支援。
具體來說,排程器可分為兩個子模組,一個是在使用者進行任務相關的操作後出發的,另一個則是週期執行的。排程器首先會進行許可權檢查和資源檢查,生成對應的 task 佇列或者是 service 佇列,佇列是帶優先順序排序的,可以在平臺上提高它的優先順序,這樣比較緊急的任務可以優先去做。而週期執行的任務則是按照順序來進行任務派發、任務狀態檢查、服務啟動、服務狀態監控這幾個任務,如果有定時的任務,也會在指定的時間進入佇列,並且去進行派發。
這種任務解析與任務派發的分離,使得多租戶的平臺擁有統一的資源排程能力,避免出現了資源競爭的情況。task 和 service 雙優先佇列的設計,可以最大程度的兼顧公平與效率,滿足大部分常見場景的需求。
最後我們來看一下平臺具體落地和最佳化的方案。主要包括三部分的內容,第一個是系統架構,第二個是工作流程,最後是系統部署。
系統架構圖
機器學習平臺的具體工作流程
怎麼樣去打造一個能夠快速迭代部署上線的流程,這裡分享一些工程化的經驗和技巧。
我們在設定開發和測試流程的時候,需要把環境放到第一位,除了日常開發測試的公有云環境之外,在私有化部署的時候,單機和叢集的情況其實都是需要考慮的。
針對環境問題,可以透過一種技術與四套工具來應對。一種技術便是容器化與 kubernetes,四套工具則是環境檢測工具、配置生成工具、安裝嚮導工具和回滾重試工具。環境檢測工具顧名思義是用於確定系統的環境狀況,包括網路磁碟埠記憶體等各類基礎的安裝包等等。環境檢測透過之後,則會由配置生成工具生成對應不同環境的對應配置方被後面的安裝嚮導工具呼叫。當安裝出現一些意外情況的時候,可以使用回滾重試工具進行徹底的清理,保證每次安裝前環境保持一致。
機器學習平臺作為一個通用企業專業的平臺,一般來說是需要在公司內部跨團隊進行開發的。那麼怎麼樣去跨團隊做出對技術背景要求比較高的產品,在多組協同的情況下,怎麼樣能夠保證大家在同一個維度溝通?
我們採用的是四個同一的方式,也就是同一定義域、同一流程、同一文件、同一環境。這些所有的“同一”都是力求保證大家在同一個維度去溝通。最後是工程上的四個優先,第一個是規範優先,第二個是離線優先,第三個是穩定優先,最後是測試優先。
通用組建開源,核心模組自研。
開源:Spark 生態,Hadoop 生態,Kubernetes 生態,通用演算法;
自研:排程器,專用演算法,資源規範;
降低開源演算法和元件的接入難度。
資源粒度較粗,抽象程度不如虛擬化;
對伺服器的配置要求,共享的層級較淺;
原生 docker 方案網路功能較弱。
子系統獨立許可權,分散的小金庫而不是一個大金庫;
無 cookie 無 session,https+token 驗證;
自定義運算元的安全性,透過 docker 進行隔離。