0.序
之前一直在使用caffe在进行深度学习的实验,我的上一篇深度学习文章就是用caffe来检测病斑,但是在使用的过程中发现caffe虽然在速度上要快很多,但是在数据准备上有些复杂,调整网络结构和参数上也比较麻烦。所以我开始尝试其他的框架,比如theano和keras,而我目前的实验内容是用深度学习对病斑进行分类,这次的文章是对实验的一小部分,主要是对卷积神经网络CNN中各层输出结果的分析。
1.keras简介
Keras是基于Theano的一个深度学习框架,它的设计参考了Torch,用Python语言编写,是一个高度模块化的神经网络库,支持GPU和CPU。使用文档在这:http://keras.io/,这个框架火起来已经有很长一段时间了,目前使用keras的人非常多,使用上的问题可以到github提issue:https://github.com/fchollet/keras
谈一下使用上的体会,keras是基于theano写的,theano的操作相对keras用更细节更底层一些,而keras等于是用theano做了一些网络层和操作上的集成。因为是使用Python写的,代码写起来也非常快,另外在官网上有非常详细的例子。需要注意的是,keras一直在更新,所以别人博客以前的代码可能会不适用了,因为会有接口上的变化。
2.网络模型
2.1 模型分析
我在这里直接采用的是cifar10中使用到的CNN卷积神经网络,该网络结构图如下图所示:
关于cifar10的一些研究结果,目前在这个网站上总结有许多方法(http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html),同时也有其他的一些数据集的研究结果。
在这个网络中,卷积层是对图像进行卷积,可以理解为对图像提取特征,其中滤波器的数量越多,找到合适特征的概率也会大一些,当然数量合适就可以,太大不仅仅效果没有提高,还会占用过多的内存。
另外pooling层是做池化操作,从信号处理的角度可以理解为对图像进行下采样,也就是过滤出更有用的特征。具体可以看下别人的博客(http://blog.youkuaiyun.com/danieljianfeng/article/details/42433475)。当然严格来说,在这里pooling层可以与上一层的卷积层一起,认为是整个网络的一层
2.2 网络模型代码
#coding: utf-8
#THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python
import theano
import cv2
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D, AveragePooling2D
from keras.optimizers import SGD, Adadelta, Adagrad
from keras.utils import np_utils, generic_utils
from Load_data import load_data
data, label=load_data()
label = np_utils.to_categorical(label, 2)
print ('finish loading data')
batch_size = 111
nb_classes = 2
nb_epoch = 2
data_augmentation = True
img_rows, img_cols = 64, 64
img_channels = 3
#init a model
model = Sequential()
#layer1:conv1
model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=(img_channels, img_rows, img_cols)))
model.add(Activation('relu'))
#layer2:conv2
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
#layer3:pool1
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
#layer4:conv3
model.add(Convolution2D(64, 3, 3, border_mode='same'))
model.add(Activation('relu'))
#layer5:conv4
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
#layer6:pool2
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
#layer7:connect1
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
#softmax
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
result = model.fit(data, label, batch_size=batch_size,nb_epoch=nb_epoch,shuffle=True,verbose=1,show_accuracy=True,validation_split=0.3)
print model.evaluate(data, label, batch_size=batch_size)
keras支持GPU的使用,拥有GPU的用户可以用下面这条指令调用GPU模式:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python filename.py
为了了解网络在具体实行过程中的效果,我对每个卷积层后的结果进行了提取。下面是对第一个卷积层进行提取的代码:
#layer1:conv1
model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=(img_channels, img_rows, img_cols)))
model.add(Activation('relu'))
model.compile(loss='categorical_crossentropy', optimizer='adamax')
feature_l1 = model.predict(data, batch_size=batch_size)
for i in range(793):
for j in range(32):
cv2.imwrite('/home/ganlinhao/DeepLearning/keras/Disease/feature_output/layer1/' + str(i) + '_' + str(j) + '.jpg', feature_l1[i][j])
3 特征提取
下面是原图和一些提取到的特征图:
(1)原图
这是一些柑橘溃疡病的图片,有些只是一些普通病斑,有些则是柑橘溃疡病的病斑
(2)提取到的特征图
从提取的到图片可以看到,有些图片中是成功提取到了特征,但是有些图片并没有提取到特征,这是因为不是每一个滤波器都可以提取到特征,所以这也就是为什么我前面说增加滤波器可以在一定程度上提高效果。
4 讨论
(1) 每一层的参数的调整需要一些经验,同时当达到一定效果后,再调整也不会有什么效果上的提高。
(2) Dropout的使用可以避免最后结果的过拟合
(3)对于Alex提出的这个网络,单纯地移植的话,很难说是否可以得到很好的效果,目前一些论文的做法是通过深度学习网络选择特征的同时,再采用一些传统方法(比如SVM)进行辅助,事实证明效果相当不错。
(4)GoogLeNet比AlexNet要更加复杂,不过我只看到了caffe的源码实现,而没有看到keras上的实现,后面可以尝试使用GoogLeNet进行实验。
5 代码
我的代码已经更新到了我的github主页中:
https://github.com/GumpCode/Disease/tree/master/feature_output
对于深度学习的工作有任何进展,我会在其他博文中展示,此博文为原创,转载请注明:
http://blog.youkuaiyun.com/GumpCode/article/details/50753918