自学内容网 自学内容网

卷积神经网络

在这里插入图片描述

简介:本文从为什么要进行卷积和卷积的步骤 卷积核与池化层,卷积神经网络的具体结构讲起,从手写体识别演示了卷积神经网络的用法。如果对你有帮助,希望多多点赞收藏关注,想要源码的可以私信我,不过我还是建议大家动手敲一遍,只有遇到问题才能印象深刻。

1.理论基础

1.1 传统神经网络存在的问题:

权值太多,计算量太大
权值太多,需要大量样本进行训练(样本的数量最好是权值的5-30倍)
局部感受野 --CNN卷积神经网络 CNN通过感受野和权值共享减少了神经网络的训练的参数个数

1.2卷积核

这是一个 3x3 的卷积核。(feature map),他的英文是feature 和map组成,feature有特征的意思 ,map有地图的意思。他的意思就是采取特征地图,一个3x3的卷积核与原来的图像的3x3的部分进行乘积,采样其中的特点,根据一定的步长移动。不同的卷积核可以对图片的不同特征进行采样
在这里插入图片描述

1.3 池化

通常是用2x2的大小,比如:
最大池化:用每个2x2区域大小的最大值代表这个区域
平均池化:用每个2x2区域大小的平均值代表整个区域
随机池化:用每个2x2区域大小内的一个随机值代表这个呢个区域”

1.3.1 SAME PADDING

在这里插入图片描述

在卷积的过程中,因为可能不是恰好能让卷积核把所有图像都卷积的形状,所以会给平面补0补到恰好能让卷积核完成卷积

1.3.2 VALID PADDING

不会超出平面外部,卷积采样后得到一个比原来平面小的平面

1.4 CNN结构

在这里插入图片描述
卷积神经网络的结构如图所示: n次的卷积池化+全连接层分类

2 卷积神经网络实现手写体识别

2.1 导包

这个warnings包是因为我在jupyter导入的时候总是报一些很烦的警告我就给他加了就忽略了,如果是在pycharm中是不用加的

# 传统神经网络存在的问题:
# 1.权值太多,计算量太大
# 2.权值太多,需要大量样本进行训练(样本的数量最好是权值的5-30倍)
# 局部感受野 --CNN卷积神经网络 CNN通过感受野和权值共享减少了神经网络的训练的参数个数
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

2.2 数据集和划分batch

每一个批次(batch)设计为100,导入数据集,用one_hot格式,如果您不懂什么是one_hot,我给您简单解释一下,就是比如我要分请手写体0-9一共十个数 所以就用10位01代表是那个数,如果第n位是1就代表这个数字是n。这就是one_hot

batch_size = 100

mnist = input_data.read_data_sets("MNIST_DATA",one_hot=True)
n_batch = mnist.train.num_examples // batch_size

2.3 权值、偏置值、卷积、池化(四个函数)

# 初始化权值
def weight_variable(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)
  1. x是输入一个tensor [batch批次,height高,width宽,channels通道数 ]
  2. w是卷积核(也叫作滤波器 ,[filter_height长,filter_width宽,in_channels输入通道数,out_channels输出通道数])
  3. stride步长 0和3都是1 1和2的值分别代表x方向的步长,和y方向的步长
  4. padding = SAME or VALID
# 卷积层
def conv2d(x,W):
    return tf.nn.conv2d(x,W,strides = [1,1,1,1],padding = 'SAME')
# 池化层
def max_pool_2x2(x):
    # ksieze 的 0  和 3都是1  1和2 是x和y的大小因为是2,2所以池化的创库大小是2,2
    return tf.nn.max_pool2d(x,ksize = [1,2,2,1],strides=[1,2,2,1],padding = 'SAME')

2.4 定义x和y占位符

因为图片的大小是28*28,分类是10个,所以是这么写

x = tf.compat.v1.placeholder(tf.float32,[None,784])
y = tf.compat.v1.placeholder(tf.float32,[None,10])

2.5 对x进行reshape

我把卷积层函数的要求复制下来,因为x要满足要求才能传入卷积层。 x是输入一个tensor [batch批次,height高,width宽,channels通道数 ]
所以要对x改变形状

# 改变28*28的图片格式为向量[batch批次,height高,width宽,channels通道数 ]
x_image = tf.reshape(x,[-1,28,28,1])

2.6 初始化第一个卷积层的权重

调用定义好的weight_variable,参数的含义如下:
【采样窗口的宽,采样窗口的高,采集的平面数量,卷积核的个数】
在我的代码中我定义的卷积核大小是5x5,初始平面是1 ,卷积核32个


W_conv1 = weight_variable([5,5,1,32])# 5*5的采样窗口 32个卷积核从1个平面抽取特征
b_conv1 = bias_variable([32])# 每一个卷积核一个偏置值

2.7 第一层的卷积和池化

使用的是2.3中定义好的两个函数 conv2d和max_pool_2x2
他执行的操作是:1.把reshape好的28*28图片和卷积核初始权重进行卷积,获得了32个平面,因为32个卷积核每个都获得一个平面,池化以后变成了14*14的平面

# 把x_image和权值向量进行卷积,再加上偏置值,用relu激活函数
h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

2.8 第二个卷积层的初始与卷积

因为上一个卷积层获得的是32个1414的平面,所以选择使用64个**55的卷积核对32个平面进行卷积,然后池化得到64个7*7**的平面

# 初始化第二个卷积层和偏置
W_conv2 = weight_variable([5,5,32,64])# 5*5的采样窗口 64个卷积核从32个平面抽取特征
b_conv2 = bias_variable([64])# 每一个卷积核一个偏置值

# 把h_pool1和权值向量进行卷积,再加上偏置值,用relu激活函数
h_conv2 = tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

2.9定义两个全连接层进行分类

因为我之前卷积得到的是64个7*7的平面,而且我的第一个全连接层设计了1024个神经元,所以代码如下:

# 28*28的图片经过第一卷积还是28*28,池化后变为14*14 ,32个卷积核抽取了32张平面
# 14*14第二次卷积还是14*14,池化为7*7,64个卷积核抽取了64张平面

#第一个全连接层
W_fc1 = weight_variable([7*7*64,1024])
b_fc1 = bias_variable([1024])

# 把池化层的输出扁平化为1维
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选择了0.7

keep_prob = tf.compat.v1.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)

第二个全连接层

w_fc2 = weight_variable([1024,10])
b_fc2 = bias_variable([10])

2.10交叉熵损失函数

因为使用的是softmax,所以代价函数选择更适合softmax的交叉熵代价函数

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_v2(labels=y,logits=prediction))

2.11 优化器Adam

train_step = tf.compat.v1.train.AdamOptimizer(1e-4).minimize(cross_entropy)

2.12计算准确率

先把计算结果放在一个布尔列表中,然后再计算准确率

correct_prediction = tf.equal(tf.argmax(prediction,1),tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

2.13定义session,feet_dict传参计算

with tf.compat.v1.Session() as sess:
    sess.run(tf.compat.v1.global_variables_initializer())
    for epoch in range(21):
        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(f"第{epoch+1}次epoch,Accuracy = {str(acc)}")
        

在这里插入图片描述
因为我的电脑运行的太慢了,cpu太差劲,我就给大家截个图,有兴趣的自己跑一下。


原文地址:https://blog.csdn.net/qq_54414907/article/details/143901842

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!