TensorFlow 卷积神经网络CNN

本章节主要介绍卷积神经网络,以及如何使用TensorFlow构建卷积神经网络结构。其他内容学习请前往:TensorFlow 学习目录

目录

一、卷积神经网络的Back Propagation的推导过程

二、理解其编码过程

<1>理解卷积操作

<2>理解池化操作

三、TensorFlow对CNN进行编码使用到的编程技巧

<1> 使用全局池化来代替原有的全连接层

<2>使用多通道卷积技术

四、使用TensorFlow构建CNN在Fashion-MNIST数据集上进行训练和预测


一、卷积神经网络的Back Propagation的推导过程

具体过程请参考:CNN 卷积神经网络Back Propagation推导过程

二、理解其编码过程

<1>理解卷积操作

定义:原图大小img_x,img_y,卷积核大小ker_x, ker_y,移动步长S。

  • 窄卷积(valid):图像通过窄卷积后的图像大小为[\frac{img_x-ker_x}{S}+1]\times [\frac{img_y-ker_y}{S}+1]
  • 同卷积(same):表示卷积之后的图像尺寸与原图片的尺寸大小一样,同卷积的步长是固定的,滑动步长S=1,一般操作的时候需要用到padding技术,以此确保尺寸不变。
  • 全卷积(full):将每个图像的每一个像素点用卷积操作展开,如下图,操作之后的图像会变大,并且全卷积的步长S=1也是确定的。所以卷积之后的图像大小为(img_x+ker_x-1)\times (img_y+ker_y-1)

TensorFlow中的代码形式如下:

feature_map = tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=True)

参数:

  • input:输入图像
  • filter:定义的一个卷积核,其张量形式为[size_x, size_y,inputchannels,outputchannels],inputchannels表示的是input的通道数量,如果说input是原始输入图像的话,如果是灰度图像,那么其通道数为1,如果是RGB图像,那么通道数是3,outputchannels表示在本卷积层,需要构建多少个卷积核,每一个卷积核计算的inputchannels个feature maps通过按像素相加的形式得到新的feature maps。如果输入的input是前一层卷积层的输出,那么很自然本层的inputchannels等于上一层卷积层或者池化层的outputchannels。
  • strides:步长,其张量形式为[1, strides_x,strides_y,1]
  • padding:定义元素边框和元素内容之间的空间。只有两种操作选项模式,第一种为”SAME“,第二种为”VALID“,这两种方式就是本文前部分讲解的同卷积和窄卷积。
  • use_cudnn_on_gpu:是否使用GPU,默认值为True。

<2>理解池化操作

  • 均匀池化:区域内取均值
  • 最大值池化:区域内取最大值

TensorFlow中的代码形式如下:

tf.nn.max_pool(input, ksize, strides, padding, name=None)
tf.nn.avg_pool(input, ksize, strides, padding, name=None)

参数:

  • input:需要进行池化的输入,例如:卷积之后的feature maps。
  • ksize:池化窗口的大小,其张量形式为[1,size_x,size_y,1],因为我们并不想在batch和channels上进行池化操作,所以这两个维度为1。
  • strides:和卷积参数含义基本类似,即窗口在每一个维度上滑动的步长,其张量形式为[1,stride_x,stride_y, 1]
  • padding:和卷积参数含义一致,VALID、SAME,其中VALID表示不进行padding操作,SAME表示进行padding操作。

三、TensorFlow对CNN进行编码使用到的编程技巧

<1> 使用全局池化来代替原有的全连接层

其思想非常的简单,如果最后一层卷积层的输出通道为分类数,那么此时我连接一个大小为卷积层feature maps的大小的池化层,那么我就将一个二维张量变成了一个标量,那么此时,如果分类数为10, 就是10个标量,然后将这10个量,连成一个向量作为预测输出即可。在下面的代码中会具体体现。可以与TensorFlow 手写数字识别中的代码进行类比。

<2>使用多通道卷积技术

上面个介绍的卷积层中使用的是单个尺寸的卷积核对输入数据卷积操作,而多通道卷积核是采用不同尺寸的滤波器对上一层的feature maps或者输入图片进行特征提取。

h_pool1 = max_pool_2x2(h_conv1)

# 此时获得如为h_pool1
W_conv2_5x5 = weight_variable([5, 5, 64, 64]) 
b_conv2_5x5 = bias_variable([64]) 
W_conv2_7x7 = weight_variable([7, 7, 64, 64]) 
b_conv2_7x7 = bias_variable([64]) 

W_conv2_3x3 = weight_variable([3, 3, 64, 64]) 
b_conv2_3x3 = bias_variable([64]) 

W_conv2_1x1 = weight_variable([3, 3, 64, 64]) 
b_conv2_1x1 = bias_variable([64]) 

