发布于 

tensorflow笔记(4)

一个简单的基于MNIST训练的CNN模型

卷积神经网络包含输入层、隐藏层和输出层,隐藏层又包含卷积层和pooling层,图像输入到卷积神经网络后通过卷积来不断的提取特征,每提取一个特征就会增加一个feature map,pooling层也就是下采样,通常采用的是最大值pooling和平均值pooling,因为参数太多喽,所以通过pooling来稀疏参数,使我们的网络不至于太复杂。

好啦,既然你对卷积神经网络已经有了大概的了解,下次课我们将通过代码来实现一个基于MNIST数据集的简单卷积神经网络。

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


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


# 我们定义Weight变量,输入shape,返回变量的参数。其中我们使用tf.truncted_normal产生随机变量来进行初始化
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)


# 同样的定义biase变量
# 输入shape ,返回变量的一些参数。其中我们使用tf.constant常量函数来进行初始化
def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)


# 定义卷积,tf.nn.conv2d函数是tensorflow里面的二维卷积函数
# x是图片的所有参数,W是次卷积层的权重,然后定义步长strides=[1,1,1,1]的值
# strides[0]和strides[3]的两个1是默认值
# 中间两个1代表padding时在x方向运动一步
# x方向运动一步,y方向运动一步,padding采用的方式是SAME
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')


# 定义池化pooling
# padding时,我们选的是一次一步,这样得到的图片尺寸没有变化
# 而我们希望压缩一下图片也就是参数能少一些从而减少系统复杂度
# 因此我们采用pooling来稀疏化参数,也就是卷积神经网络中所谓的下采样层。
# pooling 有两种,一种是最大值池化,一种是平均值池化,
# 本例采用的是最大值池化tf.max_pool()。
# 池化的核函数大小为2x2,因此ksize=[1,2,2,1],步长为2,因此strides=[1,2,2,1]:
def max_pool_2x2(x):
    return tf.nn.max_pool(
        x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')


# 数据来源
mnist = input_data.read_data_sets('MNIST_data', one_hot=False)

# 定义输入的placeholder
xs = tf.placeholder(tf.float32, [None, 784]) / 255  # 28x28
ys = tf.placeholder(tf.float32, [None, 10])

# -1代表先不考虑输入的图片例子多少这个维度
# 后面的1是channel的数量,因为我们输入的图片是黑白的,因此channel是1,例如如果是RGB图像,那么channel就是3。
x_image = tf.reshape(xs, [-1, 28, 28, 1])

## conv1 layer --- start ##
# 建立卷积层
# 定义第一层卷积,先定义本层的Weight,本层我们的卷积层核patch的大小是5x5
# 因为channel是1,所有输入是1, 输出是32个featuremap
W_conv1 = weight_variable([5, 5, 1, 32])

# 接着定义bias,它的大小是32个长度,因此我们传入它的shape为[32]
b_conv1 = bias_variable([32])
# 第一个卷积层
# h_conv1=conv2d(x_image,W_conv1)+b_conv1
# 同时我们对h_conv1进行非线性处理,也就是激活函数来处理喽,
# 这里我们用的是tf.nn.relu(修正线性单元)来处理,
# 要注意的是,因为采用了SAME的padding方式,
# 输出图片的大小没有变化依然是28x28,只是厚度变厚了,
# 因此现在的输出大小就变成了28x28x32
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

#最后我们再进行pooling的处理就ok啦,经过pooling的处理,输出大小就变为了14x14x32
h_pool1 = max_pool_2x2(h_conv1)

## conv1 layer --- end ##

## conv2 layer --- start ##

# 接着呢,同样的形式我们定义第二层卷积,
# 本层我们的输入就是上一层的输出,本层我们的卷积核patch的大小是5x5,
# 有32个featuremap所以输入就是32,输出呢我们定为64
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
# 接着我们就可以定义卷积神经网络的第二个卷积层,这时的输出的大小就是14x14x64
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
# 最后也是一个pooling处理,输出大小为7x7x64
h_pool2 = max_pool_2x2(h_conv2)
# 建立全连接层
# 进入全连接层时,我们通过tf.reshape()将h_pool2的输出值从一个三维的变为一维的数据
# 表示先不考虑输入图片例子纬度,将上一个输出结果展平

## conv1 layer --- end ##

## fc1 layer --- start ##

# 此时weight_variable的shape输入就是第二个卷积层展平的输出大小7*7*64
# 后面输出的size我们继续扩大,定为1024
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
#[n_sample, 7,7,64] ->> [n_samples. 7*6*64]
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
# 然后将展平后的h_pool2_flat与本层的W_fc1相乘(注意这个时候不是卷积了)
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
# 定义dropout的placeholder,它是解决过拟合的有效手段
keep_prob = tf.placeholder(tf.float32)
# 如果我们考虑过拟合的问题,可以加一个dropout的处理
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

## fc1 layer --- end ##

## fc2 layer --- start ##

# 接下来我们就可以进行最后一层的构建了,好激动啊,输入是1024
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
# 然后呢,我们用softmax分类器(多分类,输出的是各个类的概率),对我们的输出进行分类
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

## fc2 layer --- end ##

# 选优化方法
cross_entropy = tf.reduce_mean(
    -tf.reduce_sum(ys * tf.log(prediction), reduction_indices=[1]))  # loss

# 我们用tf.train.AdamOptimizer()作为我们的优化器进行优化,使我们的cross_entropy最小
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

# 接着呢就是和之前视频讲的一样喽, 定义Session
sess = tf.Session()

# 初始化变量
sess.run(tf.global_variables_initializer())

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]))


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @shyiuanchen 创建,使用 Stellar 作为主题。