作者:IndexFziQ 链接:https://www.jianshu.com/p/36e78313628e 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。Introduction
在前馈神经网络中,当输入层的特征维度变得很高时,全连接网络需要训练的参数就会增大很多,计算速度就会变得很慢,例如一张黑白的28×28的手写数字图片,输入层的神经元就有784个。
图(1)若在中间只使用一层隐藏层,参数w就有784×15=11760多个。这很容易看出使用全连接神经网络处理图像中的需要训练参数过多的问题。
解决方案:卷积神经网络
卷积神经网络概述:
卷积神经网络(Convolutional Neural Networks,CNN) 是一种前馈神经网络。卷积神经网络是受生物学上感受野(Receptive Field)的机制而提出的。
感受野主要是指听觉系统、本体感觉系统和视觉系统中神经元的一些性质。比如在视觉神经系统中,一个神经元的感受野是指视网膜上的特定区域,只有这个区域内的刺激才能够激活该神经元。
Structure
整个的一个卷积神经网络结构以图(2)为例来讲,把每一个部分都详细地说一下。
图(2)训练集:(x,y)
输入:x
输出:y^
超参数:Padding值和个数;卷积核的维度与个数;下采样核维度,stride卷积步长
学习参数:各卷积层中各过滤器值和偏置;卷积层到池化层权重和偏置; 全连接输出网各连接权重和偏置
第一个卷积层
卷积运算:
图(3)公式:(矩阵对应项相乘,即按位相乘,最后加对应卷积核的偏置项)
图(4)假设第一个卷积层有三个filter(卷积核),一个卷积核对应一个特征映射
图(5)
通过对第一个卷积层结构和运算的介绍,可以得出卷积层相对与全连接层的特殊之处:
Fully connected layer
图(6)Convolutional layer:
![]()
图(7)卷积层与全连接层参数数量比较:
假定图像像素是10*10,第一层需要1024左右的神经元,那么:
全连接层:
参数个数:10*10*1024=102400
卷积层:
设有16个3*3的卷积核,满足16*(8*8)=1024的神经元的要求,参数个数:16*(9+1)=160
可见:参数个数明显减少
第一个池化层
图(8)举个例子说明一下是怎么池化的:
图(9)如图(9)所示,假设经过第一个卷积层,得到一个4*4的feature map,那么我们需要一个池化(也称为下采样)过程来进一步减少神经元的个数,去掉feature map中的不重要的样本。
一般采用的方法:Max Pooling/AveragePooling(求最大值/求平均值)
第二个卷积层
由图(2)可以看出在进入第二个卷积层时,卷积层的输入已经变成了三维,可以对比着一开始的image,此时多了一个深度。注意,这里是重点,在做卷积运算时每一个卷积核都要对输入进行完整的运算。如果还是不清楚,不急,慢慢来。
图(10)同样有几个卷积核输出几个特征映射,卷积核与上层输出的特征映射集合维度一致,图(11)是计算卷积的过程,加权后加上偏置=最后的特征映射
图(11)下面举个例子,可能会更好理解一些:
超参数:
Image:5*5*3
Padding:1
Input:7*7*3
Filter:3*3*3(2个)
stride:2
图(12)第二个池化层:
与第一个池化层无异
全连接层:
把最后的feature maps平化(flatten)后接入全连接层
综上,可得:
卷积神经网络有三个结构上的特性:
1 局部连接
2 权重共享
3 空间或时间上的次采样
这些特性使得卷积神经网络具有一定程度上的平移、缩放和扭曲不变性。
Training
训练步骤如下图所示:
图(13)详见《零基础入门深度学习》,讲的比较详细,但是我觉得要结合着邱锡鹏《神经网络与深度学习讲义》来看,有些基础的概念,比如感知机、前馈神经网络、BP算法,为什么会从感知机发展到神经网络?存在着什么样的问题?BP算法里为什么会出现梯度下降或者梯度上升?
Demo
这是我参考的一个CNN-Mnist Structure(手写数字识别)的例子:
![]()
图(14)代码搭的model就是这样,认真看代码是很快能看懂的。
训练集:
X:mnist.train.images(55000*784维)
Y:mnist.train.labels(55000*10维)
测试集:
一共10000个样本
超参数:
输入层:28*28
Padding值:2
卷积核filter的大小和个数
Filter1:5*5*32
Filter2:5*5*32*64
卷积步长stride:1
Pooling的大小和stride:2*2,1
迭代次数:5000
激励函数:ReLu
设置batchsize:50
输出层:10
预测结果:
5000次迭代,最终准确率接近1
损失函数:交叉熵
优化算法:
Adam算法更新各层权重变量W,b(初始化0~0.01)
Experiment results:
效果还是可以的,识别有时候跳了1,识别率很高了。
图(15)Code:
(代码格式感觉有点乱,简书我暂时不知道怎么搞,一个个敲的)
import tensorflow as tf
# input and label
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
x = tf.placeholder(tf.float32, shape=[None,784])
y_ = tf.placeholder(tf.float32, shape=[None,10])
# session
sess = tf.InteractiveSession()
# weight
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
# bias
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
# convolution
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')
# pooling
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
# first layer
W_conv1 = weight_variable([5,5,1,32])
b_conv1 = bias_variable([32])
## reshape x
x_image = tf.reshape(x, [-1,28,28,1])
## convolution and pooling
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
# second layer
W_conv2 = weight_variable([5,5,32,64])
b_conv2 = bias_variable([64])
## convolution and pooling
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
# full connect
W_fc1 = weight_variable([7*7*64,1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1,7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
# dropout layer
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
# readout layer
W_fc2 = weight_variable([1024,10])
b_fc2 = bias_variable([10])
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
# Error: put initialize variables here will error.
# train and test
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices = [1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#train_step = tf.train.GradientDescentOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# initialize variables
sess.run(tf.initialize_all_variables())
## train
for I in range(5000):
batch = mnist.train.next_batch(50)
if i %100==0:
train_accuracy = accuracy.eval(feed_dict = {x: batch[0], y_: batch[1], keep_prob:1.0})
print' training step %d, the accuracy: %g'%(i, train_accuracy)
train_step.run(feed_dict={x:batch[0], y_:batch[1], keep_prob:0.5})
# test
test_accuracy = accuracy.eval(feed_dict = {x: mnist.test.images, y_: mnist.test.labels, keep_prob:1.0})
print' the test accuracy: %g'%test_accuracy
References
《零基础入门深度学习》https://www.zybuluo.com/hanbingtao/note/433855
《神经网络与深度学习讲义》http://download.youkuaiyun.com/download/hearthougan/9750045
卷积神经网络
最新推荐文章于 2023-04-24 08:49:09 发布