CNN

一.卷积神经网络结构:
1.输入层:为输入的特征数,如图像的像素数

2.卷积层:主要结构为卷积核(过滤器、内核)。一般经过卷积层之后节点矩阵会变得更深
过滤器(作用、尺寸、调整结果矩阵的大小
作用:将当前层神经网络上的一个子节点矩阵(三维的)转化为下一层神经网络上的一个单位节点矩阵,其中单位节点矩阵指的长和宽都为1,但深度不限的节点矩阵。
尺寸:长宽人工指定(33,55),处理的矩阵深度和当前神经网络节点矩阵的深度是一致的,处理后得到的单位节点矩阵的深度称为过滤器的深度
如:节点矩阵223 ,单位节点矩阵115,总共需要参数个数:2235+5=65个 其中权重参数为2235=60个,偏置参数为5个。一个滤波器的参数是223=12个,共需要5种滤波器,每种滤波器对应一个偏置项。卷积核参数与滤波器尺寸、深度以及当前节点矩阵的深度有关。
结果矩阵的大小(主要确定长宽、深度已经提前指定):受滤波器尺寸大小的影响、步长的影响、以及是否在周边填充0的影响。
当填充0时,out(length) = in(length)/stride(length)
当不填充0时,out(length) =( in(length)-filter(length)+1)/stride(length)
代码实现卷积前向传播过程:

import tensorflow as tf
# shape是四维矩阵,前两个是卷积核尺寸(长宽),第三个是当前层的深度,第四个是过滤器的深度
filter_weights = tf.get_variable('weights',shape=[5,5,3,16],initializer=tf.truncated_normal_initializer(stddev=0.1))
# 偏置项的维度是下一层的深度,即过滤器的深度
biases = tf.get_variable("biases",shape=[16],initializer=tf.constant_initializer(0.1))
# tf.nn.conv2d实现卷积前向传播
# input:当前层的节点矩阵——四维矩阵(batch_size,三维节点矩阵);strides:不同维度上的步长,长度为4的数组,第一维和第四维要是1;
# padding:填充方式,VALID不添加,SAME为全0填充
conv = tf.nn.conv2d(input=input,filter=filter_weights,strides=[1,1,1,1],padding='SAME')
#给每个节点添加一个偏置项tf.nn.bias_add
bias = tf.nn.bias_add(conv,biases)
# 添加激活函数
actived_conv = tf.nn.relu(bias)

3.池化层:最大池化;平均池化;没有参数。不改变三维矩阵的深度,只缩小矩阵的大小,减少参数,使得训练速度加快同时避免过拟合
需设置池化的大小、是否使用全0填充、移动步长
注意:卷积使用的过滤器是横跨整个深度的,而池化使用的过滤器只影响一个深度上的节点。池化层的过滤器不仅要在长和宽两个维度上移动、还要在深度上进行移动
代码实现最大池化前向传播过程:

tf.nn.max_pool(actived_conv,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')

4.全连接层:卷积与池化相当于特征提取过程,使用全连接神经网络作为分类

5.输出层softmax层主要用于分类问题

二.与全连接神经网路不同点

1.全连接神经网络每一层节点展示为一列;卷积神经网络每一层节点展示为三维矩阵。决定了输入格式的不一致。全连接神经网络输入是向量;而卷积神经网络的输入是矩阵(三维数组)。这里的矩阵是指一个batch的矩阵。
2.前者相邻两层节点之间全部互相链接,后者局部连接以及参数共享。参数大大减少,同时共享参数使得图像上的位置不受位置的影响

三.经典卷积神经网络模型
3.1 卷积神经网络结构设计通用模式

3.2 LeNet-5模型(99.5%准确率)

输入层:原始图像像素 32321

第一层,卷积层。输入32321,过滤器(55,深度为6,不使用0填充,步长为1),输出尺寸(32-5+1=28)28286。卷积层参数共5516+6=156个,连接个数有28286*(55+1)=122304个。其中下一层节点矩阵有28286=4704个节点,每个节点与55个当前层节点相连,同时有个偏置项

第二层,池化层。输入:28286。过滤器(22,不使用0填充,步长为2),输出尺寸:1414*6

第三层,卷积层。输入:14146。过滤器(55,深度为16,不使用0填充,步长为1),输出尺寸(14-5+1=10)101016。卷积层参数共55616+16=2416个,连接个数有101016*(5*5+1)=41600个。

第四层:池化层。输入:101016。过滤器(22,不使用0填充,步长为2),输出尺寸:55*16

第五层:全连接层。输入:5516。过滤器(55,深度为120,不使用0填充,步长为1)输出尺寸:11120 。卷积层参数共5516120+120=48120个,连接个数有11120*(5516+1)=48120个

第六层:全连接层。输入:120个,输出84个。参数个数84120+84=10164个,连接个数84(120+1)=10164个

第七层:全连接层。输入84个,输出10个。参数个数84*10+10=850个

tensorflow实现:输入为一个四维矩阵,全连接神经网络是一维的。调整输入数据的格式

# 调整输入格式
x = tf.placeholder(tf.float32,shape=[batch_size,mnist_inference.image_size,mnist_inference.image_size,mnist_inference.num_channels],name='x-input')
reshaped_xs = np.reshape(xs,(batch_size,mnist_inference.image_size,mnist_inference.image_size,mnist_inference.num_channels))

# 修改前向传播过程
input_node = 784
output_node = 10

image_size = 28
num_channels = 1
num_labels = 10

# 第一层卷积的尺寸以及深度
conv1_size = 5
conv1_deep = 32
# 第二层卷积的尺寸以及深度
conv2_size = 5
conv2_deep = 64
# 全连接层的节点个数
fc_size = 512
# 添加参数train表示训练或者测试,同时添加dropout在训练时使用,只在全连接层使用,而不在卷积或者池化层使用
def inference(input_tensor,train,regularizer):

    with tf.variable_scope("layer1-conv1"):
        conv1_weights = tf.get_variable("weight",[conv1_size,conv1_size,num_channels,conv1_deep],initializer=tf.truncated_normal_initializer(stddev=0.1))
        conv1_biases = tf.get_variable("bias",[conv1_deep],initializer=tf.constant_initializer(0.0))
        conv1 = tf.nn.conv2d(input_tensor,conv1_weights,strides=[1,1,1,1],padding='SAME')
        relu1 = tf.nn.relu(tf.nn.bias_add(conv1,conv1_biases))
        # 输入:28*28*1 矩阵
        # 输出:28*28*16 矩阵


    with tf.variable_scope("layer2-pooling1"):
        pooling1 = tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
        # 输入:28*28*16 矩阵
        # 输出:14*14*16 矩阵


    with tf.variable_scope("layer3-conv2"):
        conv2_weights = tf.get_variable("weight",shape=[conv2_size,conv2_size,num_channels,conv2_deep],initializer=tf.truncated_normal_initializer(stddev=0.1))
        conv2_biases = tf.get_variable('bias',shape=[conv2_deep],initializer=tf.constant_initializer(0.0))
        conv2 = tf.nn.conv2d(pooling1,conv2_weights,strides=[1,1,1,1],padding="SAME")
        relu2 = tf.nn.relu(tf.nn.bias_add(conv2,conv2_biases))
        # 输入:14*14*16 矩阵
        # 输出:14*14*64 矩阵


    with tf.variable_scope("layer4-pooling2"):
        pooling2 = tf.nn.max_pool(input=relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
        # 输入:14*14*64 矩阵
        # 输出:7*7*64 矩阵


    #注意这里全连接神经网络的输入是向量,而第四层池化层的输出是矩阵,将矩阵中的节点拉直转化为向量。其中通过get_shape函数可以得到矩阵的维度,返回的是元组
    # as_list()转化为列表
    #只有张量才可以使用get_shape这种方法,tf.shape()都可以
    pool_shape = pooling2.get_shape().as_list() #四维,第0维是一个batch的数据个数
    nodes = pool_shape[1]+pool_shape[2]+pool_shape[3]
    # 通过tf.reshape函数将第四层的输出变成一个batch的向量
    reshaped = tf.reshape(pooling2,[pool_shape[0],nodes])
    with tf.variable_scope('layer5-fc'):
        fc1_weights = tf.get_variable("weight",[nodes,fc_size],initializer=tf.truncated_normal_initializer(stddev=0.1))
        if regularizer!=None:
            tf.add_to_collection('losses',regularizer(fc1_weights))
        fc1_biases = tf.get_variable('bias',shape=[fc_size],initializer=tf.constant_initializer(0.1))
        fc1 = tf.nn.relu(tf.matmul(reshaped,fc1_weights)+fc1_biases)
        if train:
            fc1 = tf.nn.dropout(fc1,0.5)
            # 注意:dropout只在全连接层使用,不在卷积层以及池化层使用;同时在训练过程中使用,在测试过程中不使用
        # 输入:14*14*64 =3136向量
        # 输出:512向量


    with tf.variable_scope('layer6-fc2'):
        fc2_weights = tf.get_variable('weight',shape=[fc_size,num_labels],initializer=tf.truncated_normal_initializer(stddev=0.1))
        if regularizer!=None:
            tf.add_to_collection('losses',regularizer(fc2_weights))
        fc2_biases = tf.get_variable('bias',shape=[num_labels],initializer=tf.constant_initializer(0.1))
        fc2 = tf.matmul(fc1,fc2_weights)+fc2_biases
        # 输入:512向量
        # 输出:10向量
    return fc2

3.3 Inception 模型

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章