h_conv2_1x1 = tf.nn.relu(conv2d(h_pool1, W_conv2_1x1) + b_conv2_1x1)
h_conv2_3x3 = tf.nn.relu(conv2d(h_pool1, W_conv2_3x3) + b_conv2_3x3)
h_conv2_5x5 = tf.nn.relu(conv2d(h_pool1, W_conv2_5x5) + b_conv2_5x5)
h_conv2_7x7 = tf.nn.relu(conv2d(h_pool1, W_conv2_7x7) + b_conv2_7x7)
h_conv2 = tf.concat([h_conv2_5x5,h_conv2_7x7,h_conv2_3x3,h_conv2_1x1],3)

解析一下h_conv2的张量形状[batch, height,width,64*4],主要是看最后一个维度,表示四种不同的滤波器连接在一起形成了大小为256的输出通道。

四、使用TensorFlow构建CNN在Fashion-MNIST数据集上进行训练和预测

Fashion-MNIST数据集的解析请参考:MNIST、Fashion-MNIST、SmallNORB三款标准图像数据集

import tensorflow as tf
import numpy as np
import get_Dataset
x_train, y_train, x_test, y_test = get_Dataset.get_Dataset(name='fashion')

def conv2d(x, id, filter_size):
    with tf.variable_scope('conv2d_' + str(id)):
        w = tf.get_variable(name='filter', initializer=tf.truncated_normal(shape=filter_size, stddev=0.1),
                            dtype=tf.float32)
        b = tf.get_variable(name='bias', initializer=tf.constant(0.1, shape=[filter_size[3]], dtype=tf.float32))
        z = tf.nn.relu(tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME') + b)
    return z

def pooling2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

def pooling7x7(x):
    return tf.nn.avg_pool(x, ksize=[1, 7, 7, 1], strides=[1, 7, 7, 1], padding='SAME')

inputs = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='inputs')
labels = tf.placeholder(dtype=tf.float32, shape=[None, 10], name='labels')
predict_labels = tf.placeholder(dtype=tf.int64, shape=[None], name='predict_labels')

net = tf.reshape(inputs, shape=[-1, 28, 28, 1])
net = conv2d(net, 1, [5, 5, 1, 64])
net = pooling2x2(net)
net = conv2d(net, 2, [3, 3, 64, 64])
net = pooling2x2(net)
net = conv2d(net, 3, [3, 3, 64, 10])
net = pooling7x7(net)
logits = tf.reshape(net, [-1, 10])

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=logits))
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)

correct_prediction = tf.equal(tf.argmax(logits, 1), predict_labels)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

epochs = 50
batch_size = 32
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:
    sess.run(tf.global_variables_initializer())

    for epoch in range(epochs):
        for batch in range(int(x_train.shape[0] / batch_size)):
            batch_xs = x_train[batch * batch_size: (batch + 1) * batch_size]
            batch_ys = y_train[batch * batch_size: (batch + 1) * batch_size]

            feed_dict = {
                inputs: batch_xs,
                labels: batch_ys
            }
            sess.run(train_step, feed_dict=feed_dict)
        acc = sess.run(accuracy, feed_dict={inputs: x_test, predict_labels: y_test})
        print("Epoch ", epoch + 1, " acc=", acc)

输出:

Epoch  1  acc= 0.6975
Epoch  2  acc= 0.7331
Epoch  3  acc= 0.7561
Epoch  4  acc= 0.7683
Epoch  5  acc= 0.7788
Epoch  6  acc= 0.7857
Epoch  7  acc= 0.7924
Epoch  8  acc= 0.7975
Epoch  9  acc= 0.8007
Epoch  10  acc= 0.805
Epoch  11  acc= 0.809
Epoch  12  acc= 0.8134
Epoch  13  acc= 0.8163
Epoch  14  acc= 0.8183
Epoch  15  acc= 0.8222
Epoch  16  acc= 0.8249
Epoch  17  acc= 0.827
Epoch  18  acc= 0.8291
Epoch  19  acc= 0.8307
Epoch  20  acc= 0.8318
Epoch  21  acc= 0.8335
Epoch  22  acc= 0.8362
Epoch  23  acc= 0.8371
Epoch  24  acc= 0.838
Epoch  25  acc= 0.839
Epoch  26  acc= 0.8408
Epoch  27  acc= 0.8415
Epoch  28  acc= 0.8443
Epoch  29  acc= 0.8452
Epoch  30  acc= 0.8473
Epoch  31  acc= 0.8487
Epoch  32  acc= 0.8497
Epoch  33  acc= 0.851
Epoch  34  acc= 0.8517
Epoch  35  acc= 0.8525
Epoch  36  acc= 0.8532
Epoch  37  acc= 0.8537
Epoch  38  acc= 0.8545
Epoch  39  acc= 0.8549
Epoch  40  acc= 0.856
Epoch  41  acc= 0.857
Epoch  42  acc= 0.8578
Epoch  43  acc= 0.8588
Epoch  44  acc= 0.8599
Epoch  45  acc= 0.8599
Epoch  46  acc= 0.8611
Epoch  47  acc= 0.8621
Epoch  48  acc= 0.8631
Epoch  49  acc= 0.8642
Epoch  50  acc= 0.8654
发布了331 篇原创文章 · 获赞 135 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/Triple_WDF/article/details/103353960