今天看了卷积神经网络的基本概念,并实际应用了一次。
使用卷积神经网络的原因在于对于图像识别来说(目前我接触过的内容),如果大量输入图像的像素点进行深度神经网络的学习,那么随着层数的增多,参数值会以几何数增长因为每个神经元如果完全连接下一层其他神经元,那么在两层网络之间就会出现n x m个参数,这导致计算量极大地被增加。
为了减小计算量,一个思路就是减少输入的数量。而卷积神经网络就是依靠filter,也就是过滤器来减少输入。
具体来讲,卷积神经网络通过设定一个kernel,也就是一个小方块矩阵,用这个矩阵在整张图像上进行遍历,计算这个小方块矩阵和原图像中同样大小的矩阵的内积,得到一个数值填入特征图的新矩阵中。这样做的目的是为了获得一张特征图。这张特征图通过数字研究了大图像和filter之间的相似关系,并且给出一个与相似程度相关的数值,如此提取出了特征。
设置多个filter就可以尝试提出图片里不同的特征。
而这些小的特征就代替了一个一个的像素成为新的输入,进而进入池化(pooling)阶段。池化层本质上类似于缩放,道理就是如果有一张10241024的图,图上画了一个乌龟,然后这张图缩小成2828的图标,我们依然可以看得出这是一只乌龟,原因就是乌龟这张图里面有一些点和线的关系存在,因此维持了乌龟的形态。而池化层的Maxpooling方法就是在特征图里面以在某个规模的小矩阵(自定)里面取最大值,形成新的由前面抽取的最大值构成的矩阵。
最后还有一个可以增加的层次就是dropout层,dropout层的做法就是在训练模型的过程中关闭某些神经元,这个行为促使了某些本来没有分到什么权重的神经元被重新启用,并强迫它们接收训练,由此减少了over-fitting的情况。
综上,用keras框架的代码简单定义一个CNN神经网络:
def leNet_model():
model = Sequential()
#设置卷积层, 使用30个5*5的filter,激活函数为relu
model.add(Conv2D(30, (5, 5), input_shape = (28, 28, 1) , activation ='relu'))
#Maxpooling,‘池子’的大小是2,2
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(15, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
#变成一维数组,重新变成输入层进行输入
model.add(Flatten())
model.add(Dense(500, activation='relu'))
#对网络进行dropout处理
model.add(Dropout(0.5))
#分类使用softmax函数
model.add(Dense(num_classes, activation='softmax'))
model.compile(Adam(lr=0.01), loss='categorical_crossentropy', metrics=['accuracy'])
return model