在之前深度學習debug沉思錄第一集中,我們曾經討論過在深度學習實踐過程中可能遇到的一些bug或者問題,總共討論了20個問題。在本文中,我們將繼續討論與深度學習有關的bug和問題,其中很多是關于一些超參數的實踐中的調優問題。后期將持續更新。需要強調的是,本文的很多單純只是經驗,在盡可能列出參考文獻的同時卻并無嚴格理論驗證,希望大家見諒。
本文轉載自徐飛翔的“深度學習debug沉思錄第二集”。
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
文章目錄
- 1. 協變性和不變性
- 2. 在視覺任務中從頭開始訓練模型可能存在loss的“平坦期”
- 3. 若出現`training loss`一直不下降的情況,可以嘗試縮小網絡參數量
- 4. 進行模型遷移時,要根據任務進行特定層的保留和舍去
- 5. 在某些場景可能使用局部連接的卷積層更好
- 6. 一種特殊的過擬合現象
- 7. 通過矩陣分解對全連接層進行壓縮
- 8. 在使用CTC Loss時其loss會Nan
- 9. 在進行預訓練模型的測試時,容易出現標簽沒對齊的情況
- 10. 在進行不同的深度學習框架之間進行模型遷移時的調試
- 11. 在大批次訓練中,可以增加學習率
- Reference
1. 協變性和不變性
協變性(Covariance)和不變性(Invariance)是在深度學習任務中比較重要的兩個概念,用于指導根據不同任務來進行卷積網絡的設計。
其中,協變性[6]簡單來說,是網絡的輸入和輸出能夠在線形変換(比如translation操作,簡單的deformation也可以看成線性的)下,呈現相同比例的變化,用Wikipedia[6]上的解釋來說,就是:
For a covector
to be basis-independent, its components must co-vary with a change of basis to remain representing the same covector. That is, the components must be transformed by the same matrix as the change of basis matrix.(In English)對于某個covector是基底無關的,而且它的線性分解的系數
必須跟隨著基底的變化而變化,以保持同個covector表示的不變性,也就是,當基底用矩陣
進行變換時,系數
必須也用同樣的矩陣
進行變換。
而不變性則好理解得多,就是指不管網絡的輸入怎么變化,其輸出始終會保持在一個誤差范圍內(很難做到絕對的不變),數學表達為:
其中為一個變換。
那么,在一些應用場景,比如語義分割(semantic image segmentation)和動作估計(motion estimation),物體識別(object detection)中,則要求網絡模型具有協變性,因為其實體可能分布在圖像的任意角落中,并且圖像中通常有多個不同的實體,如果網絡模型要求協變性,那么通常不使用池化pooling等手段進行尺度下采樣。
反之,在一些應用中,比如物體分類(image classification)中,因為通常圖像上只包含一種目標實體,因此要求網絡模型具有不變性,此時就可以用池化pooling手段對圖像feature map進行下采樣了。[7]
我們知道,池化pooling[8]會選取某個固定大小區域中的具有代表性的值(最大值或者平均值等)作為這個區域的代表,那么,如果圖像的某個小塊在其中旋轉(rotation)或者平移(translation),因為這個下采樣的特性,將會使得特征具有平移和旋轉不變性,然而,正如上面所述的,在某些場景中,這個不變性是不期望得到的,可能會有負效果。
2. 在視覺任務中從頭開始訓練模型可能存在loss的“平坦期”
筆者以前多在skeleton數據[9]上跑動作識別模型,而skeleton數據有個特點就是足夠的緊致(compact),而傳統的RGB視頻數據則有著很多和動作信息(pose-related)無關的信息,比如背景信息,光照等,因此使用skeleton信息作為動作識別的輸入媒體,能在剛開始訓練模型時就得到快速的loss下降。
而一些視覺模型使用的是RGB信息,比如ImageNet, UCF101等,如果從頭訓練這些模型(from scratch),因為沒有任何預訓練模型提供足夠好的淺層特征,在訓練過程中就需要模型去“關注表演動作的實體”并且去學習圖像的淺層特征,如紋理,邊緣等,因此訓練過程中可能出現:loss在剛開始的幾個epoch不會下降,即便是訓練率已經很低了,在某個epoch后才開始正常下降。
因此,即便是你的模型在前幾個epoch不收斂,也可以繼續跑下去觀察是否是這個問題造成的。可以嘗試在前面使用預訓練的模型進行淺層特征提取,將有利于整個模型的收斂。
3. 若出現training loss一直不下降的情況,可以嘗試縮小網絡參數量
在第二節中筆者曾經談到過關于training from scratch時的開始的“平坦期”的情況,現在還有一種情況是:整個網絡在訓練過程中,訓練損失總是不下降,或者下降得很慢,也就是說網絡模型甚至沒有辦法過擬合。而這個相同的網絡在其他更大型的數據集上卻能正常工作 這個問題很可能是因為你的網絡模型參數量太大了,特別是在全連接層中參數量太大了,而訓練集樣本不足以支撐整個網絡。
這個解釋有點奇怪而且違反了常理,因為即便是網絡參數量太大也應該只會導致過擬合而不至于沒法擬合才對。但是筆者在實驗過程中卻發現了這個情況。后面筆者將最后一層的卷積層(shape (N, c=512, h=128,w=171))用1x1卷積將通道數弄成1之后,才大大減少了后續的全連接層的參數量,解決了這個問題。這個情況歡迎各位討論,給予意見。
PS: 這個情況在筆者跑C3D模型[10]驗證RGB video數據時出現的,數據集是筆者實驗室自己采集的,規模較小。
4. 進行模型遷移時,要根據任務進行特定層的保留和舍去
在進行視覺相關的任務,如image/video caption, video/image action recognition, object detection時,常常會用預先在大型數據集ImageNet上進行過預訓練的卷積模型,如resnet,vgg等作為遷移特征提取器,以在新任務中提取出有效地低級特征,如條紋,邊緣等,加快訓練的收斂。有些模型因為訓練難度,甚至一定需要用預訓練好的模型進行特征提取后,進行分步驟地訓練,才能得到正常的收斂,如LRCN[11]。
然而,在這些預訓練模型中,經常也是和特定任務有關的,比如說分類任務,就肯定會在最后存在若干全連接層。一般來說,越靠近最后的層,其和特定任務的關聯就最大,因此在遷移模型的時候,只會使用卷積層過后的最前面的全連接層作為特征,然后進行后續其他任務的遷移等。
如上圖所示,一般來說只會用fc_1的特征進行模型的遷移使用。
5. 在某些場景可能使用局部連接的卷積層更好
卷積網絡是在圖像處理領域率先使用的,在卷積網絡中,一個很重要的假設就是圖片的局部統計特征具有一致性,換句話說就是,一張圖片上,某個小區域的統計特性應該和同一張圖片的其他區域的是相似的,在這種情況下,就可以采用參數共享(weights sharing)的手段以大幅度減少需學習的參數的數量,并且有利于泛化。[12]
但是,在某些場景中,比如人臉識別中,因為人臉的局部特征不能很好地符合這個假設,因此在一些工作中,會嘗試使用不帶有參數共享的卷積網絡進行處理[15],比如DeepFace[13,14],其結構就如:
- Conv:32個11×11×3的卷積核
- max-pooling: 3×3, stride=2
- Conv: 16個9×9的卷積核
- Local-Conv: 16個9×9的卷積核,Local的意思是卷積核的參數不共享
- Local-Conv: 16個7×7的卷積核,參數不共享
- Local-Conv: 16個5×5的卷積核,參數不共享
- Fully-connected: 4096維
- Softmax: 4030維
因此,在某些特定的圖像領域,如果覺得你的待處理對象不符合這個假設都可以嘗試這個手段。其也有成熟的API接口,比如:
- TensorFlow: tf.keras.layers.LocallyConnected2D。 (Keras中同樣也有)
- PyTorch: 可以通過torch.nn.fold和torch.nn.unfold間接實現,目前還沒有直接的API,不過下一版本應該會出來。[16,17,18]
6. 一種特殊的過擬合現象
筆者在近日的實驗中,發現了一種比較特殊的過擬合現象,實驗場景大致是:
對特征
進行注意力機制的操作,公式如:
, 其中加上1的目的是做所謂的加強特征的處理。這里的
中的元素都在[0,1]之間。
在實驗過程中發現,輸出的分類的logit中,經常有一個值會比其他值有數量級上的差距,比如20.03和0.03, 0.20等,這樣導致很容易在交叉熵的計算過程中導致出現接近0的現象(當logit預測位和label相同時),同時,此時的loss很容易上下震蕩,并且很容易出現0.0000的現象(交叉熵不可能等于0,此處只是因為太接近0了)。此時應該也是出現了過擬合的現象,形成原因暫且不明。
7. 通過矩陣分解對全連接層進行壓縮
全連接層在深度學習中也有著廣泛的應用,數學表示為:
其中,當其中的n , m都比較大時,無論是對于計算還是內存都是一個大考驗,因此可以用基于矩陣奇異值分解的思想,進行分解。我們將奇異值縮減到只保留最大的t tt個,稱之為truncated SVD,我們有:
其中,
,
,通過這種手段可以將參數量從之前的
縮減到
,當然,要求這里的
那么在實踐中,我們把一層的全連接層更換成兩層全連接層疊加,兩層之間不添加非線性激活單元,第一層的參數矩陣為
(同時,這個層沒有添加偏置),第二層的參數矩陣為
,這層的偏置就是原先的
中的偏置。
因此,在學習到了之后,可以通過這種方法,將一層換成兩層全連接進行近似,取得更高的計算效率和儲存效率。
8. 在使用CTC Loss時其loss會Nan
CTC Loss(Connectionist Temporal Classification Loss)[19]是在序列到序列(Seq2Seq)模型中常見的loss,使用此類loss的好處就是可以避免對序列進行顯式地對齊(alignment),比如在語音翻譯成文本的過程中,顯式地對語音進行每個音節的標注是需要大量人力物力的,而使用CTC Loss可以避免這種標注。
在使用這種loss的時候,很基本的,需要注意你預測出來的類別是,其中的加1表示的是加上blank字符也就是下圖中的
。如果預測出來的類別沒有加1,則可能會導致loss變成Nan,梯度爆炸等。最一般的的就是在特征提取網絡之后的LSTM之后需要輸出若干個類的概率分布時,將這個類設置成
。[20]
9. 在進行預訓練模型的測試時,容易出現標簽沒對齊的情況
筆者最近犯了一個很傻丫丫的錯誤。筆者最近需要評估一個動作識別模型的性能,其在github上有預訓練好的模型,因此筆者直接下載完數據集Kinetics 400之后就直接考慮去評估模型性能了。因為數據集中的每個文件夾中都包含著同一類的樣本,一共有著400個類別,因此有400個文件夾。筆者一開始并不知道每個文件名,也就是類別名字與其label數字標簽的對應關系,竟然傻傻地對其進行os.listdir()之后按順序進行排序,順序給了一個數字標簽,這個顯然是不對的,因為模型是加載預訓練模型的,其輸出的標簽的規則和我自己定義的不一定相同,如果是自己從頭訓練還好不會受到影響,如果是打算在預訓練模型上進行,筆者的這個操作就放了大錯誤了。后果當然就是模型的評估結果很差,讓筆者花了不少時間調bug啊。讀者一定要注意這種低級錯誤,如果評估一個現有的預訓練模型,一定要注意這個預訓練模型對標簽是怎么定義的。不要一上手就急著進行評估和編碼,欲速則不達。
10. 在進行不同的深度學習框架之間進行模型遷移時的調試
不同深度學習框架(比如pytorch,tensorflow,caffe2等等)之間的底層運算細則,底層運算精度可能相差很多,并且其某些層的默認參數(比如BN層中有eps參數)可能每個框架都不同,因此為了更好地在不同的深度學習框架中進行模型遷移,及時地盤查出出錯的遷移層,我們可以用相同的輸入(比如全1矩陣),在兩個不同的框架中的相同模型中進行前向傳播,當然,兩個不同的框架的模型需要載入相同的模型參數,然后觀測到底在哪層開始中間的輸出張量的具體值(比如對張量進行取均值layer_out.mean())開始變得不同,據此去進行高效地調試。
11. 在大批次訓練中,可以增加學習率
文獻[21]指出,訓練過程中,在batch size越大的情況下,可以加大學習率。這個想法其實相當直觀,從理論上說,深度學習模型在學習過程中是從隨機樣本中采樣得到的,采樣的一個批次我們稱之為batch,增大批次的數量大小,并不會影響到隨機梯度下降的均值,但會減少其方差。換句話說,批次越大,在梯度下降過程中其噪聲就越小,梯度的方向可信度就越高,因此可以用更大的學習率進行學習。文獻[22]指出在resnet-50的訓練過程中,學習率可以隨著batch size線性增大或減小。如果將batch size = 256時的學習率初始化為0.1,讓實際的batch size表示為b bb,那么有初始化學習率為。
Reference
[1]. 深度學習debug沉思錄
[2]. Ioffe S, Szegedy C. Batch normalization: accelerating deep network training by reducing internal covariate shift[C]// International Conference on International Conference on Machine Learning. JMLR.org, 2015:448-456.[3]. Pytorch的BatchNorm層使用中容易出現的問題
[4].https://github.com/tensorflow/tensorflow/blob/r1.12/tensorflow/python/ops/nn_impl.py
[5]. https://www.tensorflow.org/api_docs/python/tf/nn/batch_normalization
[6]. https://en.wikipedia.org/wiki/Covariance_and_contravariance_of_vectors
[7]. Bronstein M M, Bruna J, LeCun Y, et al. Geometric deep learning: going beyond euclidean data[J]. IEEE Signal Processing Magazine, 2017, 34(4): 18-42.[8]. https://www.cnblogs.com/makefile/p/pooling.html
[9]. 【動作識別相關,第一篇】skeleton骨骼點數據類型介紹
[10]. Tran, Du, et al. “Learning spatiotemporal features with 3d convolutional networks.”Proceedings of the IEEE international conference on computer vision. 2015.
[11]. Donahue J, Anne Hendricks L, Guadarrama S, et al. Long-term recurrent convolutional networks for visual recognition and description[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2015: 2625-2634.
[12].https://www.quora.com/What-exactly-is-meant-by-shared-weights-in-convolutional-neural-network
[13]. Taigman Y, Yang M, Ranzato M A, et al. Deepface: Closing the gap to human-level performance in face verification[C]//Computer Vision and Pattern Recognition (CVPR), 2014 IEEE Conference on. IEEE, 2014: 1701-1708.
[14].https://blog.csdn.net/app_12062011/article/details/78510531
[15].https://prateekvjoshi.com/2016/04/12/understanding-locally-connected-layers-in-convolutional-neural-networks/
[16].https://github.com/pytorch/pytorch/pull/1583
[17].https://github.com/pytorch/pytorch/issues/499
[18].https://discuss.pytorch.org/t/locally-connected-layers/26979
[19].https://towardsdatascience.com/intuitively-understanding-connectionist-temporal-classification-3797e43a86c
[20].https://stackoverflow.com/questions/39565451/how-to-avoid-nan-value-in-ctc-training/43380602
[21]. He, T., Zhang, Z., Zhang, H., Zhang, Z., Xie, J., & Li, M. (2019). Bag of tricks for image classification with convolutional neural networks. In Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (pp. 558-567).
[22]. P. Goyal, P. Dollar, R. B. Girshick, P. Noordhuis, ´L. Wesolowski, A. Kyrola, A. Tulloch, Y. Jia, and K. He.Accurate, large minibatch SGD: training imagenet in 1 hour.CoRR, abs/1706.02677, 2017
未完待續!!!