题外话
这几天连续看了好几天的CNN相关的博客,在此只想把我的理解和总结记录此文章中,参考文章过多,会有一些抄袭,如有侵权,告知便可以。
一.CNN是什么?
1. CNN(convolutional neural network),顾名思义就是卷积神经网络,大致分为输入层,卷积层,池化层,卷积层,池化层,全连接层,输出层,如下图所示
CNN新手入门 如上图所示,输入层是28×28像素点的图片,在第一层卷积过程中使用20个大小为5×5的卷积核,生成了20个24×24 feature map(24 = 28-5+1,即pading=“valid”)strider =1 padding =0;然后经过池化层(max-pooling(从扫描区域取最大值),即从上一层中按设置strider = 2滑动,池化窗口为2×2,生成了20个12×12 的feature map,再到第二次卷积,使用50个大小为5×5的卷积核,strider = 1,生成了50个8×8的feature map,再经过第二次池化,strider = 2滑动,池化窗口为2×2,生成了50个4×4的feature map,然后进入全连接层,使用和上一层feature map(4×4)相等的500个50×4×4的卷积核,卷积后相加求和;再通过**函数RELU(Rectified linear unit.),此时再通过第二次全连接,使用10个100×1×1的卷积核,卷积后相加求和,在通过softmax function函数进行分类。

2.分步讲解
(1)如何卷积和卷积核大小的选取规则请看下图

图2.1
CNN新手入门
图2.2
CNN新手入门
图2.3
CNN新手入门
图2.1是在卷积中选取的一个卷积核大小为3×3,卷积核的类型有好多这里不一一介绍了比如图像锐化滤波器Sharpness Filter,边缘检测Edge Detection等,每一种提取的特征各不相同;卷积核的数值以及大小有如下规定
1)滤波器的大小应该是奇数,这样它才有一个中心,例如3x3,5x5或者7x7。有中心了,也有了半径的称呼,例如5x5大小的核的半径就是2。
2)滤波器矩阵所有的元素之和应该要等于1,这是为了保证滤波前后图像的亮度保持不变。当然了,这不是硬性要求了。
3)如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。
4)对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们将他们直接截断到0和255之间即可。对于负数,也可以取绝对值。
图2.2是是模拟输入图片矩阵大小为5×5,其中的数值代表颜色的深浅,彩色图片是三层(RGB)
图2.3是卷积的过程,其滑动的顺序是依次从左往右。
其中的运算如上图所示,每个元素相加再求和;这个过程体现了平移不变性(再图片的每个位置都执行相同的操作),而且是线性的(这个操作是线性的)。
卷积过程为了更好的提取边缘图像特征,大致有三种模式,conv2 = “full”,’‘same’’,’‘valid’’,其本质是padding取值不同。

(2)池化
1)最大池化(Max Pooling)取4个点的最大值。这是最常用的池化方法。
2)均值池化(Mean Pooling)取4个点的均值。
注意 :
由于特征图的变长不一定是2的倍数,所以在边缘处理上也有两种方案:
保留边缘。将特征图的变长用0填充为2的倍数,然后再池化。
忽略边缘。将多出来的边缘直接省去。

(3)全连接在上面描述的比较清楚
(4) **函数是什么,其作用是什么,如何选取**函数?
**函数其实就是如何把“**的神经元的特征”通过函数把特征保留并映射出来,用于更好的解决非线性问题。
常用的**函数有RELU,Sigmoid,Tanh,Softmax,
图2.3
CNN新手入门 图2.4
CNN新手入门上图所示此处为copy,理解不是很好?
图2.3为Sigmoid与人的神经反应很相似,在很多浅层模型上发挥巨大作用从数学上来看,非线性的Sigmoid函数对中央区的信号增益较大,对两侧区的信号增益小,在信号的特征空间映射上,有很好的效果。它容易出现梯度饱和,也就是斜率趋近于0。
图2.4为RELU,作为一个非线性函数,它还具备线性性质,对线性部分的输出,结果等效于左乘一个非0即1的对角阵(向量负数位置对应对角阵位置上为0),仍可以被看作是一个线性操作,这一性质会使模型的理论分析变得简单,且不会出现梯度消失。常用在深度学习当中。

(4)CNN中softmax层理解加记忆
SoftMax层计算过程:其实就是一个概率分类问题
CNN新手入门

上式中Z1,Z2,Z3,代表了全连接后的输出,3,1,-1代表了该层的权重。

二.反向传播算法的在CNN中的应用
预设定一个初始化权重矩阵,第一次图片输入,通过前向传播算法计算出一个cost,然后通过反向传播算法,计算出cost function对每层的每一个权重求导数,再通过梯度下降,设置合理的学习率,更新权重矩阵,再输入第二张图片,重复上述的过程。
具体的过程参考
文章名为 前向传播算法(Forward propagation)与反向传播算法(Back propagation) bitcarmanlee 写的很具体,跟着例子做一边,应该就没有问题了。

