日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

VGGNet详述

發布時間:2024/4/11 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VGGNet详述 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介

縱觀如今DeepLearning的研究領域,主要的研究領域還是CV和NLP及其衍生領域。CV的常見神經網絡中,VGGNet在卷積神經網絡的發展過程有著舉足輕重的作用,它作為著LeNet與Resnet的承接者,直到今天類VGG結構仍在圖像領域發揮著巨大的作用。由于最近的課題設計到VGGNet和Resnet的研究,在本項目著重實現每一個版本的VGGNet兼以近年的優化方式優化VGGNet。

  • 論文標題

    Very deep convolutional networks for large-scale image recognition

  • 論文地址

    https://arxiv.org/abs/1409.1556

  • 論文源碼

    https://github.com/pytorch/vision/blob/master/torchvision/models/vgg.py(PyTorch實現)

網絡說明

設計背景

VGGNet的基本模型主要由牛津大學的幾何視覺組(Visual Geometry Group)于2014年提出,這也是網絡名稱的由來,其獲得了2014年ILSVRC競賽的分類任務的第二名和定位任務的第一名,其最偉大之處在于證明使用3*3的小卷積核通過多層堆疊可以有效提高模型性能及泛化能力,這也是后面較長時間CNN傾向于小卷積核的原因之一。

結構說明

如圖所示,共有6種網絡配置,其實按照層數來說只有11層、13層、16層、19層四種,主要區別在于11層網絡嘗試了使用Local Response Normalisation(LRN),結果并沒有提高網絡性能,另一個區別就是16層(這就是著名的VGG16)結構在最后三個block使用不同的卷積核大小。網絡上可以找到很多概念結構圖,上面列舉了一個很經典的。

主要貢獻

使用3*3的小卷積核堆疊。

為什么使用3*3的小卷積核?這主要基于兩個考慮,不過解釋之前必須明確一個概念,兩個3*3卷積核可以獲得一個5*5的卷積核視野,三個3*3的卷積核堆疊可以獲得7*7的感受野。(注意,之間不能有池化層)

  • 第一,三次卷積會進行三次非線性變換。這種非線性變換會有效提高不同信息的判別能力(即對差異的識別能力)。
  • 第二,利用三個3*3代替一個7*7可以減少參數數量。(過多的參數是神經網絡的通有的問題)假設對于3通道,三個3*3卷積核的參數量為3×(32C2)=27C23\times (3^2C^2)=27C^23×(32C2)=27C2,而一個7*7卷積核參數量為72C2=49C27^2C^2=49C^272C2=49C2。

真正提高了網絡的深度。

  • 更深的模型的好處就是可以進行更多的非線性映射次數,從而提高網絡的信息判別能力。這樣做的前提是參數量不會增加太多,這是基于小卷積核做到的。
  • 使用1*1小卷積核也是為了增加非線性變換次數。

代碼實現

由于代碼過多,只列舉VGG16和VGG19的實現代碼,其余見文末Github。

def VGG16D(input_shape=(224, 224, 3), n_classes=1000):"""實現VGG16D的網絡結構(著名的VGG16)沒有使用Dropout和BN:param input_shape::param n_classes::return:"""# input layerinput_layer = Input(shape=input_shape)# block1x = Conv2D(filters=64, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')(input_layer)x = Conv2D(64, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)# block2x = Conv2D(128, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(128, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)# block3x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)# block4x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)x = BatchNormalization()(x)# block5x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)x = BatchNormalization()(x)# fcx = Flatten()(x)x = Dense(4096, activation='relu')(x)x = Dropout(rate=0.5)(x)x = Dense(4096, activation='relu')(x)x = Dropout(rate=0.5)(x)output_layer = Dense(n_classes, activation='softmax')(x)model = Model(inputs=input_layer, outputs=output_layer)return modeldef VGG19(input_shape=(224, 224, 3), n_classes=1000):"""實現VGG16C的網絡結構(著名的VGG16)沒有使用Dropout和BN:param input_shape::param n_classes::return:"""# input layerinput_layer = Input(shape=input_shape)# block1x = Conv2D(filters=64, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')(input_layer)x = Conv2D(64, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)# block2x = Conv2D(128, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(128, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)# block3x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)# block4x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)x = BatchNormalization()(x)# block5x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = Conv2D(512, (3, 3), strides=1, padding='same', activation='relu')(x)x = MaxPooling2D(2, 2, padding='same')(x)x = BatchNormalization()(x)# fcx = Flatten()(x)x = Dense(4096, activation='relu')(x)x = Dropout(rate=0.5)(x)x = Dense(4096, activation='relu')(x)x = Dropout(rate=0.5)(x)output_layer = Dense(n_classes, activation='softmax')(x)model = Model(inputs=input_layer, outputs=output_layer)return model

為了編寫效率,均使用Function API。(事實上Keras的構建精髓正是Function API)

模型的訓練及測試均在Caltech101數據集上進行(該數據集由李飛飛整理,含一個干擾項)。為了比較模型性能,不進行數據增廣,采用同樣的優化函數Adam。模型訓練選取適中batch_size,為128,使用了BN和Dropout等訓練技巧(這不影響核心網絡結構)。后面的深層模型如VGG16和VGG19不使用Dropout或者BN難以訓練,每個block輸出時使用BN層。

訓練結果

損失圖像

從上圖可以看出,隨著模型深度加深,訓練集上損失收斂速度變慢,驗證集上損失收斂波動大。

準確率圖像

從上圖可以看出,隨著模型深度加深,訓練集上準確率上升變慢,在同樣的epoch下,到達的最終驗證集準確率變低。

整體看來,隨著模型加深,需要更多的訓練控制如Dropout和BN這樣的中間層來提高訓練效果。

關鍵提示

當使用VGGNet時一般使用的并非上述任何一種網絡模型,每個block的卷積層數目、是否使用Dropout、是否使用BN等完全依據當前任務修改即可。VGG最偉大之處絕對不是這個VGG模型而是小卷積核多層疊加的思想,這也是后來的卷積網絡的大部分采用的思路。

補充說明

本項目實現基于Keras2(TensorFlow后端)以及Python3。具體代碼已經開源于我的Github,歡迎star或者fork。訓練過程在ipynb文件內可見。如有疏漏,歡迎評論指出。

總結

以上是生活随笔為你收集整理的VGGNet详述的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。