特征层次分析、视觉特征语义探索(微调+预训练)
1. 關于卷積運算、密集連接層、池化與小樣本
密集連接層與卷積層的根本區別在于,密集連接層從輸入特征中學到的是全局模式,在計算機視覺領域對應著的是高級語義特征(全局模式就是涉及所有像素的模式,如 狗,耳朵,向日葵等)。卷積層學到的是局部模式,學到的就是輸入圖像二維圖像小窗口中發現的模式,對應低級語義特征(局部模式就是卷積覆蓋的區域,3*3,5*5...,如邊緣、紋理等)。
正是因為這樣的特性,使得卷積神經網絡具有兩個有趣的特性:
- 卷積神經網絡學到的模式具有平移不變性。卷積神經網絡在圖像某個區域學習到某個模式之后,可以在任何地方識別這個模式(其實質就是低級特征提取器,后續應用時相當于對每一個候選模式進行判別)。
- 卷積神經網絡可以學習到模式的空間層次結構。例如,第一個卷基層可以學到較小的圖像特征(如邊緣、紋理、色度);第二個卷積層講學習由第一特征層組成更大的模式(如貓的耳朵形狀、眼睛紋理等),以此類推。這就使得卷及神經網絡可以有效地學習越來越復雜、越來越抽象的視覺概念。(視覺世界從根本上也具有空間層次結構)
池化也是卷積網絡中常使用的一種技巧。與跨步卷積類似的是,池化也是下采樣的一種操作。但是相比之下,最大池化操作往往可以取得更好而效果,這主要在于最大池化保留了卷積濾波器的最大響應值(我們也可以理解為最有效益的特征值),更具體的效益如下:
- 減少了需要處理的特征圖的元素個數
- 通過讓連續卷積層的觀察窗口越來越大(即串口覆蓋原始輸入的比例越來越大)從而引入空間過濾器的層級結構
很多時候我們會聽說,只有在大量數據可以使用的情況下,深度學習才會有效。這種觀點只能說是部分正確:深度學習的一個基本特性就是能夠獨立地[更特別地我希望數據局限在某個domain中,以提高魯棒性]在訓練數據中找到有趣的特征,不需要人為的特征工程,而這只能在擁有大量訓練樣本的情況下才能實現。對于輸入樣本維度非常高的情況下更是這樣,比如說圖像。只能說他是部分正確,是因為還存在如下兩種更可能出現的情況:
- 模型本身就很小,正則化做的也很好,同時任務也是非常的簡單。這種情況下幾百個樣本就足夠了。
- 深度學習模型本質上具有高度可重復使用性。正如上面所分析的那樣,淺層卷積網絡提取的是諸如邊緣、紋理、色度等低級視覺特征;深層卷積網絡/全連接層提取的是諸如鼻子、桌子、打太極、奔跑的馬等高級的視覺特征。低級特征是可以重復使用的,所以我們可以在已經訓練好的大型卷積網絡中僅裁剪出淺層卷積網絡,再結合小樣本進行特征網絡的微調,同樣可以取得非常可觀的效果(與之相比較的是,利用小樣本和深層模型從參數初始化階段進行訓練)。
2. 使用預訓練卷積神經網絡實現小樣本任務
數據增強技術不是這里討論的核心,這里不進行重點討論。
預訓練網絡是一個已經在大型數據集上(如ImageNet等大規模圖像分類任務)訓練好的深度神經網絡結構,正如在上面1中討論的,如果提供訓練的數據集足夠大而且通用,那么預先訓練的網絡學到的空間層次特征提取結構可以有效的作為視覺世界的通用模型。即使視覺任務之間存在差異,但是預先訓練的網絡也給我們給拱了更好的初始化參數選擇。例如,在ImageNet訓練好的網絡Alexnet、ResNet等,其雖然原本出發點是對動物和生活中的物品進行分類,但是如果將其應用于不同類型的植物種類判別,這依然可以取得不錯的效果。這足以說明,深度卷積神經網絡學習到的特征確實的不同視覺問題之間具備可移植性。這也是深度學習與其他傳統的特征工程方法的優勢所在:深度學習在小樣本學習問題上更有效(高效的特征可移植性)。
2.1 對比試驗
數據集:kaggle2013貓狗分類任務,構造小樣本:1000張貓/狗圖像作為訓練集,500張貓/狗圖像作為驗證數據集,500張貓/狗圖像作為測試數據集。
- 方法一:淺層卷積神經網絡 - training from scratch
網絡結構:
實驗結果:
vvvvv
評價:
通過accuracy和loss評價,我們能夠看出模型已經出現了過擬合的特征。訓練精度隨著時間幾乎線性增加,直到接近100%,而驗證數據集的精度停留在65%-72%;驗證數據集僅僅在7輪迭代之后就達到了最小值,但是訓練集的損失卻一直在下降,最后趨近0.
訓練樣本少是很常見的,如果貿然采用深度學習并且training from scratch明顯是不合理的,因為過擬合問題很難避免。這時候就不得不考慮dropout、L2-norm(權重衰減)、數據增強、pre-trained、tuning等操作。
- 方法二:預訓練深層卷積神經網絡 - training from pretrained model [VGG16]
Note 1:雖然VGG16相比較VGG19、Xception、Inception V3、 ResNet50、ResNet101等是一個比較老古董的結構了,但是VGG16比較簡單,與方法一中訓練的網絡結構具有高度相似性,所以實驗結果更有說服力。
Note 2:用于圖像分類的卷積神經網絡包括低級視覺特征抽取[pooling+convolution]和高級語義特征綜合[fullyconnection]兩個部分。對于預訓練網絡處理小樣本問題,實際上就是直接應用pretained模型的低級視覺特征抽取部分,然后重新構造數據domain-self的高級語義特征。
ThinKing:為什么僅僅重復卷積操作,是否也可以重復使用密集連接層[全連接層]?
因為卷積操作學習到的表示是低級視覺特征抽取器,在處理視覺任務上更加通用;而全連接層是高級予以特征綜合,直接與任務掛鉤,類似于決策部分。此外,高級語義抽取器[全連接層]不在包含物體在輸入圖像中的位置信息,空間分別率很差。如果位置信息對于視覺任務是很重要的,如分割、檢測、跟蹤等,那么密集連接層的特征很大程度上是沒有用處的。
此外,即使對于卷積操作而言,其特征通用性也是存在差別的,這很大程度上取決于該卷積層在模型中的深度。 模型中更靠近底部的層提取出來是局部的、高度通用的特征圖,就像我們說的邊緣、文理、色度;而更靠近頂部的層提取出來的特征將會是更加抽象的概念。所以我更傾向于使用pretrained模型前3-4層的卷積參數。
Feature Extraction + Classification = NOT End-to-End [運行成本極低] 實驗結果:
我先采用VGG16的卷積網絡提取特征,然后將特征輸入到全連接層,很明顯這并不是End-to-End的過程。
def extract_features(directory, sample_count):features = np.zeros(shape=(sample_count, 4, 4, 512))labels = np.zeros(shape=(sample_count))generator = datagen.flow_from_directory(directory,target_size=(150, 150),batch_size=batch_size,class_mode='binary')i = 0for inputs_batch, labels_batch in generator:features_batch = conv_base.predict(inputs_batch)features[i * batch_size : (i + 1) * batch_size] = features_batchlabels[i * batch_size : (i + 1) * batch_size] = labels_batchi += 1if i * batch_size >= sample_count:breakreturn features, labelstrain_features, train_labels = extract_features(train_dir, 2000) validation_features, validation_labels = extract_features(validation_dir, 1000) test_features, test_labels = extract_features(test_dir, 1000)train_features = np.reshape(train_features, (2000, 4 * 4 * 512)) validation_features = np.reshape(validation_features, (1000, 4 * 4 * 512)) test_features = np.reshape(test_features, (1000, 4 * 4 * 512))model = models.Sequential() model.add(layers.Dense(256, activation='relu', input_dim=4 * 4 * 512)) model.add(layers.Dropout(0.5)) model.add(layers.Dense(1, activation='sigmoid'))model.compile(optimizer=optimizers.RMSprop(lr=2e-5),loss='binary_crossentropy',metrics=['acc'])history = model.fit(train_features, train_labels,epochs=100,batch_size=20,validation_data=(validation_features, validation_labels))實驗結果:
vvvv
雖然仍然存在過擬合現象,但是在驗證數據集上,精度得到了非常大的提升,大約為90%-92%.
Expanding vgg16-cnn with dense net = End-to-End [運行成本極高] 實驗結果:
網絡結構:
這里需要注意的是,在編譯和訓練模型之前,一定要‘凍結’VGG卷積網絡中的權重參數,也就是說保持他的權重值不變。因為我們添加的Dense層是隨機初始化的,如果不凍結VGG中的權重值,將會導致非常大的權重更新在網絡中進行傳播,這對于VGG中已經學習好的特征提取參數將會造成非常嚴重的破壞。
conv_base = VGG16(weights = 'imagenet',include_top = False,input_shape = (150,150,3)) model = models.Sequential() model.add(conv_base) model.add(layers.Flatten()) model.add(layers.Dense(256, activation='relu')) model.add(layers.Dense(1, activation='sigmoid'))conv_base.trainable = False實驗結果:
vvvv
End-to-End訓練之后,精度進一步得到了提升,大約94%-95%。
數據增強技術的引入,不僅僅解決了‘過擬合’現象,是使得驗證數據集的精度得到了進一步提升,最終約為96%-97.4%。
3. 微調模型實現小樣本數據的深度訓練
pretrained模型還有一種更為常用的方法-模型微調 fine-tuning。前面是對特征提取的卷積神經網絡進行完全的凍結,微調是指將與預先訓練的網絡模型的頂部幾層進行'解凍'[因為越是底層,視覺特征越基礎,特征越通用;越靠近頂部,特征越容易聚合成針對任務的更高級語義特征,所以更好的辦法是對頂層特征提取器參數進行微調,使其更適應特定的任務]。
上一節說過,凍結VGG16的卷積特征提取層,是為了能夠基于卷積特征,訓練一個分類器(也就是形成高級語義特征用于分類)。同理,只有上面的分類器訓練好了,才可能微調卷積特征提取網絡的頂部幾層。如果分類器沒有訓練好,那么訓練期間通過網絡傳播的誤差信號就會特別大,微調的幾層之前好不容易學習到的有效的表達能力,也會被破壞掉。
- 微調的步驟如下:
我們能夠發現,fine tuning其實是對pretraining的一種優化,使得網絡更加具備‘個性化’能力。
核心代碼+網絡結構:
conv_base = VGG16(weights = 'imagenet',include_top = False,input_shape = (150,150,3)) model = models.Sequential() model.add(conv_base) model.add(layers.Flatten()) model.add(layers.Dense(256, activation='relu')) model.add(layers.Dense(1, activation='sigmoid'))conv_base.trainable = True # 最頂層的卷積特征提取器的參數是可以和全連接層一起訓練的 # 底部四層卷積特征提取器依然被‘凍結’ set_trainable = False for layer in conv_base.layers:if layer.name == 'block5_conv1':set_trainable = Trueif set_trainable:layer.trainable = Trueelse:layer.trainable = False實驗結果:
vvvv
實驗結果更加的精確,精度提高到了~98%.
Note:我們應不應該調整更多的層?
4. 參考資料
1. Simonyan K, Zisserman A. Very Deep Convolutional Networks for Large-Scale Image Recognition[J]. international conference on learning representations, 2015.
2. python3-wih-deep-learning.
總結
以上是生活随笔為你收集整理的特征层次分析、视觉特征语义探索(微调+预训练)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows Sysinternals
- 下一篇: 林华达视角-概率图模型与计算机视觉