作者:Cecelia Shao編譯:ronghuaiyang導讀
預訓練模型用起來非常容易,但是你是否忽略了可能影響模型效能的細節呢?你執行過多少次下面的程式碼:
import torchvision.models as modelsinception = models.inception_v3(pretrained=True)
或者是這個
from keras.applications.inception_v3 import InceptionV3base_model = InceptionV3(weights='imagenet', include_top=False)
看起來使用這些預訓練的模型已經成為行業最佳實踐的新標準。畢竟,有一個經過大量資料和計算訓練的模型,你為什麼不利用呢?
預訓練模型萬歲!
利用預訓練的模型有幾個重要的好處:
合併超級簡單快速實現穩定(相同或更好)的模型效能不需要太多的標籤資料遷移學習、預測和特徵提取的通用用例NLP領域的進步也鼓勵使用預訓練的語言模型,如GPT和GPT-2、AllenNLP的ELMo、谷歌的BERT、Sebastian Ruder和Jeremy Howard的ULMFiT。
利用預訓練模型的一種常見技術是特徵提取,在此過程中檢索由預訓練模型生成的中間表示,並將這些表示用作新模型的輸入。通常假定這些最終的全連線層得到的是資訊與解決新任務相關的。
每個人都參與其中
每一個主流框架,如Tensorflow,Keras,PyTorch,MXNet等,都提供了預先訓練好的模型,如Inception V3,ResNet,AlexNet等,帶有權重:
Keras ApplicationsPyTorch torchvision.modelsTensorflow Official Models (and now TensorFlow Hubs)MXNet Model ZooFast.ai Applications很簡單,是不是?
但是,這些benchmarks可以復現嗎?
這篇文章的靈感來自Curtis Northcutt,他是麻省理工學院電腦科學博士研究生。他的文章‘Towards Reproducibility: Benchmarking Keras and PyTorch’ 提出了幾個有趣的觀點:
resnet結構在PyTorch中執行得更好, inception結構在Keras中執行得更好在Keras應用程式上不能復現Keras Applications上的已釋出的基準測試,即使完全複製示例程式碼也是如此。事實上,他們報告的準確率(截至2019年2月)通常高於實際的準確率。當部署在伺服器上或與其他Keras模型按順序執行時,一些預先訓練好的Keras模型會產生不一致或較低的精度。使用batch normalization的Keras模型可能不可靠。對於某些模型,前向傳遞計算(假定梯度為off)仍然會導致在推理時權重發生變化。你可能會想:這怎麼可能?這些不是相同的模型嗎?如果在相同的條件下訓練,它們不應該有相同的效能嗎?
並不是只有你這麼想,Curtis的文章也在Twitter上引發了一些反應:
關於這些差異的原因有一些有趣的見解:
了解(並信任)這些基準測試非常重要,因為它們允許你根據要使用的框架做出明智的決策,並且通常用作研究和實現的基線。
那麼,當你利用這些預先訓練好的模型時,需要注意什麼呢?
使用預訓練模型的注意事項
1、你的任務有多相似?你的資料有多相似?
對於你的新x射線資料集,你使用Keras Xception模型,你是不是期望0.945的驗證精度?首先,你需要檢查你的資料與模型所訓練的原始資料集(在本例中為ImageNet)有多相似。你還需要知道特徵是從何處(網路的底部、中部或頂部)遷移的,因為任務相似性會影響模型效能。
閱讀CS231n — Transfer Learning and ‘How transferable are features in deep neural networks?’
2、你如何預處理資料?
你的模型的預處理應該與原始模型相同。幾乎所有的torchvision模型都使用相同的預處理值。對於Keras模型,你應該始終為相應的模型級模組使用 preprocess_input函式。例如:
# VGG16keras.applications.vgg16.preprocess_input# InceptionV3keras.applications.inception_v3.preprocess_input#ResNet50keras.applications.resnet50.preprocess_input
3、你的backend是什麼?
有一些關於HackerNews的傳言稱,將Keras的後端從Tensorflow更改為CNTK (Microsoft Cognitive toolkit)提高了效能。由於Keras是一個模型級庫,它不處理諸如張量積、卷積等較低級別的操作,所以它依賴於其他張量操作框架,比如TensorFlow後端和Theano後端。
Max Woolf提供了一個優秀的基準測試專案,發現CNTK和Tensorflow之間的準確性是相同的,但CNTK在LSTMs和多層感知(MLPs)方面更快,而Tensorflow在CNNs和embeddings方面更快。
Woolf的文章是2017年發表的,所以如果能得到一個更新的比較結果,其中還包括Theano和MXNet作為後端,那將是非常有趣的(儘管Theano現在已經被廢棄了)。
還有一些人聲稱,Theano的某些版本可能會忽略你的種子。
4、你的硬體是什麼?
你使用的是Amazon EC2 NVIDIA Tesla K80還是Google的NVIDIA Tesla P100?甚至可能是TPU?看看這些不同的pretrained模型的有用的基準參考資料。
Apache MXNet’s GluonNLP 0.6:Closing the Gap in Reproducible Research with BERTCaleb Robinson’s ‘How to reproduce ImageNet validation results’ (and of course, again, Curtis’ benchmarking post)DL BenchStanford DAWNBenchTensorFlow’s performance benchmarks5、你的學習率是什麼?
在實踐中,你應該保持預訓練的引數不變(即,使用預訓練好的模型作為特徵提取器),或者用一個相當小的學習率來調整它們,以便不忘記原始模型中的所有內容。
6、在使用batch normalization或dropout等優化時,特別是在訓練模式和推理模式之間,有什麼不同嗎?
正如Curtis的帖子所說:
使用batch normalization的Keras模型可能不可靠。對於某些模型,前向傳遞計算(假定梯度為off)仍然會導致在推斷時權重發生變化。
但是為什麼會這樣呢?
Expedia的首席資料科學家Vasilis Vryniotis首先發現了Keras中的凍結batch normalization層的問題。
Keras當前實現的問題是,當凍結批處理規範化(BN)層時,它在訓練期間還是會繼續使用mini-batch的統計資訊。我認為當BN被凍結時,更好的方法是使用它在訓練中學習到的移動平均值和方差。為什麼?由於同樣的原因,在凍結層時不應該更新mini-batch的統計資料:它可能導致較差的結果,因為下一層沒有得到適當的訓練。
Vasilis還引用了這樣的例子,當Keras模型從訓練模式切換到測試模式時,這種差異導致模型效能顯著下降(從100%下降到50%)。
英文原文:https://medium.com/comet-ml/approach-pre-trained-deep-learning-models-with-caution-9f0ff739010c