卷積神經網絡keras實作
- AlexNet
- VGGNet
- InceptionNet
- 資料 oxflower17 ,使用keras實作AlexNet,VggNet,InceptionNet
AlexNet
- 如果說 LeNet是卷積神經網絡的開山鼻祖,那麼在2012年ImageNet競賽中以超過第二名10.9個百分點的AlexNet就是激起深度學習和卷積神經網絡千層浪的巨石。
- 主要閃光點:
- 資料增廣:ImageNet1000類,輸入圖檔規定是256×256彩色圖檔,AlexNet在256x256圖中随機裁剪多張224*224圖作為訓練資料。
- 第一次采用Relu激活函數替代Sigmoid。
- 采用dropout層,避免過拟合。
- 網絡結構: 在AlexNet時代由于硬體裝置的現在,是以将網絡拆分成了兩部分,在不同GPU上訓練最後整合,對于現在我們可以直接将整個網絡整合在一起訓練。
DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet
type | kernel size / stride | output size |
---|---|---|
conv2d | 11x11/4 | 55x55x96 |
conv2d | 5x5/1 | 55x55x256 |
max pool | 2x2/2 | 27x27x256 |
conv2d | 3x3/1 | 27x27x384 |
max pool | 2x2/2 | 13x13x384 |
conv2d | 3x3/1 | 13x13x384 |
conv2d | 3x3/1 | 13x13x256 |
max pool | 2x2/2 | 6x6x256 |
dense | 4096 | |
dropout | 0.5 | |
dense | 4096 | |
dropout | 0.5 | |
dense | 1000 |
- keras 實作:使用的oxflower17 資料集太小,訓練集accuracy基本達到99%,驗證集accuracy接近50%,過拟合明顯。
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import tflearn.datasets.oxflower17 as oxflower17
from sklearn.model_selection import train_test_split
x, y = oxflower17.load_data()
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2,shuffle = True)
model = keras.models.Sequential()
model.add(keras.layers.Conv2D(filters=96,kernel_size=(11,11),strides=4,padding='same',activation='relu',input_shape=(224,224,3)))
model.add(keras.layers.Conv2D(filters=256,kernel_size=(5,5),strides=1,padding='same',activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2),strides=2))
model.add(keras.layers.Conv2D(filters=384,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2),strides=2))
model.add(keras.layers.Conv2D(filters=384,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.Conv2D(filters=256,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2),strides=2))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(4096,activation='relu'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(4096,activation='relu'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(17,activation='softmax'))
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
model.summary()
cb = [ keras.callbacks.EarlyStopping(patience=30,min_delta=1e-4),
keras.callbacks.ModelCheckpoint('./AlexNet.h5',save_best_only=True) ]
his = model.fit(x_train,y_train,batch_size=64,epochs=100,validation_data=(x_test,y_test),callbacks=cb)
pd.DataFrame(his.history).plot(figsize=(8,5))
plt.grid(True)
# plt.gca().set_ylim(0,1)
plt.show()
VGGNet
- VGG-Nets是由牛津大學VGG(Visual Geometry Group)提出,是2014年ImageNet競賽定位任務第一名和分類任務第二名中的基礎網絡。
- 主要閃光點:
- 資料增廣:采用更多種方式采集,例如先縮大成512x512,在截取224x224的樣本圖。
- 多使用更小的3x3卷積核。
- 層次更深。
- 網絡結構: 每經過一個pooling層,通道數要翻倍。(因為pooling大小減小資訊會丢失,是以使通道再翻倍。)
DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet
- keras 實作:同樣使用oxflower17 小資料集,依舊過拟合明顯,但模型效果确實更好,驗證集accuracy接近60%。
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import tflearn.datasets.oxflower17 as oxflower17
from sklearn.model_selection import train_test_split
x, y = oxflower17.load_data()
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2,shuffle = True)
model = keras.models.Sequential()
model.add(keras.layers.Conv2D(filters=64,kernel_size=(3,3),strides=1,padding='same',activation='relu',input_shape=(224,224,3)))
model.add(keras.layers.Conv2D(filters=64,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2),strides=2))
model.add(keras.layers.Conv2D(filters=128,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.Conv2D(filters=128,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2),strides=2))
model.add(keras.layers.Conv2D(filters=256,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.Conv2D(filters=256,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.Conv2D(filters=256,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2),strides=2))
model.add(keras.layers.Conv2D(filters=512,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.Conv2D(filters=512,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.Conv2D(filters=512,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2),strides=2))
model.add(keras.layers.Conv2D(filters=512,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.Conv2D(filters=512,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.Conv2D(filters=512,kernel_size=(3,3),strides=1,padding='same',activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2),strides=2))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(4096,activation='relu'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(4096,activation='relu'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Dense(17,activation='softmax'))
model.compile(optimizer=keras.optimizers.Adam(lr=0.00001),loss='sparse_categorical_crossentropy',metrics=['accuracy'])
model.summary()
cb = [ keras.callbacks.EarlyStopping(patience=30,min_delta=1e-4),
keras.callbacks.ModelCheckpoint('./VggNet16.h5',save_best_only=True) ]
his = model.fit(x_train,y_train,batch_size=64,epochs=100,validation_data=(x_test,y_test),callbacks=cb)
InceptionNet
- GoogLeNet也稱為InceptionNet因其特殊的Inception結構,在2014的ImageNet分類任務上擊敗了VGG-Nets奪得冠軍。至目前從InceptionNet-V1 到 InceptionNet-V4共遞進式的發展了4個版本。
-
Inception-V1
主要閃光點:
- 引入Inception結構:替換中間單純的卷積池化層,是一種分組卷積的思想。
DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet 對前一層的輸出采用四種不同卷積政策進行卷積,4組不同卷積得到的feature map大小都是保持一緻的,最後再将所有的feature map 一張張并排疊起來,作為輸出。
1X1的卷積層做非線性變換,用于降維,減少大量參數。
- 中間加入了2個輔助LOSS單元,避免梯度消失的情況,讓網絡更好地被訓練。這兩個輔助LOSS單元的計算被乘以0.3,然後和最後的LOSS相加作為最終的損失函數來訓練網絡。
DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet - 将最後的全連接配接層替換成Average Pooling,減少了大量的參數。
-
Inception-V2
主要閃光點:
- 引入BatchNormalization層,在每一層卷積層後面。加速了網絡訓練,防止梯度消失,一定程度避免過拟合。
- 改進Inception結構:使用2個3x3卷積核替代5x5,且減少了28%的參數量。
DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet
-
Inception-V3
主要閃光點:
- 繼續改進Inception結構:nxn卷積核并非最小,可采用一組:1xn和nx1卷積核替換。3x3換成3x1和1x3,且參數量能再降低33%。
DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet
-
Inception-V4
主要閃光點:學習了ResNet,應入了殘差連接配接塊。
-
keras 實作Inception-V2:oxflower17 小資料集,同樣過拟合明顯,但驗證集accuracy接近70%。
網絡結構:
#3x3 reduce卷積 為連接配接 #3x3卷積 的 1x1卷積。
double #3x3 reduce卷積 為連接配接 double #3x3卷積 的 1x1卷積。
DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet DL(3) - 卷積神經網絡AlexNet/VGGNet/InceptionNet之keras實作 (上)AlexNetVGGNetInceptionNet
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import tflearn.datasets.oxflower17 as oxflower17
from sklearn.model_selection import train_test_split
x, y = oxflower17.load_data()
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2,shuffle = True)
def Conv2D_BN(inputs,filter,kernel,padding,stride):
outputs = keras.layers.Conv2D(filters=filter,kernel_size=kernel,padding=padding,strides=stride,activation='relu')(inputs)
outputs = keras.layers.BatchNormalization()(outputs)
return outputs
def InceptionBlock_1(inputs,channel_for_branch):
channel_branch1,channel_branch2,channel_branch3,channel_branch4 = channel_for_branch
branch_1_1 = Conv2D_BN(inputs,channel_branch1[0],(1,1),'same',1)
branch_3_3 = Conv2D_BN(inputs,channel_branch2[0],(1,1),'same',1)
branch_3_3 = Conv2D_BN(branch_3_3,channel_branch2[1],(3,3),'same',1)
branch_3_3_2 = Conv2D_BN(inputs,channel_branch3[0],(1,1),'same',1)
branch_3_3_2 = Conv2D_BN(branch_3_3_2,channel_branch3[1],(3,3),'same',1)
branch_3_3_2 = Conv2D_BN(branch_3_3_2,channel_branch3[1],(3,3),'same',1)
branch_pooling = keras.layers.AveragePooling2D(pool_size=(3,3),strides=1,padding='same')(inputs)
branch_pooling = Conv2D_BN(branch_pooling,channel_branch4[0],(1,1),'same',1)
outputs = keras.layers.concatenate([branch_1_1,branch_3_3,branch_3_3_2,branch_pooling])
return outputs
def InceptionBlock_2(inputs,channel_for_branch):
channel_branch1,channel_branch2 = channel_for_branch
branch_3_3 = Conv2D_BN(inputs,channel_branch1[0],(1,1),'same',1)
branch_3_3 = Conv2D_BN(branch_3_3,channel_branch1[1],(3,3),'same',2)
branch_3_3_2 = Conv2D_BN(inputs,channel_branch2[0],(1,1),'same',1)
branch_3_3_2 = Conv2D_BN(branch_3_3_2,channel_branch2[1],(3,3),'same',1)
branch_3_3_2 = Conv2D_BN(branch_3_3_2,channel_branch2[1],(3,3),'same',2)
branch_pooling = keras.layers.MaxPool2D(pool_size=(3,3),strides=2,padding='same')(inputs)
outputs = keras.layers.concatenate([branch_3_3,branch_3_3_2,branch_pooling])
return outputs
def InceptionBlock_3(inputs,channel_for_branch):
channel_branch1,channel_branch2,channel_branch3,channel_branch4 = channel_for_branch
branch_1_1 = Conv2D_BN(inputs,channel_branch1[0],(1,1),'same',1)
branch_3_3 = Conv2D_BN(inputs,channel_branch2[0],(1,1),'same',1)
branch_3_3 = Conv2D_BN(branch_3_3,channel_branch2[1],(3,3),'same',1)
branch_3_3_2 = Conv2D_BN(inputs,channel_branch3[0],(1,1),'same',1)
branch_3_3_2 = Conv2D_BN(branch_3_3_2,channel_branch3[1],(3,3),'same',1)
branch_3_3_2 = Conv2D_BN(branch_3_3_2,channel_branch3[1],(3,3),'same',1)
branch_pooling = keras.layers.MaxPool2D(pool_size=(3,3),strides=1,padding='same')(inputs)
branch_pooling = Conv2D_BN(branch_pooling,channel_branch4[0],(1,1),'same',1)
outputs = keras.layers.concatenate([branch_1_1,branch_3_3,branch_3_3_2,branch_pooling])
return outputs
inputs = keras.Input(shape=(224,224,3))
x = Conv2D_BN(inputs,64,(7,7),'same',2)
x = keras.layers.MaxPool2D(pool_size=(3,3),strides=2,padding='same')(x)
x = Conv2D_BN(x,64,(1,1),'same',1)
x = Conv2D_BN(x,192,(3,3),'same',1)
x = keras.layers.MaxPool2D(pool_size=(3,3),strides=2,padding='same')(x)
x = InceptionBlock_1(x,[(64,),(64,64),(64,96),(32,)])
x = InceptionBlock_1(x,[(64,),(64,96),(64,96),(64,)])
x = InceptionBlock_2(x,[(128,160),(64,96)])
x = InceptionBlock_1(x,[(224,),(64,96),(96,128),(128,)])
x = InceptionBlock_1(x,[(192,),(96,128),(96,128),(128,)])
x = InceptionBlock_1(x,[(160,),(128,160),(128,160),(128,)])
x = InceptionBlock_1(x,[(96,),(128,192),(160,192),(128,)])
x = InceptionBlock_2(x,[(128,192),(192,256)])
x = InceptionBlock_1(x,[(352,),(192,320),(160,224),(128,)])
x = InceptionBlock_3(x,[(352,),(192,320),(192,224),(128,)])
x = keras.layers.AveragePooling2D(pool_size=(7,7),strides=1)(x)
x = keras.layers.Flatten()(x)
x = keras.layers.Dense(17,activation='softmax')(x)
model = keras.Model(inputs=inputs,outputs=x)
model.compile(optimizer=keras.optimizers.Adam(lr=0.00001),loss='sparse_categorical_crossentropy',metrics=['accuracy'])
model.summary()
cb = [ keras.callbacks.EarlyStopping(patience=30,min_delta=1e-4),
keras.callbacks.ModelCheckpoint('./InceptionNet.h5',save_best_only=True) ]
his = model.fit(x_train,y_train,batch_size=64,epochs=100,validation_data=(x_test,y_test),callbacks=cb)
pd.DataFrame(his.history).plot(figsize=(8,5))
plt.grid(True)
# plt.gca().set_ylim(0,1)
plt.show()