天天看點

【神經網絡搜尋】Efficient Neural Architecture Search

【GiantPandaCV導語】本文介紹的是Efficient Neural Architecture Search方法,主要是為了解決之前NAS中無法完成權重重用的問題,首次提出了參數共享Parameter Sharing的方法來訓練網絡,要比原先标準的NAS方法降低了1000倍的計算代價。從一個大的計算圖中挑選出最優的子圖就是ENAS的核心思想,而子圖之間都是共享權重的。

【神經網絡搜尋】Efficient Neural Architecture Search

ENAS是一個快速、代價低的自動網絡設計方法。在ENAS中,控制器controller通過在大的計算圖中搜尋挑選一個最優的子圖來得到網絡結構。

controller使用Policy Gradient算法進行訓練,通過最大化驗證集上的期望準确率作為獎勵reward。

被挑選的子圖将使用經典的CrossEntropy Loss進行訓練。

子網絡之間的權重共享可以讓ENAS性能更強大的性能,同時要比經典的NAS方法降低了約1000倍的計算代價。

NAS-RL使用了450個GPU訓練了3-4天,花費了32,400-43,200個GPU hours才可以訓練出一個合适的網絡,需要大量的計算資源。NAS的計算瓶頸就在于需要讓每個子模型從頭開始收斂,訓練完成後就廢棄掉其訓練好的權重。

本文主要貢獻是通過讓所有子模型共享權重、避免從頭開始訓練,進而有效提升了NAS的訓練效率。随後的子模型可以通過遷移學習的方法加速收斂速度、進而加速訓練。

ENAS可以做到使用單個NVIDIA GTX 1080Ti顯示卡,隻需要花費16個小時。同時在CIFAR10上可以達到2.89%的test error。

ENAS可以看作是從一個超網中得到一個自網絡,如下圖所示。6個節點互相連接配接得到的就是超網(是一個有向無環圖),通過controller得到紅色的路徑就是其中的一個子網絡。

【神經網絡搜尋】Efficient Neural Architecture Search

舉一個具體的例子,假設目前有4個節點:

【神經網絡搜尋】Efficient Neural Architecture Search

上圖是controller,具體實作是一個LSTM,需要做出以下決策:

激活哪個邊

對應Node選擇什麼操作

第一個Node,controller首先采樣一個激活函數,這裡采用的是tanh,然後這個激活會接收x和h作為輸入。

第二個Node,先采樣上一個index=1,說明Node2應該和Node1相連接配接;然後再采樣一個激活函數relu。

第三個Node,先采樣上一個index=2,說明Node3應該和Node2相連接配接;然後采樣一個激活函數Relu。

第四個Node,先采樣上一個index=1,說明Node4應該和Node1相連接配接,然後采樣一個激活函數tanh。

結束後發現有兩個節點是loose end, ENAS的做法是将兩者結果做一個平均,得到最終輸出。

【神經網絡搜尋】Efficient Neural Architecture Search

在上述例子中,假設節點數量為N,一共使用了4個激活函數可選。搜尋空間大小為:\(4^N\times N!\)

其中\(4^N\)代表N個節點可選的4個激活函數組成的空間,\(N!\) 代表節點的連接配接情況,之是以是階乘也很容易了解,因為随後的Node隻能連接配接之前出現過的Node。

在ENAS中,有兩組可學習參數,Controller LSTM中的參數\(\theta\) 和 子模型共享的權重參數\(w\)。具體流程是:

LSTM sample出一個子模型,然後訓練模型\(w\), 通過标準的反向傳播算法進行訓練,訓練完成以後在驗證集上進行測試。

通過驗證集上結果回報給LSTM,計算\(\theta\)的梯度,更新LSTM的參數。

如此反複,可以訓練出一個LSTM能夠讓模型在驗證集上的性能最佳。

第一步:訓練共享參數w

首先固定住controller的參數,然後使用蒙特卡洛估計來計算梯度,更新w權重:

【神經網絡搜尋】Efficient Neural Architecture Search

m是從\(\pi(m;\theta)\) 中采樣得到的模型,對于所有的模型計算模型損失函數的期望。右側公式是梯度的無偏估計。

第二步:訓練controller 參數\(\theta\)

這一步固定住w,更新controller參數,希望可以得到的Reward值(也就是驗證集準确率)盡可能大。

【神經網絡搜尋】Efficient Neural Architecture Search

這裡使用的是REINFORCE算法來進行計算的,具體内容可以檢視NAS-RL那篇文章中的講解。

【神經網絡搜尋】Efficient Neural Architecture Search

有了上邊的例子做鋪墊,卷積的這部分就很好了解了,差別有幾點:

節點操作不同,這裡可以是3x3卷積、5x5卷積、平均池化、3x3最大池化、3x3深度可分離卷積,5x5深度可分離卷積 一共六個操作。

上圖Node3輸出了兩個值,代表先将node1和node2的輸出tensor合并,然後在經過maxpool操作。

