kerastensorflow+分布式训练︱实现简易视频内容问答框架
內容來源:Keras 之父講解 Keras:幾行代碼就能在分布式環境訓練模型
把 Keras API 直接整合入 TensorFlow 項目中,這樣能與你的已有工作流無縫結合。至此,Keras 成為了
TensorFlow 內部的一個新模塊:tf.keras,它包含完整的 Keras API。用 Keras API 定義模型,用
TensorFlow estimator 和 experiments 在分布式環境訓練模型。
我們有一組 10 秒短視頻組成的數據集,視頻內容是人從事各種活動。一個深度學習模型將會觀察這些視頻的每一幀畫面,進行理解,然后你可以用簡短的自然語言問它視頻內容。
本例子中,一個男人把紙板箱放進車的行李箱里。任務是回答這個人在做什么。模型會處理該視頻和問題,試圖在可能的答案中挑選出正確的那一個。這次,它的回答是 “裝貨”。這個答案很有意思:如果僅僅看一幀畫面,是得不出該結論的——這個人也有可能在卸貨。所以,我們不僅要求模型能理解視頻畫面的內容,還要能理解每一幀畫面的先后順序。
放到三四年前,Keras 和 TensorFlow 誕生之前,這會是一個無比棘手的難題,全世界只有個位數的研究機構能處理。即便是一只由世界級專家學者、工程師組成的團隊,也需要半年左右的時間來一點一點解決。而現在,所有具備基礎 Python 編程技能的人都能借助工具處理該問題。我們這也是在使深度學習民主化。
下圖便是我們的神經網絡方案。它的結構可分為三個部分:
首先,一個分支會導入視頻輸入,把它轉化為對視頻內容編碼的矢量。另一個分支導入問題,也把它轉化為矢量。現在,你可以把視頻矢量和問題矢量連結起來,在它們之上添加一個分類器。該分類器的任務,是從一堆潛在回答中,選出正確的那一個。
第一步,是把視頻輸入矢量轉化為張量。一個視頻只是一組連續的畫面幀,每一幀都是一個圖像。對于圖像處理,你要做的全部的事,就是運行一個 CNN。
每個 CNN,會從每幀畫面提取一個矢量表示。最后所得到的,是對每幀畫面進行編碼的矢量序列。當遇到一個序列,你會做什么?當然是用序列處理模塊—— LSTM 把它跑一遍。LSTM 會把序列簡化為一個單一矢量,該矢量編碼了視頻的所有信息,包括每一幀畫面、以及它們的順序。
下一步,使用類似的過程來處理問句。它是一個由詞語組成的序列,需要用內嵌模塊把每個詞語映射為一個詞矢量。你就獲得了一個詞向量序列,再用另一個 LSTM 層來簡化。
當視頻、問題的矢量表示都有了以后,就可以把它們連接起來,在上面添加一個用于選擇正確答案的分類器。
這就是深度學習的魔力:把復雜的輸入,比如視頻、圖像、語言、聲音變成矢量,變成幾何空間中的不同的點——把了信息變成了幾何空間中的點,這就是深度學習的本質。
而當完成之后,你就可以用線性代數來處理幾何空間,捕捉到到有趣的映射模式。在上面的例子中,該模型就是在學習一個視頻、問題空間到答案空間的映射。而執行的方式,是把不同的信息處理模塊組合起來。這是一個十分自然的操作:對象是圖像,就用圖像處理模塊 CNN;對象是序列,就用序列處理模塊 LSTM;如果需要從一組候選中選擇一個,就用分類器。
因而,創建深度學習模型,在概念上和拼樂高積木是很相似的,前者的實現也應該這么簡單。這張圖,就是對我們的模型在 Keras 上的直觀結構。
我們用一個按時間分布的層,把 CNN 應用于由輸入視頻和張量組成的時間軸上的每一幀畫面。然后把輸入導入 LSTM 層,前者被簡化為單一張量。InceptionV3 CNN 會內置預訓練的權重,這一點很重要,因為以目前的視頻輸入,靠我們自己是無法學習到有趣的視覺特征的。我們需要利用現有的、在大型數據集上學習到的視覺特征。這個例子里是 ImageNet。在深度學習里,這是一個常見的舉措,而 Keras 使它變得更方便。問題的編碼更加簡單。把詞語序列導入內嵌層(embedding layer),生成矢量序列,再用 LSTM 層簡化為單一矢量。
.
代碼演示
下面是視頻編碼機器人的完整代碼,加起來只有幾行,非常簡潔。你從確認視頻輸入開始,高亮部分就是你的視頻輸入:
這是一個由合理幀數組成的序列?!癗one” 就是幀數,它沒有被定義,你可以不同的 batch 進行修改。每一幀畫面的分辨率是 150*150。下一步,僅用一行我們就定義了整個 InceptionV3 模型。它裝滿了從 ImageNet 得到的預訓練權重。所有這些已經內置于 Keras 中,你不需要做任何多余操作,僅此一行代碼足矣。代碼并不包含頂層,因為并不相關,但在頂部加入了 pooling,使得我們能從每一幀抓取一個矢量。
下一步,CNN 被設置為不可訓練,意味它的參數表示并不會在訓練中更新。這一步很重要,因為該 CNN 已經有了非常不錯的表示,沒必要更改。再強調一遍,這是深度學習的常用操作,把封住不再改動的預訓練模型添加入流水線。在 Keras 中,這項操作變得十分簡便。有了不再變動的 CNN 之后,我們用一個時間分配層(time distributed layer),把它在視頻輸入的時間軸上均衡分配。這樣做的結果,是得到所有幀的張量,再導入 LSTM 層得到單一矢量。
如上圖,問題處理就更加簡單。最終的問題輸入,被處理為整數序列。為什么是整數呢?每一個整數,都會用某些詞匯映射到一個矢量。隨后把整數序列導入嵌入層,這會把每個整數映射到一個矢量上。這些訓練過的嵌入是模型的一部分。再把矢量序列導入 LSTM,簡化為單一矢量。
這里有一個有意思的地方。通常使用 LSTM 的時候,有許多東西需要考慮、許多套路需要參考。但在這里,除了設置輸入單位的數量,我們并沒有做任何其他操作配置 LSTM 層——所有 “最佳套路”,都已經成為 Keras 的默認設置。這是 Keras 的一大特點,已知的最佳方案被用于默認設置。對于開發者,這意味著模型直接就能用,不需要對所有參數都進行調參。
在完成對視頻、問題的編碼之后,你只需要用 concate up 把它們轉化為單一矢量,然后在頂端加入兩個密集層,它們會從備選詞匯中選出一個作為答案。
下一步,使用輸入和輸出初始化 Keras 模型,本質上它是一個神經網絡各層的圖(a graph of layers)的容器。然后要確定訓練設置,比如優化器、Adam 優化器和損失函數。到現在一切都很簡單,我們已經定義了模型和訓練設置。下面是在分布式環境訓練模型,或許在 Cloud ML 上。
只用幾行代碼,你就可以用 TensorFlow Estimator 和 Experiment 類訓練模型。所有需要你做的事,僅僅是寫 experiment 函數,用內置的 get_estimator 方法在其中定義模型,并用模型來初始化 Estimator。有了 estimator 之后,再用它創建 Experiment,在其中你確認輸入數據。
僅僅用幾行非常直觀、具有高度可讀性的 Python 代碼就可以實現,我們就定義了一個相當先進的模型、在分布式環境訓練它,來解決視頻問答難題。而這在幾年前是完全難以想象的。
到這里,你應該已經看到,像 Keras 這樣的 API 是如何推動 AI 民主化。這借助兩個東西實現:
其中一個,當然是 Keras API。為在 TensorFlow 中定義模型提供了易于使用、功能強大的工具。而且,每一層都有非常優秀的默認設置,讓模型可以直接運行。
另外一個,則是全新的高級 TensorFlow 訓練 API:Estimator 和 Experiment。
把它們結合到一起,使得開發者們能夠以相當小的時間、經歷代價處理任何深度學習難題。
總結
以上是生活随笔為你收集整理的kerastensorflow+分布式训练︱实现简易视频内容问答框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习批处理之安装一键装机必备软件
- 下一篇: 算法探讨——再议经典算法问题:求最大子序