0
| 本文作者: AI科技評論 | 2016-06-27 13:56 |
今年8月,雷鋒網將在深圳舉辦盛況空前的“全球人工智能與機器人峰會”,屆時雷鋒網將發布“人工智能&機器人Top25創新企業榜”榜單。目前,我們正在拜訪人工智能、機器人領域的相關公司,從中篩選最終入選榜單的公司名單。
如果你也想加入我們的榜單之中,請聯系:2020@leiphone.com。

正在美國紐約舉行的國際機器大會(ICML)上,我們很難忽略 Facebook 研究科學家們的身影——他們呈現三篇論文、主導四場研討會、并主講兩場教程。其中包括 FB 研究科學家 Ronan Collobert、Armand Joulin 和 Laurens van der Maaten合作的論文《Torch:機器學習研究的開源平臺》。
Torch 是進行深度機器學習研究的主要框架之一,不過研究人員必須重復實驗邏輯,Facebook 推出的 Torchnet 由于鼓勵模塊化編程和代碼重用,未來可以推動機器視覺、自然語言處理和語音處理等多個機器學習領域的發展,并且,整個研究社區都能通過插件參與貢獻。
摘要
Torch 7 是一個支持 CPU 和 GPU 計算的科學計算平臺,在簡單的腳本語言中帶有輕量的包裝,可以快速執行常見的代數運算。它已成為(深度)機器學習研究的主要框架之一。不過,Torch 不提供機器學習實驗的抽象和樣板代碼。因此,研究人員一次次重復完成那些并非彼此協作的實驗邏輯。我們在此介紹 Torchnet:一個為機器學習提供抽象和樣板代碼的開源框架。它鼓勵模塊化編程和代碼重用,這減少了漏洞出現的幾率,并且讓不同步的數據載入和高效的多GPU計算,使用起來簡單明了。Torchnet 是用 Lua 語言編寫的,因此用 Torch 裝置在任何架構上都很容易安裝。我們認為未來 Torch 會成為一個平臺,外界社區可以通過插件參與貢獻。
1. 簡介
Torch 7 是一個針對科學計算框架的靈活計算庫,包含 CPU (通過 OpenMP / SSE)和 GPU (通過 CUDA)上、針對主要代數運算的低等級高效執行,以及使用 Lua 腳本語言的非常輕量的包裝(Collobert等人,2011)。Torch 有非常活躍的開發者社區,已經開發了許多程序包,包括優化、流行學習、度量學習和神經網絡等等。Torch 神經網絡程序包目前是一個非常流行的深度學習框架,因為它融合了靈活性和計算高效性。
Torch 神經網絡程序包使得建立模型、評估模型輸出、以及基于其參數或輸入來計算模型輸出的導數變得很容易。但是,要實施一個完整的學習實驗仍然需要大量開發工作,而 torch / nn 無法為之提供支持:研究人員們需要開發一個高效的數據加載器,將可用的數據區分為訓練組和測試組,用所選的優化器連接模型(梯度)進行評估,進行性能測量來監控訓練、評估最終模型的質量,并且設立日志。此類樣板代碼的開發經常包含大量代碼重復,并且容易出錯,這可能會導致不正確的研究結果。尤其是缺少預定義的抽象和參考執行,讓研究人員很難寫出容易為他人所采用和重用的代碼。
這篇論文中我們呈現 Torch:一個新的開源框架,推動(深度)機器學習實驗快速前進。Torchnet 提供了一系列關鍵抽象、樣板代碼和參考執行,目標是讓代碼可以重用,并且實現高效。Torchnet 特別鼓勵一種模塊化設計,明確區分數據庫、數據載入過程、模型、優化和性能測量。不同的組成部分在一個 Engine 中互相聯接,它執行模型訓練和評估。模塊化設計使其很容易重用代碼、并開發一系列實驗:例如,在不同的數據庫上運行同樣的實驗,相當于插入一個不同的數據載入器;改變評估標準,相當于插入一個不同的性能表。Torch 也不犧牲效率:它提供不同步數據載入的創新支持,并在多GPU上支持訓練。
我們預見,Torchnet 未來會成為一個平臺,研究社區可以通過機器學習實驗或工具的插件來參與貢獻。這會讓驗證實驗設置的細節(和正確度)、復制結果和重用代碼都變得更加容易。

