CNN(卷积神经网络)

  大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理解,而且能够帮助新手快速入门。

  本文主要介绍了CNN(卷积神经网络),希望能对同学们有所帮助。

1. 卷积神经网络(CNN)结构

cnn网络结构一般为卷积层----池化层----卷积层----池化层----卷积层----池化层----…----全连接层----全连接层----…

2. 卷积层

卷积层的输入是是一个四维数组,如[batch, in_height, in_width, in_channels],如[128, 28, 28, 3],这里的3指channel(通道个数),28×28分别对应height和width,128指一批训练样本共有128个,完整物理含义可以理解为128个样本中,对于每个样本的输入是3个28×28的矩阵。卷积层的计算是输入和卷积核(filter)对应元素相乘再相加。卷积核也是一个四维数组,[filter_height, filter_width, in_channels, out_channels],heigt与width类似于input,filter的height和width决定了将input划分的形状;in_channels要和input的in_channels一样,out_channel即输出结果的channel数,也即filter的个数,就像全连接中x与w相乘后维度由n变成m。卷积层具体计算过程如下图所示:对于filter1,第一步:A与1相乘的结果+B与5相乘的结果;第二步:按照stride(步长)如2,下图中1对应的矩阵就要向右移动2步,上面移动完后向下移动两步,然后向右。依次计算A×2+B×6、A×3+B×7、A×4+B×8。最终得到一个2×2的矩阵,然后再加上一个偏置项。filter2和filter1一样做同样的操作。
在这里插入图片描述
最终结果如下图:
在这里插入图片描述
卷积层输出的结果也为四维数组,和input一样[batch, in_height, in_width, in_channels]。
tf中,卷积层是用tf.nn.conv2d(
input,
filter=None,
strides=None,
padding=None,
use_cudnn_on_gpu=True,
data_format=‘NHWC’,
dilations=[1, 1, 1, 1],
name=None,
filters=None
)
input和filter上述已经讲过,strides为int或list of ints,只有一个数时如2,表示height和width每次都移动两步;当为list of ints式,如[1, 2, 3, 1]表示heiht每次移动两步,width每次移动3步,开头的1对应input的batch,一般都为1,最后的1对应input的channel,一般也为1。
padding的意思是,按照stride向右移动或者向下移动后,如果最右边或最下边不够了怎么办,两种处理方式:SAME和VALID。
在这里插入图片描述
在这里插入图片描述
其他参数可以忽略。

3. 池化层

3.1 池化层正向传播

池化层和卷积层的移动原理相似,首先定义一个小区域(小矩阵),使用最大池化、平均池化、随机池化中的一种得到该小矩阵的结果(最大池化即返回小矩阵的最大值,平均池化返回小矩阵的平均值,随机池化就是随机选择一个数)。然后按照stride移动得到一个新的小矩阵,依次类推得到最终结果。如上述卷积层后按照每2×2,步长为1进行最大池化,得到结果为3 & 6。tf中最大池化为tf.nn.max_pool,平均池化为tf.nn.avg_pool。下面以max_pool为例讲解:
tf.nn.max_pool(
value,
ksize,
strides,
padding,
data_format=‘NHWC’,
name=None,
input=None
)
value即卷积层后的结果值,ksize类似stride,int或list of ints,[1, 2, 3, 1],开头和结果两个1对应batch_size 和channel,一般都为1,中间的2,3表示每2×3的小矩阵进行一次最大池化。stride、padding和卷积层一样

3.2 池化层反向传播

在这里插入图片描述

4. 全连接层

全连接层同dnn,注意池化层的结果仍然是一个四维的,因此要扁平化处理成二维的[batch, dimension。

5. 使用tensorflow实现cnn实例

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot = True)
# batch_size批次大小
batch_size = 100
# iteration
n_batch = mnist.train.num_examples // batch_size

# 初始化权值
def weight_variabel(shape):
    initial = tf.truncated_normal(shape, stddev = 0.1)
    return tf.Variable(initial)

# 初始化偏置
def bias_variable(shape):
    initial = tf.constant(0.1, shape = shape)
    return tf.Variable(initial)

# 卷积层
def con2d(x, W):
    return tf.nn.conv2d(x, W, strides = [1, 1, 1, 1], padding = 'SAME')

# 池化层
def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize = [1, 2, 2, 1], strides = [1, 2, 2, 1], padding = 'SAME')

# 定义placeholder
x = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])

# 改变x的格式转化为4D向量[batch, in_height, in_width, in_channels]
x_image = tf.reshape(x, [-1, 28, 28, 1])

# 初始化第一个卷积层的权值和偏置
w_conv1 = weight_variabel([5, 5, 1, 32])# 5*5的采样窗口,32个卷积核从一个平面抽取数据
b_conv1 = bias_variable([32])# 每个卷积核有一个偏置

# 将x_image和权值向量进行卷积,再加上偏置,然后应用于relu激活函数
h_conv1 = tf.nn.relu(con2d(x_image, w_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

# 初始化第二个卷积层的权值和偏置
w_conv2 = weight_variabel([5, 5, 32, 64])
b_conv2 = bias_variable([64])

# 将h_pool和权值向量进行卷积,再加上偏置项,应用于relu函数
h_conv2 = tf.nn.relu(con2d(h_pool1, w_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

# 28*28第一次卷积后为28*28,第一次池化后为14*14
# 14*14第一次卷积后为14*14,第一次池化后为7*7
# 上述操作后得到64张7*7的平面

# 初始化第一个全连接层的权值
w_fc1 = weight_variabel([7*7*64, 1024])
b_fc1 = bias_variable([1024])

# 把池化层2的输出扁平化为1维
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) 
# 或者可以使用tf.layers.Flatten(h_pool2):保留第0维数据,其他维度展平成到一个轴上

# 求第一个全连接层的输出
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, w_fc1) + b_fc1)

# keep_prob 用来表示神经元的输出概率
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

# 初始化第二个全连接层
w_fc2 = weight_variabel([1024, 10])
b_fc2 = bias_variable([10])

# 计算输出
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, w_fc2) + b_fc2)

# 交叉熵损失函数
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = y, logits = prediction))

# 优化器
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

# 结果存放到布尔
correct_prediction = tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1))

# 准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(10):
        for batch in range(n_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            sess.run(train_step, feed_dict = {x:batch_xs, y:batch_ys, keep_prob:0.7})
        acc = sess.run(accuracy, feed_dict = {x:mnist.test.images, y:mnist.test.labels,keep_prob:1.0})
        print('Iter' + str(epoch) + ', Testing Accuracy = ' + str(acc))
Iter0, Testing Accuracy = 0.7716
Iter1, Testing Accuracy = 0.8763
Iter2, Testing Accuracy = 0.9767
Iter3, Testing Accuracy = 0.9799
Iter4, Testing Accuracy = 0.9826
Iter5, Testing Accuracy = 0.9859
Iter6, Testing Accuracy = 0.9872
Iter7, Testing Accuracy = 0.9849
Iter8, Testing Accuracy = 0.988
Iter9, Testing Accuracy = 0.9879

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的喵喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值