VGG卷积神经网络模型加载与运行
1,VGG概述
VGG Net由牛津大學(xué)的視覺幾何組(Visual Geometry Group)和 Google DeepMind公司的研究員一起研發(fā)的的深度卷積神經(jīng)網(wǎng)絡(luò),在 ILSVRC 2014 上取得了第二名的成績,將 Top-5錯(cuò)誤率降到7.3%。它主要的貢獻(xiàn)是展示出網(wǎng)絡(luò)的深度(depth)是算法優(yōu)良性能的關(guān)鍵部分。他們最好的網(wǎng)絡(luò)包含了16個(gè)卷積/全連接層。網(wǎng)絡(luò)的結(jié)構(gòu)非常一致,從頭到尾全部使用的是3x3的卷積和2x2的匯聚。VGGNet不好的一點(diǎn)是它耗費(fèi)更多計(jì)算資源,并且使用了更多的參數(shù),導(dǎo)致更多的內(nèi)存占用(140M)。其中絕大多數(shù)的參數(shù)都是來自于第一個(gè)全連接層。后來發(fā)現(xiàn)這些全連接層即使被去除,對(duì)于性能也沒有什么影響,這樣就顯著降低了參數(shù)數(shù)量。
目前使用比較多的網(wǎng)絡(luò)結(jié)構(gòu)主要有ResNet(152-1000層),GooleNet(22層),VGGNet(19層),大多數(shù)模型都是基于這幾個(gè)模型上改進(jìn),采用新的優(yōu)化算法,多模型融合等。到目前為止,VGG Net 依然經(jīng)常被用來提取圖像特征。
2,GVV19的結(jié)構(gòu)圖
輸入是大小為224224的RGB圖像,預(yù)處理(preprocession)時(shí)計(jì)算出三個(gè)通道的平均值,在每個(gè)像素上減去平均值(處理后迭代更少,更快收斂)。圖像經(jīng)過一系列卷積層處理,在卷積層中使用了非常小的33卷積核,在有些卷積層里則使用了11的卷積核。卷積層步長(stride)設(shè)置為1個(gè)像素,33卷積層的填充(padding)設(shè)置為1個(gè)像素。池化層采用max pooling,共有5層,在一部分卷積層后,max-pooling的窗口是2*2,步長設(shè)置為2。卷積層之后是三個(gè)全連接層(fully-connected layers,FC)。前兩個(gè)全連接層均有4096個(gè)通道,第三個(gè)全連接層有1000個(gè)通道,用來分類。所有網(wǎng)絡(luò)的全連接層配置相同。全連接層后是Softmax,用來分類。所有隱藏層(每個(gè)conv層中間)都使用ReLU作為激活函數(shù)。
VGGNet不使用局部響應(yīng)標(biāo)準(zhǔn)化(LRN),這種標(biāo)準(zhǔn)化并不能在ILSVRC數(shù)據(jù)集上提升性能,卻導(dǎo)致更多的內(nèi)存消耗和計(jì)算時(shí)間(LRN:Local Response Normalization,局部響應(yīng)歸一化,用于增強(qiáng)網(wǎng)絡(luò)的泛化能力)。
3,優(yōu)化討論
1、選擇采用33的卷積核是因?yàn)?3是最小的能夠捕捉像素8鄰域信息的的尺寸。
2、使用1*1的卷積核目的是在不影響輸入輸出的維度情況下,對(duì)輸入進(jìn)行形變,再通過ReLU進(jìn)行非線性處理,提高決策函數(shù)的非線性。
3、2個(gè)33卷積堆疊等于1個(gè)55卷積,3個(gè)33堆疊等于1個(gè)77卷積,感受野大小不變,而采用更多層、更小的卷積核可以引入更多非線性(更多的隱藏層,從而帶來更多非線性函數(shù)),提高決策函數(shù)判決力,并且?guī)砀賲?shù)。唯一的不足是,在進(jìn)行反向傳播時(shí),中間的卷積層可能會(huì)導(dǎo)致占用更多的內(nèi)存。
4、每個(gè)VGG網(wǎng)絡(luò)都有3個(gè)FC層,5個(gè)池化層,1個(gè)softmax層。
5、在FC層中間采用dropout層,防止過擬合,如下圖:
左邊的圖為一個(gè)完全的全連接層,右邊為應(yīng)用dropout后的全連接層。
我們知道,典型的神經(jīng)網(wǎng)絡(luò)其訓(xùn)練流程是將輸入通過網(wǎng)絡(luò)進(jìn)行正向傳導(dǎo),然后將誤差進(jìn)行反向傳播。dropout就是針對(duì)這一過程之中,隨機(jī)地刪除隱藏層的部分單元,進(jìn)行上述過程。步驟為:
(1)隨機(jī)刪除網(wǎng)絡(luò)中的一些隱藏神經(jīng)元,保持輸入輸出神經(jīng)元不變;
(2)將輸入通過修改后的網(wǎng)絡(luò)進(jìn)行前向傳播,然后將誤差通過修改后的網(wǎng)絡(luò)進(jìn)行反向傳播;
(3)對(duì)于另外一批的訓(xùn)練樣本,重復(fù)上述操作(1)。
Dropout可以有效防止過擬合,原因是:
(1)達(dá)到了一種vote的作用。對(duì)于單個(gè)神經(jīng)網(wǎng)絡(luò)而言,將其進(jìn)行分批,即使不同的訓(xùn)練集可能會(huì)產(chǎn)生不同程度的過擬合,但是我們?nèi)绻麑⑵涔靡粋€(gè)損失函數(shù),相當(dāng)于對(duì)其同時(shí)進(jìn)行了優(yōu)化,取了平均,因此可以較為有效地防止過擬合的發(fā)生。
(2)減少神經(jīng)元之間復(fù)雜的共適應(yīng)性。當(dāng)隱藏層神經(jīng)元被隨機(jī)刪除之后,使得全連接網(wǎng)絡(luò)具有了一定的稀疏化,從而有效地減輕了不同特征的協(xié)同效應(yīng)。也就是說,有些特征可能會(huì)依賴于固定關(guān)系的隱含節(jié)點(diǎn)的共同作用,而通過dropout的話,就有效地阻止了某些特征在其他特征存在下才有效果的情況,增加了神經(jīng)網(wǎng)絡(luò)的魯棒性。
6、如今用得最多的是VGG16(13層conv + 3層FC)和VGG19(16層conv + 3層FC),注意算層數(shù)時(shí)不算maxpool層和softmax層,只算conv層和fc層。
4,模型訓(xùn)練
訓(xùn)練采用多尺度訓(xùn)練(Multi-scale),將原始圖像縮放到不同尺寸 S,然后再隨機(jī)裁切224*224的圖片,并且對(duì)圖片進(jìn)行水平翻轉(zhuǎn)和隨機(jī)RGB色差調(diào)整,這樣能增加很多數(shù)據(jù)量,對(duì)于防止模型過擬合有很不錯(cuò)的效果。
初始對(duì)原始圖片進(jìn)行裁剪時(shí),原始圖片的最小邊不宜過小,這樣的話,裁剪到224*224的時(shí)候,就相當(dāng)于幾乎覆蓋了整個(gè)圖片,這樣對(duì)原始圖片進(jìn)行不同的隨機(jī)裁剪得到的圖片就基本上沒差別,就失去了增加數(shù)據(jù)集的意義,但同時(shí)也不宜過大,這樣的話,裁剪到的圖片只含有目標(biāo)的一小部分,也不是很好。
針對(duì)上述裁剪的問題,提出的兩種解決辦法:
(1) 固定最小邊的尺寸為256;
(2) 隨機(jī)從[256,512]的確定范圍內(nèi)進(jìn)行抽樣,這樣原始圖片尺寸不一,有利于訓(xùn)練,這個(gè)方法叫做尺度抖動(dòng)(scale jittering),有利于訓(xùn)練集增強(qiáng)。
5,模型測試
將全連接層等效替換為卷積層進(jìn)行測試,原因是:
卷積層和全連接層的唯一區(qū)別就是卷積層的神經(jīng)元和輸入是局部聯(lián)系的,并且同一個(gè)通道(channel)內(nèi)的不同神經(jīng)元共享權(quán)值(weight)。卷積層和全連接層的計(jì)算實(shí)際上相同,因此可以將全連接層轉(zhuǎn)換為卷積層,只要將卷積核大小設(shè)置為輸入空間大小即可:例如輸入為77512,第一層全連接層輸出4096;我們可以將其看作卷積核大小為77,步長為1,沒有填充,輸出為11*4096的卷積層。這樣的好處在于輸入圖像的大小不再受限制,因此可以高效地對(duì)圖像作滑動(dòng)窗式預(yù)測;而且全連接層的計(jì)算量比較大,等效卷積層的計(jì)算量減小了,這樣既達(dá)到了目的又十分高效。
6,存在的問題
(1)雖然 VGGNet 減少了卷積層參數(shù),但實(shí)際上其參數(shù)空間比 AlexNet 大,其中絕大多數(shù)的參數(shù)都是來自于第一個(gè)全連接層,耗費(fèi)更多計(jì)算資源。在隨后的 NIN 中發(fā)現(xiàn)將這些全連接層替換為全局平均池化,對(duì)于性能影響不大,同時(shí)顯著降低了參數(shù)數(shù)量。
(2)采用 Pre-trained 方法訓(xùn)練的 VGG model(主要是 D 和 E),相對(duì)其他的方法參數(shù)空間很大,所以訓(xùn)練一個(gè) VGG 模型通常要花費(fèi)更長的時(shí)間,所幸有公開的 Pre-trained model 讓我們很方便的使用。Imagenet VGG-19參數(shù)下載地址:http://www.vlfeat.org/matconvnet/models/beta16/imagenet-vgg-verydeep-19.mat
7,模型加載與運(yùn)行
加載Imagenet VGG-19完整代碼如下:
import scipy.io #讀寫.mat文件(可以加載和保存matlab文件)
import numpy as np
import os #os模塊提供了多數(shù)操作系統(tǒng)的功能接口函數(shù)。當(dāng)os模塊被導(dǎo)入后,它會(huì)自適應(yīng)于不同的操作系統(tǒng)平臺(tái),根據(jù)不同的平臺(tái)進(jìn)行相應(yīng)的操作,在python編程時(shí),經(jīng)常和文件、目錄打交道,所以離不了os模塊
import scipy.misc #是npy文件的圖片,都可以用指定的格式保存
import matplotlib.pyplot as plt
import tensorflow as tf #Functions for VGG
def _conv_layer(input, weights, bias):#卷積操作conv = tf.nn.conv2d(input, tf.constant(weights), strides=(1, 1, 1, 1),padding='SAME')return tf.nn.bias_add(conv, bias)
def _pool_layer(input):#池化操作return tf.nn.max_pool(input, ksize=(1, 2, 2, 1), strides=(1, 2, 2, 1),padding='SAME')
def preprocess(image, mean_pixel): #預(yù)處理(減均值)return image - mean_pixel
def unprocess(image, mean_pixel):#不進(jìn)行預(yù)處理return image + mean_pixel
def imread(path): #讀取模型return scipy.misc.imread(path).astype(np.float)
def imsave(path, img): #讀取圖像img = np.clip(img, 0, 255).astype(np.uint8)scipy.misc.imsave(path, img)# Network for VGG (完成前向傳播)
def net(data_path, input_image):layers = ('conv1_1', 'relu1_1', 'conv1_2', 'relu1_2', 'pool1','conv2_1', 'relu2_1', 'conv2_2', 'relu2_2', 'pool2','conv3_1', 'relu3_1', 'conv3_2', 'relu3_2', 'conv3_3','relu3_3', 'conv3_4', 'relu3_4', 'pool3','conv4_1', 'relu4_1', 'conv4_2', 'relu4_2', 'conv4_3','relu4_3', 'conv4_4', 'relu4_4', 'pool4','conv5_1', 'relu5_1', 'conv5_2', 'relu5_2', 'conv5_3','relu5_3', 'conv5_4', 'relu5_4')#定義各卷積層的參數(shù)(16層conv)data = scipy.io.loadmat(data_path)#加載.mat文件(模型參數(shù))mean = data['normalization'][0][0][0]#保存三個(gè)通道的均值mean_pixel = np.mean(mean, axis=(0, 1))weights = data['layers'][0]net = {}#定義字典結(jié)構(gòu)(保存前向傳播的結(jié)果)current = input_image#當(dāng)前的輸入for i, name in enumerate(layers):kind = name[:4]#取名字的前4個(gè)字母if kind == 'conv':kernels, bias = weights[i][0][0][0][0] #w,b的一個(gè)元組# matconvnet: weights are [width, height, in_channels, out_channels]# tensorflow: weights are [height, width, in_channels, out_channels]kernels = np.transpose(kernels, (1, 0, 2, 3))#轉(zhuǎn)換成tensorflow模式bias = bias.reshape(-1)current = _conv_layer(current, kernels, bias)elif kind == 'relu':current = tf.nn.relu(current)elif kind == 'pool':current = _pool_layer(current)net[name] = currentassert len(net) == len(layers)return net, mean_pixel, layerscwd = os.getcwd()#得到當(dāng)前路徑
VGG_PATH = cwd + "/source/imagenet-vgg-19.mat"#imagenet-vgg-19.mat的絕對(duì)路徑
IMG_PATH = cwd + "/source/lena.png"#lena.png的絕對(duì)路徑
input_image = imread(IMG_PATH) #讀取imagenet-vgg-19.mat文件
shape = (1,input_image.shape[0],input_image.shape[1],input_image.shape[2])
with tf.Session() as sess:image = tf.placeholder('float', shape=shape)nets, mean_pixel, all_layers = net(VGG_PATH, image)input_image_pre = np.array([preprocess(input_image, mean_pixel)])#預(yù)處理layers = all_layers # For all layers # layers = ('relu2_1', 'relu3_1', 'relu4_1')for i, layer in enumerate(layers):print ("[%d/%d] %s" % (i+1, len(layers), layer))features = nets[layer].eval(feed_dict={image: input_image_pre})#當(dāng)前層前向傳播的結(jié)果#print (" Type of 'features' is ", type(features))#print (" Shape of 'features' is %s" % (features.shape,))# Plot response if 1:plt.figure(i+1, figsize=(10, 5))plt.matshow(features[0, :, :, 0], cmap=plt.cm.gray, fignum=i+1)plt.title("" + layer)plt.colorbar()plt.show()
運(yùn)行結(jié)果:
……
總結(jié)
以上是生活随笔為你收集整理的VGG卷积神经网络模型加载与运行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个权志龙qq网名韩文
- 下一篇: 上海同济口腔医院 补牙多少钱?拔智齿多少