表1:Torchnet 中所有實現的 Dataset 概況。
2. 抽象
Torchnet 從有所相似、但是問世更早的 Lush 框架中獲得啟發,執行五種主要類型的抽象:(1) Dataset,(2) DatasetIterator,(3) Engine,(4) Meter 和(5) Log。下面,我們分別呈現這五種主要的抽象:
2.1. Dataset
Dataset 抽象只提供兩種函數:(1) size( ) 函數,返回數據庫中樣本的數量,以及(2) get ( idx ) 函數,返回數據庫中第 idx 個樣本。創建復雜的數據載入器可以通過將一個數據庫插入另一個數據庫,后者執行各種操作,例如數據聯接、數據庫分割、批量數據、數據重新取樣、數據過濾和樣本轉換,這與 Torchnet 對模塊化編程的重視一致。表1展現了通過使用 Torchnet 在數據庫上可以運行的所有操作。模塊化方法的主要優勢是,它在少數幾行代碼中幫助打造復雜的數據載入器:當你想在一個新數據庫上訓練模型時,只要執行一個返回數據庫中樣本數量的函數、以及一個返回某個具體樣本的函數就行。接下來,表1中的數據庫可以基于某個特定的分布用于各項操作,包括重新平衡類別、打造小批量進行訓練、將數據分割為訓練數據和測試數據等等。而且,實施模型訓練或評估的引擎,對于其用來訓練的數據庫基本上是不可知的:例如,當使用 Imagenet(Deng等人,2009)、MS COCO(Lin等人,2014b) 數據庫等數據載入器的時候,在 MS COO 數據庫上重新訓練(或測試)一個 Imagenet 卷積神經網絡(He等人,2016),相當于只要將 MS COCO 數據庫的核心數載入器插入現有代碼中就行了。
2.2. 數據庫迭代器
當運行訓練或測試時,必須在數據庫中所有樣本上進行迭代,并進行參數更新或者性能測量積累(分別是 Engine 和 Meter 函數的功能)等操作。類似這樣的數據庫迭代器最簡單的形式是一個簡單的 for 循環,從1運行至數據庫大小,調用 get()函數,用循環值作為輸入;DatasetIterator 執行的就是這個迭代器,帶有一個可選的依賴數據的過濾器(可以通過 filter ( ) 閉包來實現)。在實際情況中效率非常重要,寧可多線不同步地執行數據載入。ParallelDatasetIterator 提供這項功能:其中線的數量是預定義的,都從其中的數據庫中載入數據,當迭代器中的樣本遇到請求,會返回首個可用的樣本。如果有足夠多線,數據迭代器永遠都會有可供即刻返回的可用樣本,這樣我們可以將整個針對訓練或測試的數據載入和預處理都隱藏起來。當數據在進入模型前執行復雜轉換時,這變得尤為重要,例如,在訓練計算機視覺模型時經常應用在圖像上的仿射變換和色彩變換(Howard,2013)。
2.3. Engine
當利用不同的模型和數據庫進行實驗時,經常是基于相同的訓練過程。Engine 抽象提供模型訓練和測試必需的樣本邏輯。特別重要的是,它完成模型(默認為 nn.Module)、DatasetIterator 和損失函數(默認為 nn.Criterion)之間的交互。舉個例子,一個 Engine 執行兩個說明這類互動的函數:(1)一個 train( ) 函數從數據中取樣、在模型中傳輸該數據、計算損失值、在模型中傳輸損失梯度并執行參數更新;(2)一個 test( ) 函數從數據中取樣、在模型中傳輸數據并測量最終預測的質量。
Engine 提供了一系列鉤子,讓用戶不用編輯 Engine 的核心邏輯,就能插入針對某個具體實驗的代碼,例如性能 Meter。這鼓勵了代碼重用,并可能預防漏洞,同時仍然為編寫訓練和測試代碼提供了完全靈活性。鉤子有一個特別好的特點,就是它們被打造為閉包,這樣,要在訓練模型使用的代碼和測試模型使用的代碼之間分享邏輯(例如復制數據樣本到 GPU)就很方便。

表2:Torchnet 中實現的所有 Meter 的概況。
目前的 Torchnet 代碼包含兩個 Engine 操作:(1)一個 SGDEngine,通過 SGD 執行模型的訓練;(2)一個 OptimEngine,通過 torch / optim 程序包中的任何優化器——包括 AdaGrad(Duchi等人,2011)、Adam(Kingma & Ba,2015)、共軛梯度法以及 L-BFGS——執行模型的訓練。
2.4. Meter
通常在學習模型的訓練和測試中,我們希望測量一些特性,例如執行訓練階段所需要的時間、在所有樣本上平均的損失函數值、二元分類器的 ROC 曲線下的面積、多類分類器的分類錯誤、檢索模型的精度和召回、或者排名算法的歸一化衰減累積增量。Torchnet 提供了各種 Meter,能防止研究人員一遍遍重新執行此類性能測量(此過程中還可能引入漏洞)。表2 是所有目前 Torchnet 中實現的所有 Meter 的概況。。大部分性能表(除了 TimeMeter 和AverageValueMeter 之外)執行兩個主要函數:(1)add(output,target)函數,將模型輸出和一或多個樣本相應目標的值加入性能表;(2)value()函數,返回目前性能表的值。
2.5. 日志
Torchnet 為記錄實驗提供兩種 Log:一種簡單的 Log,還有一種 RemoteLog。兩者都可以以原始文本(輸入到一個文檔或者 stdout)和 JSON 的形式輸出日志信息。
3. 例子
在這個部分,我們將呈現一個簡單、可用的例子,說明如何在 MNIST 數據庫上使用 Torchnet 訓練一個邏輯回歸量。代碼首先包括所需的相關性:

