同一個模型用theano,tf,pytorch實現,performance可能差距較大嗎?

所有參數都相同


去年 10 月,在 DCASE 2017 Challenge 結束後不久,我用了一周半的時間,自己擼了一個做該項比賽任務四的神經網路。

先簡要介紹一下這個任務。任務的目標是判斷一段 10 秒的音頻中含有哪些音頻事件,事件一共有 17 種,主要是各種車輛和警報的聲音。訓練數據是 Google Audio Set 的一個子集,含有大約 5 萬條音頻,約佔全集的 2.5%。成績用所有事件的 micro-average F1 來衡量,如果你不知道這是個什麼東西,那你就知道這是一個百分數,越高越好,就行了。

這次比賽的結果(我並沒有參加)如下所示,可以看到,第 3~7 名的成績都是非常接近的。

我 10 月的神經網路是用 Keras + Theano 搭建的,含有三個卷積層和一個 GRU 層。我並沒怎麼調參數,竟也一舉獲得了 50.7% 的成績,可以位列第三。(註:50.7% 這個數字,是我聯繫了比賽的組織方,在他們用於排名的私密測試集上測試的結果;在公開測試集上,成績為 50.1%,下文的數字也都是在公開測試集上測的)後來發現,我當時選的隨機種子特別好,但換了其它種子,成績也都在 48~50% 之間。

然而 Theano 是一個行將就木的工具包,我從 11 月開始轉向 PyTorch。作為練手,我首先就用 PyTorch 重新搭建了上面的神經網路。其結果是,成績一直在 44~46% 徘徊。注意上面的排名表,如果認為在公開和私密測試集上的成績會差不多,那就意味著我從正數第三跌到了倒數第三!

於是我開始了漫長的調試過程,並深入查看了 Keras、Theano 和 PyTorch 的源代碼。

我懷疑的第一個點是初始化。果不其然,Keras 對大部分權重矩陣都採用了標準的 Glorot uniform 初始化,對 GRU 的 recurrent weight 採用了正交初始化,對所有偏置都採用了零初始化;而 PyTorch 對所有參數都一律採用了 uniform 初始化,但範圍與 Glorot 不同。修改了 PyTorch 初始化之後,在某些參數設置下 PyTorch 取得了跟 Keras + Theano 相同的成績,但在某些參數設置下差距依然明顯。

我懷疑的第二個點是 Nesterov momentum 的實現。經查 Keras 與 PyTorch 的實現確實不同,但推過公式後,發現二者等價。

最終,我發現了 Keras GRU 層的一個默認參數設置有貓膩:recurrent_activation=hard_sigmoid。原來,Keras GRU 層中的門使用了一個近似的 sigmoid 函數:

y = egin{cases} 0,  x le -2.5 \ 0.2x + 0.5,  -2.5 < x < 2.5 \ 1,  x ge 2.5 end{cases}

把 PyTorch GRU 層中的 sigmoid 函數也換成上述的近似函數後,PyTorch 終於也達到了 48~50% 的成績。是不是很奇怪:近似的函數反倒性能更好!換這個函數費了我一整天的勁,因為 PyTorch 中有三種 GRU 的實現,優先順序較高的兩種是用 CUDA 代碼寫的,根本看不懂;只有設法把這兩種實現都繞過,才能讓 PyTorch 採用 Python 實現,然後再修改其代碼。

總結一下,就是不同的工具包,會在很多實現的細節上有差別,在你搭建一個大的神經網路的時候,可能不會有意地去設置每個細節,而是相信工具包的默認實現。然而不同的默認實現,性能可能會有顯著差別。

然而……當我用整個 Google Audio Set 去訓練神經網路時,我發現成績又降下來了,並且這次修改初始化和 sigmoid 函數的實現都不起作用了。真 TM 玄學 (╯‵□′)╯︵┻━┻


person reid,跑baseline,一模一樣的參數,或者各種調參大法也都使用過了,最好的結果,gluon上比pytorch上低5個點以上,至今沒找到原因,另外長寬不一樣的圖片,在pytorch上和一致的圖片性能幾乎一樣,但是在gluon上卻有顯著下降,同樣沒找到原因。所以棄坑了,以後還是繼續pytorch走起吧。


我是徹底服氣了。

目前手上有個mxnet模型,自己完成自己實現。訓練完精度68.5。

由於要加入GAN的一些東西,pytorch比較好實現,為了遷移已經花了一兩周,已經遇到如下的坑了:

1.mxnet默認的優化器是SGD,而pytorch是adam,至少我clone的那個項目是。後來修改了。

2.mxnet與訓練的模型範圍是[-128,+128]但是pytorch會自動把圖片壓縮到[0,1]之間。

後期我把所有的都修改了,把mxnet的模型轉成Pytorch的,並且每一層都看了輸出,甚至把數據迭代器都改成之前mxnet寫的,輸出完全一致。優化器,初始化的方法,完全一樣,然後扔進去訓練,pytorch效果跌了6%。煉丹什麼的,真的很難說啊:)


你們對用最優化方法解決高維非線性問題一無所知~~~(滑稽

高維非線性問題簡直是人類科技的死穴,隨便拿個學科出來,最後都會發現高維非線性問題擋在那。能搞出點東西來就算不錯啦,成系統的理論根本沒有,把超參設一設,開始迭代,回家睡覺啦!


所有參數相同,模型初始化方式相同,理論上應該是一致的,不過不同框架可能在計算方法上(例如矩陣求逆,求導,可能用的優化計算方法不一樣),或者浮點計算上保留的精度不一樣,那就會產生差距了。


推薦閱讀:

TAG:機器學習 | 深度學習DeepLearning | TensorFlow | PyTorch |