训练神经网络的技巧总结
訓練神經網絡是一個復雜的過程。 有許多變量相互配合,通常不清楚什么是有效的。
以下技巧旨在讓您更輕松。 這不是必須做的清單,但應該被視為一種參考。 您了解手頭的任務,因此可以從以下技術中進行最佳選擇。 它們涵蓋了廣泛的領域:從數據增強到選擇超參數; 涉及到很多話題。 使用此選擇作為未來研究的起點。
過擬合單個批次
使用此技術來測試您的網絡容量。 首先,取一個數據批次,并確保它被正確標記(如果使用了標簽)。 然后,重復擬合這單個批次,直到損失收斂。 如果您沒有達到完美的準確度(或類似的指標),您應該查看您的數據。 這種情況下使用更大的網絡通常不是解決方案。
將 epoch 數量增加一個顯著因素
通常,您可以從運行大量步驟的算法中受益。 如果您可以土工更長的訓練時間,請將 epoch 數從例如 100 擴展到 500。如果您觀察到更長訓練時間的是有好處,可以在開始時就選擇更合理的值。
隨機種子
為確保可重復性,請設置任何隨機數生成操作的種子。 例如,如果您使用 TensorFlow,則可以使用以下代碼段:
import os, random import numpy as np import tensorflow as tfdef set_seeds(seed: int):os.environ['PYTHONHASHSEED'] = str(seed)random.seed(seed)tf.random.set_seed(seed)np.random.seed(seed)重新平衡數據集
一個不平衡的數據集有一個或多個主要類別,它們構成了數據集的很大一部分。相反,一個或多個小類僅貢獻少量樣本。如果您正在處理具有相似特征的數據,請考慮重新平衡您的數據集。推薦的技術是對少數類進行過采樣、對主要類進行下采樣、收集額外的樣本(如果可能)以及生成具有增強功能的人工數據。
使用中性類
考慮以下情況:您有一個包含“Ill”和“not Ill”兩個類別的數據集。樣本由領域專家手工標記。如果他們中的一個不確定合適的標簽,他可能沒有或幾乎沒有信心分配。在這種情況下,引入第三個中性類是個好主意。這個額外的類代表“我不確定”標簽。在訓練期間,您可以排除此數據。之后,您可以讓網絡預先標記這些模糊的樣本,并將它們展示給領域專家。
設置輸出層的偏置
對于不平衡的數據集,網絡的初始猜測不可避免地不足。即使網絡學會了考慮這一點,在模型創建時設置更好的偏差可以減少訓練時間。對于 sigmoid 層,偏差可以計算為(對于兩個類):
bias = log(pos/negative)
創建模型時,將此值設置為初始偏差。
物理模擬過擬合
為了模擬流體的運動,人們經常使用特殊的軟件。在復雜的相互作用中(例如,水流過不平坦的地面),可能需要很長時間才能看到結果。神經網絡在這里可以提供幫助。由于模擬遵循物理定律,任何神奇的事情發生的可能性為零——只需要努力計算結果。網絡可以學習這種物理模擬。因為定律是明確定義的,我們“只”要求網絡過擬合。我們不希望有任何看不見的測試樣本,因為它們必須遵循相同的規則。在這種情況下,過擬合訓練數據是有幫助的;通常,甚至不需要測試數據。一旦網絡經過訓練,我們就用它來代替慢速模擬器。
調整學習率
如果您要尋找任何要調整的超參數,那么主要關注學習率。 下圖顯示了學習率設置過高的影響:
相比之下,使用不同的、較小的學習率,發展如預期:
使用快速數據管道
對于小型項目,我經常使用自定義生成器。當我處理較大的項目時,我通常用專用的數據集機制替換它們。對于 TensorFlow,這是 tf.data API。它包括所有必需的方法,如改組、批處理和預取。依靠許多專家編寫的代碼,而不是自定義解決方案,讓我有時間來完成實際任務。
使用數據增強
擴充您的訓練數據以創建強大的網絡、增加數據集大小或對次要類別進行過采樣。這些好處是以增加訓練時間為代價的,特別是如果增強是在 CPU 上完成的。如果您可以將其移動到 GPU,您將更快地看到結果。
使用 AutoEncoders 提取嵌入
如果您的標記數據集相對較小,您仍然可以使用一些技巧。其中之一是訓練 AutoEncoder。背景是額外收集未標記的數據比標記它們更容易。然后,您可以使用具有足夠大的潛在空間(例如,300 到 600 個條目)的 AutoEncoder 來實現相當低的重建損失。要獲得實際數據的嵌入,您可以丟棄解碼器網絡。然后,您可以使用剩余的編碼器網絡來生成嵌入。是將此解碼器添加到主網絡還是僅用于提取嵌入由您決定。
使用來自其他模型的嵌入
您可以使用其他模型學習的嵌入,而不是從頭開始為您的數據學習嵌入。這種方法與上面提出的技術有關。對于文本數據,下載預訓練的嵌入是很常見的。對于圖像,您可以使用在 ImageNet 上訓練的大型網絡。選擇一個足夠的層,然后剪切所有內容,并將輸出用作嵌入。
使用嵌入來縮小數據
假設我們的數據點都具有分類特征。一開始,它可以取兩個可能的值,所以一個單熱編碼有兩個索引。但是一旦這增長到 1000 個或更多可能的值,稀疏的 one-hot 編碼就不再有效。因為它們可以在低維空間中表示這些數據,所以嵌入在這里很有用。嵌入層采用分類值(在我們的例子中從 0 到 1000)并輸出一個浮點向量,即嵌入。這種表示是在訓練期間學習的,并作為連續網絡層的輸入。
使用檢查點
沒有什么比運行昂貴的訓練算法無數個小時然后看到它崩潰更令人沮喪的了。有時,這可能是硬件故障,但通常是代碼問題——您只能在訓練結束時看到。雖然您永遠不能期望只有完美的運行,但您仍然可以通過保存檢查點來做好準備。在它們的基本形式中,這些檢查點每 k 步存儲模型的權重。您還可以擴展它們以保持優化器狀態、當前時期和任何其他關鍵信息。然后,在重新訓練時,檢查點保證可以從失敗時恢復所有必要的設置。這與自定義訓練循環結合使用效果非常好。
編寫自定義訓練循環
在大多數情況下,使用默認的訓練例程,例如 TensorFlow 中的 model.fit(…),就足夠了。但是,我經常注意到的是靈活性有限。一些小的更改可能很容易合并,但重大的修改很難實施。這就是為什么我通常建議編寫自定義算法。起初,這聽起來可能令人生畏,但可以使用大量教程來幫助您入門。最初幾次遵循此方法時,您可能會暫時放慢速度。但是一旦你有了經驗,你就會獲得更大的靈活性和理解力。此外,這些知識使您可以快速修改算法,整合您的最新想法。
適當設置超參數
現代 GPU 擅長矩陣運算,這就是它們被廣泛用于訓練大型網絡的原因。通過適當地選擇超參數,您可以進一步提高算法的效率。對于 Nvidia GPU(這是當今使用的主要加速器),您可以從使用以下方法開始:
- 選擇可被 4 或 2 的更大倍數整除的批次大小
- 對于密集層,將輸入(來自前一層)和輸出設置為可被 64 或更多整除
- 對于卷積層,將輸入和輸出通道設置為可被 4 或更大的 2 的倍數整除
- 從 3 (RGB) 到 4 通道填充圖像輸入
- 使用批量大小 x 高度 x 寬度 x 通道
- 對于遞歸層,將批次和隱藏大小設置為至少可被 4 整除,理想情況下可被 64、128 或 256 中的任何一個整除
- 對于遞歸層,使用大批次
這些建議遵循使數據分布更均勻的想法。主要是通過將值選擇為 2 的倍數來實現這一點。您設置的這個數字越大,您的硬件運行效率就越高。
使用早停機制
“我什么時候停止訓練”這個問題很難回答。可能發生的一種現象是深度雙重下降:您的指標在穩步改善后開始惡化。然后,經過一些更新,分數再次提高,甚至比以前更查。為了解決這個問題,您可以使用驗證數據集。這個單獨的數據集用于衡量您的算法在新的、看不見的數據上的性能。如果性能在一定次數后沒有提高,訓練將自動停止。對于這個參數。一個好的起始值是 5 到 20 個 epoch。
使用遷移學習
遷移學習背后的想法是利用從業者在大量數據集上訓練的模型并將其應用于您的問題。理想情況下,您使用的網絡已經針對相同的數據類型(圖像、文本、音頻)和與您的任務(分類、翻譯、檢測)類似的任務進行了訓練。有兩種相關的方法:
微調
微調是采用已經訓練好的模型并更新特定問題的權重的任務。通常,您會凍結前幾層,因為它們經過訓練可以識別基本特征。然后在您的數據集上對其余層進行微調。
特征提取
與微調相反,特征提取描述了一種使用經過訓練的網絡來提取特征的方法。在預先訓練好的模型之上,添加自己的分類器,只更新這部分網絡;基層被凍結。您遵循此方法是因為原始 top 是針對特定問題進行訓練的,但您的任務可能會有所不同。通過從頭開始學習自定義頂部,您可以確保專注于您的數據集——同時保持大型基礎模型的優勢。
使用數據并行的多 GPU 訓練
如果您可以使用多個加速器,則可以通過在多個 GPU 上運行算法來加快訓練速度。通常,這是以數據并行的方式完成的:網絡在不同的設備上復制,批次被拆分和分發。然后將梯度平均并應用于每個網絡副本。在 TensorFlow 中,您有多種關于分布式訓練的選擇。最簡單的選擇是使用 MirroredStrategy,但還有更多策略。我注意到從 1 到 2 和從 2 到 3 個 GPU 時的加速效果比較明顯。對于大型數據集,這是最小化訓練時間的快速方法。
使用 sigmoid 進行多標簽設置
在樣本可以有多個標簽的情況下,您可以使用 sigmoid 激活函數。與 softmax 函數不同,sigmoid 單獨應用于每個神經元,這意味著多個神經元可以觸發。輸出值介于 0 和 1 之間,便于解釋。此屬性很有用,例如,將樣本分類為多個類或檢測各種對象。
對分類數據使用 one-hot 編碼
由于我們需要數字表示,因此分類數據必須編碼為數字。例如,我們不能直接輸入字符串格式的數據,而必須使用替代表示。一個誘人的選擇是枚舉所有可能的值。然而,這種方法意味著在編碼為 1 的“bank”和編碼為 2 的“tree”之間進行排序。這種排序很少出現,這就是我們依賴單熱向量來編碼數據的原因。這種方法確保變量是獨立的。
對索引使用 one-hot 編碼
假設您正在嘗試預測天氣并索引日期:1 表示星期一,2 表示星期二,等等。但是,因為它只是一個任意索引,我們可以更好地使用 one-hot 編碼。與上一個技巧類似,這種表示在索引之間沒有建立關系。
(重新)縮放數值
網絡通過更新權重進行訓練,優化器負責這一點。通常,如果值介于 [-1, 1] 之間,它們會被調整為最佳。這是為什么?讓我們考慮一個丘陵景觀,我們尋找最低點。該地區越是丘陵,我們花在尋找全球最小值上的時間就越多。但是,如果我們可以修改景觀的形狀呢?那么我們可以更快地找到解決方案嗎?
這就是我們通過重新調整數值所做的。當我們將值縮放到 [-1, 1] 時,我們使曲率更球形(更圓、更均勻)。如果我們用這個范圍的數據訓練我們的模型,我們會更快地收斂。
這是為什么?特征的大小(即值)影響梯度的大小。較大的特征會產生較大的梯度,從而導致較大的權重更新。這些更新需要更多的步驟來收斂,這會減慢訓練速度。
使用知識蒸餾
你肯定聽說過 BERT 模型,不是嗎?這個 Transformer 有幾億個參數,但我們可能無法在我們的 GPU 上訓練它。這就是提煉知識的過程變得有用的地方。我們訓練第二個模型以產生更大模型的輸出。輸入仍然是原始數據集,但標簽是參考模型的輸出,稱為軟輸出。這種技術的目標是在小模型的幫助下復制更大的模型。
問題是:為什么不直接訓練小模型呢?首先,訓練較小的模型,尤其是在 NLP 領域,比訓練較大的模型更復雜。其次,大型模型對于我們的問題可能是過度的:它足夠強大,可以學習我們需要的東西,但它可以學到更多。另一方面,較小的模型難以訓練,但足以存儲所需的知識。因此,我們將廣泛的參考模型的知識提煉到我們的小型輔助模型中。然后我們受益于降低的復雜性,同時仍然接近原始質量。
本文作者:Pascal Janetzky
deephub翻譯組
總結
以上是生活随笔為你收集整理的训练神经网络的技巧总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 主定理 - 算法导论摘录
- 下一篇: Java开发之计算机概述01