然后,我們定義一個函數,在 MNIST 訓練或測試庫中打造一個不同步的數據庫迭代器。數據庫迭代器收到一個閉包作為輸入,后者打造 Torchnet 數據庫目標。這里,數據庫是一個 ListDataset,僅僅從張量返回包含圖像和目標的行;實踐中,你會用自己的數據庫定義代替這個 ListDataset。核心的 Dataset 被包裹在一個 BatchDataset 中,用于打造大小為128的迷你批次。

然后,我們設立了一個簡單的線性模型:

接下來,我們初始化 Torchnet 引擎,實施鉤子來重設、更新和打印平均損失和平均分類錯誤。調用更新平均損失和分類錯誤的鉤子,是在 forward () 調用以下的訓練 criterion 之后:


之后,我們使用 SGD 將邏輯損失最小化:

模型訓練后,我們在測試組上測量平均損失和分類錯誤:

大部分高級例子可能會在 engine 中實施額外的 hooks。例如,如果你想在每一次訓練后測量測試錯誤,這可以在 engine.hooks.onEndEpoch 鉤子中實施。讓同一個樣本運行 GPU 需要為代碼做一些簡單的增補,特別是將模型和數據都復制到 GPU。要復制數據樣本到 GPU 的一個緩沖器上,可以通過實施一個鉤子來實現,鉤子在可用的樣本出現后執行:

4. 與其他框架相比較
Torchnet 與其他深度學習框架都非常不同,例如 Caffe(Jia等人,2014)、Chainer、TensorFlow(Abadi等人,2016)和 Theano(Bergstra等人,2011),因為 Torchnet 不專注于在深度網絡中執行有效的推理和梯度計算,而是在一個深度學習框架之上(在我們的例子中,也就是 torch / nn)提供一個框架 ,通過提供樣板代碼以及鼓勵模塊化設計——后者讓研究人員可以恨簡單地進行代碼重用——這讓快速實驗更加簡單。Torchnet 對于其學習框架不做什么假設:Torchnet 抽象可以為例如 Caffe 和 TensorFlow 進行直接實施。
Torchnet 與 Blocks 和 Theano 的 Fuel 類似。特別是 Torchnet 的 Dataset 類似于 Fuel 的 Transformer,但是 Torchnet 的 Dataset 更加靈活,因為他們還完成數據批量、分離和重新取樣。Torchnet 的 DatasetIterator 類似于 Fuel 的 DataStream,但是 Torchnet 對不同步、多線數據載入有更好的支持: Fuel 提供的 ServerDataStream 運行單獨的數據載入過程,通過 TCP 插座與訓練器聯絡——多線數據載入必須手動完成。與之相比,Torchnet 提供的插件 ParallelDatasetIterator 讓不同步的、多線數據載入變得非常簡單。Fuel 的 ServerDataStream 與 Torchnet 的 ParallelDatasetInterator 相比有一個潛在優勢,即是數據載入過程可以在與訓練代碼不同的機器上運行。在 Blocks 里,Brick 類似于 torch / nn 的 Module,Blocks 里的 MainLoop 類似于 Torchnet 的 Engine。Blocks 可以實現一些基本的性能測試,例如分類錯誤,但是目前 Blocks 不提供 Torchnet 的 Meter 所提供的那種豐富的測量庫。
5. 展望
我們預見 Torchnet 未來會成為一個由社區擁有的平臺,在 Torchment 的核心完成之后,與 Torch 一樣提供一系列子程序包。我們認為,最重要的子程序包未來將實施與許多機器學習問題相關的樣板代碼,例如計算機視覺(vision)、自然語言處理(text)和語音處理(speech)。不過,其他子程序包可能更小,專注于更加特定的問題、甚至特定的數據庫。舉個例子,我們認為未來會有小的子程序包,將各種數據庫包裝入 Torchnet 的 Dataset,例如 Imagenet 和 COCO 等視覺數據庫(Deng等人,2009;Lin等人,2014a)、TIMIT 和 LibriSpeech 等語音數據庫(Garofalo等人,1993;Panayotov等人,2015)、以及“十億單詞基準”和 WMT-14 等文本數據庫(Chelba等人,2013)。
VIA ICML

雷峰網原創文章,未經授權禁止轉載。詳情見轉載須知。