关于用Keras搭建AlexNet网络,网上代码很多,但是大部分都有错误,我经过一天时间学习研究,写了这一份代码。
AlenNet网络的详细描述,这位大神写的非常好,除了他写的卷积——池化——归一化我不能苟同以外就没什么了。我认为应该是卷积——归一化——池化。
AlexNet是深度学习历史上的分水岭,影响深远,其创新点主要包括:relu函数做激活函数加快了训练速度,LRN法对数据做归一化,使用dropout层防止过拟合。
Keras在搭建AlexNet的主要问题包括:
1、原论文用的归一化方法是LRN,但是最新版包括我使用的Keras已经没有这个方法了,只有一个BatchNormalization()层可以用做归一化,勉强就这样吧,效果还算可以;
2、Keras我查了好久,卷积的过程中如果想在外层填充0的话只能选择卷积层里面padding参数为'same',Google上也找到了一位大神持相同看法,毫无办法,但是幸好在这里不影响网络搭建;
3、卷积之后是先归一化再池化呢,还是先池化再归一化?网上各种说法的人都有,我们老师的PPT上是支持先归一化再池化,我就也持这种观点。
主体模型部分代码如下:
# AlexNet
model = Sequential()
#第一段
model.add(Conv2D(filters=96, kernel_size=(11,11),
strides=(4,4), padding='valid',
input_shape=(resize,resize,3),
activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(3,3),
strides=(2,2),
padding='valid'))
#第二段
model.add(Conv2D(filters=256, kernel_size=(5,5),
strides=(1,1), padding='same',
activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(3,3),
strides=(2,2),
padding='valid'))
#第三段
model.add(Conv2D(filters=384, kernel_size=(3,3),
strides=(1,1), padding='same',
activation='relu'))
model.add(Conv2D(filters=384, kernel_size=(3,3),
strides=(1,1), padding='same',
activation='relu'))
model.add(Conv2D(filters=256, kernel_size=(3,3),
strides=(1,1), padding='same',
activation='relu'))
model.add(MaxPooling2D(pool_size=(3,3),
strides=(2,2), padding='valid'))
#第四段
model.add(Flatten())
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1000, activation='relu'))
model.add(Dropout(0.5))
# Output Layer
model.add(Dense(2))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
在试验中我是用kaggle上的猫狗大战数据集,我从train数据集里读5000幅图像做训练集,其中2500幅猫2500幅狗,另读5000幅做测试集,同样是2500幅猫2500幅狗,发现最终在测试集上分类准确率能达到82%左右,效果确实不错。
我的代码和train文件夹在同一目录下,train文件夹里放的就是kaggle上下载的训练集图像。
完整代码在这个链接目录下的dogs_vs_cats_CNN.ipynb文件。