三.代码的实现
笔者是借助莫烦tensorflow学习CNN代码,tensorflowCPU版本,数据库是mnist库。代码中都是自己注释的,方便以后自己学习和看。

from future import print_function
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

number 1 to 10 data

mnist = input_data.read_data_sets(‘MNIST_data’, one_hot=True)

def compute_accuracy(v_xs, v_ys):
global prediction
y_pre = sess.run(prediction, feed_dict={xs: v_xs, keep_prob: 1})
correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(v_ys,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys, keep_prob: 1})
return result#输出的依旧是一个准确率

def weight_variable(shape):#只要输入shape就可以输出weight变量和bias变量
initial = tf.truncated_normal(shape, stddev=0.1)#产生随机变量
return tf.Variable(initial)#返回initial的值

def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)

def conv2d(x, W):#x为输入的值,或图片的值,也就是X的所有参数
# stride [1, x_movement, y_movement, 1]规定第一个和最后一个为1,第二个1表示在图片水平方向跨度为1,竖直方向也为1
# Must have strides[0] = strides[3] = 1
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding=‘SAME’)#2纬CNN strides再tensorflow中为一个列表;使用same padding

def max_pool_2x2(x):
# stride [1, x_movement, y_movement, 1]
return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding=‘SAME’)#ksiez是卷积核大小!!!#根据吴恩达DL视屏,卷积神经网络中pooling一般选择padding = 0,即vaild pooling?

define placeholder for inputs to network

xs = tf.placeholder(tf.float32, [None, 784]) # 28x28
ys = tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder(tf.float32)
x_image = tf.reshape(xs,[-1,28,28,1])#-1具体代表什么是由导入的数据决定的,28×28×1为一个图片的像素点,1表示DEPTH为黑白;batch_size是决定一次训练取多少张图片;-1表示不知道填什么数据,但是可以通过后面的数据计算得出右面的形状确定为以后,系统会自同进行一个除法运算,得到图片数;
#print(x_image.shape)#[n_sample,28,28,1]

conv1 layer

W_conv1 = weight_variable([5,5,1,32])#in_size是patch的长宽(5×5),channel是1,feature_map是32,卷基层作用就是从图片中提取feature,不同的feature_map提取不同feature.32取值最好为2的N次方,不同的特征可以用来标识不同类型的图片 1为本层输入的通道数
b_conv1 = bias_variable([32])#32就是卷积核的个数,按照经验取值
h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1) + b_conv1)#类似于Wx+b; tf.nn.relu表示非线性化处理#output size 282832
h_pooling1 = max_pool_2x2(h_conv1)#由于padding=“same”,所以图片大小不变,但厚度变厚, #output size 14
14*32

conv2 layer

W_conv2 = weight_variable([5,5,32,64])#patch 5x5,in size 32,out size 64
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pooling1,W_conv2) + b_conv2)#output size 14x14x64
h_pooling2 = max_pool_2x2(h_conv2) #output size 7x7x64

func1 layer

W_fc1 = weight_variable([7764,1024])
b_fc1 = bias_variable([1024])
#[n_samples,7,7,64]->>[n_samples,7764]
h_pool2_flat = tf.reshape(h_pooling2,[-1,7764])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)

func2 layer

W_fc2 = weight_variable([1024,10])
b_fc2 = bias_variable([10])
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2) + b_fc2)

the error between prediction and real data

cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
reduction_indices=[1])) # loss
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)#不用上次用的那个 le-4代表0.0001

sess = tf.Session()

important step

tf.initialize_all_variables() no long valid from

2017-03-02 if using tensorflow >= 0.12

if int((tf.version).split(’.’)[1]) < 12 and int((tf.version).split(’.’)[0]) < 1:
init = tf.initialize_all_variables()
else:
init = tf.global_variables_initializer()
sess.run(init)
saver=tf.train.Saver()
for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 0.5})
if i % 50 == 0:
print(compute_accuracy(
mnist.test.images[:1000], mnist.test.labels[:1000]))

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(10):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 0.5})
#save_path = saver.save(sess,“save_net.ckpt”)
if i % 50 == 0:
print(compute_accuracy(
mnist.test.images[:1000], mnist.test.labels[:1000]))

相关文章:

  • 2021-12-13
  • 2021-10-06
  • 2022-01-07
  • 2021-08-24
  • 2021-07-16
  • 2021-10-22
  • 2021-04-03
  • 2021-05-18
猜你喜欢
  • 2021-12-31
  • 2021-12-04
  • 2021-12-06
  • 2021-11-18
  • 2021-04-03
  • 2021-08-13
  • 2021-10-06
相关资源
相似解决方案