計算卷積網絡設計的空間複雜度,對于第k個節點,頂多可以選取k-1個層,是以在第k層就有\(2^{k-1}\)種選擇,而這裡假設一共有L個層需要做從6個候選操作中做選擇。那麼在不考慮連線的情況下就有\(6^L\)可能被挑選的操作,由于所有連線都是獨立事件,那複雜度計算就是:\(6^L\times 2^{L(L-1)/2}\)(除以2是因為連線具有對稱性,采樣1,2和2,1結果是一緻的)。

ENAS中首次提出了搜尋一個一個單元,然後将單元組合拼接成整個網絡。其中單元分為兩種類型,一種是Conv Cell 該單元不改變特征圖的空間分辨率;另外一種是Reduction Cell 該單元會将空間分辨率降低為原來的一半。

【神經網絡搜尋】Efficient Neural Architecture Search

假定每個cell裡邊有B個節點,由于網絡設定是node1和node2是單元的輸入,是以剛開始這部分需要特殊處理,固定兩個單元,搜尋随後的單元,即還剩下B-2個節點需要搜尋。

【神經網絡搜尋】Efficient Neural Architecture Search

如上圖所示,從node3開始生成,首先生成兩個需要連接配接的兩個對象,indexA和indexB; 然後生成兩個op, 分别是sep 5x5和直連id。将操作sep 5x5施加到indexA對應節點上;将操作直連施加到indexB對應節點上,然後通過add的方式融合特征。

【神經網絡搜尋】Efficient Neural Architecture Search

搜尋空間複雜度計算:首先分為Conv Cell和Reduction Cell,由于他們并沒有本質不同,隻是所有的操作的stride設定為2,複雜度也是一樣的。

假定目前是第i個節點,可以選擇來自先前i-1個節點中的兩個節點,并且可選操作有5個。假設隻選擇一個節點,那麼複雜度是\(5\times (B-2)!\), 由于要選擇兩個節點,兩個節點的選擇是互相獨立的,是以複雜度計算變為:\((5\times (B-2)!)^2\) 。而又有Reduction Cell和Conv Cell也是互相獨立的,是以複雜度變為\((5\times (B-2)!)^4\) ,計算完畢。

主要是在NLP中常用的語料庫Penn Treebank和CV中經典的資料集CIFAR-10上進行了實驗。

在單個GTX 1080Ti上訓練了10個小時,達到了55.8的test perplexity, 下圖是通過ENAS找到的RNN單元。

【神經網絡搜尋】Efficient Neural Architecture Search

結果如下:

【神經網絡搜尋】Efficient Neural Architecture Search

資料集:CIFAR10有5w張訓練圖檔和1w張測試圖檔,使用标準的資料預處理和資料增強方法:如将訓練圖檔padding到40x40大小,然後随機裁剪到32x32,水準随機反轉。

訓練細節: 共享權重w使用Nesterov momentum來訓練,使用cosine schedule調整lr,lr最大設定為0.05,最小設定為0.001,T0=10, Tmul=2。每個子網絡設定運作310個epoch。權重初始化使用He initialization。weight decay設定為\(10^{-4}\)。

controller的設定細節,policy gradient的權重\(\theta\)使用均勻的從[-0.1,0.1]初始化,使用0.00035的學習率,使用Adam優化器,設定tanh常數為2.5 temerature 設定為5.0; 給controller 得到的熵添加0.1的權重。

在macro搜尋空間中,通過在skip connection兩層之間添加KL 散度來增加稀疏性, KL散度項對應的權重設定為0.8.

【神經網絡搜尋】Efficient Neural Architecture Search
【神經網絡搜尋】Efficient Neural Architecture Search

實驗結果對比如下:

【神經網絡搜尋】Efficient Neural Architecture Search

代碼這裡參考NNI中的實作,以macro為例,ENASLayer實作如下:

其中的mutables是NNI中的一個核心類,可以從LayerChoice所提供的選擇中挑選一個操作,其中最後一個SEConvBranch是筆者自己補充上去的。

mutable LayerChoice就是從備選選項中選擇其中一個操作

mutable InputChoice是選擇前幾層節點進行連接配接。

主幹網絡如下:

需要注意有幾個點:

self.stem是第一個node,手動設定的。

池化是強制設定的,在某些層規定進行下采樣。

搜尋過程調用了NNI提供的API:

mutator是NNI提供的一個類,就是上述提到的controller,這裡具體調用的是EnasMutator。

這部分是EnasMutator中一個核心函數,實作的是REINFORCE算法。

ENAS核心就是提出了一個超網,每次從超網中采樣一個小的網絡進行訓練。所有的子網絡都是共享超網中的一套參數,這樣每次訓練就不是從頭開始訓練,而是進行了遷移學習,加快了訓練速度。

有注釋代碼連結如下:https://github.com/pprp/SimpleCVReproduction/tree/master/nni

代碼改變世界

繼續閱讀