tensorflow及tensorboard中MNIST数据解释及实现

一、MNIST数据:

MNIST数据是tensorflow内置的一组手写数字的图片样例数据,其数据的格式是gz压缩格式。图片如下:

对于上述图片,tensorflow中存在对应的input_data将图片转为对应的字节流的形式读入,并提供了各种API将数据转换为对应的张量参与运算。具体数据的读取以及API接口的使用不做多的介绍。有兴趣的可以看一下对应的源码(mnist.py)。

MNIST数据中存在55000个训练集,10000个测试集,5000个验证集,其中训练集和验证集放在一起构成了60000个训练数据用来对模型进行训练。并且每张图片有28X28的像素点构成且均带有标签用于监督式学习。MNIST数据作为经典的识别类数据,通常被用于模型的验证以及软件环境的验证。可以通过这样一组简单的样例数据来实现tensorflow和tensorboard(tensorflow的可视化界面)的运用。

二、网络结构:

本文采用的是深度学习中卷积网络和全连接层相关连的方式构建模型并进行学习。其中分别采用了2个5x5的卷积层和一个全连链接层。最后采用softmax函数对样本进行归类。

1.卷积神经网络:

卷积神经网络主要包括卷积计算,池化两部分。

卷积计算:其中卷积的计算方式为:

其中K被称作是卷积核。由上式可以看出矩阵中的每一个元素在循环计算时对应的是同一个卷积核,而往往卷积核的维度是远小于矩阵的,因此卷积的这种特性可以使学习的参数变少及把网络的全链接(一个向量中的每个元素和另一个向量中的每个元素相连)变成部分链接(一个向量中的部分元素合起来和另一个向量中的某个元素相连)。这两个特性往往会加速网路的学习,并且在图像处理方面往往能展示出很高的性能(图像的原始数据往往存在成千上万的像素点)。其具体转变方式如下(左:全连接,一个点要和每个点相连,右:部分链接:一个点只和两个相连):

池化:池化是指用一个区域内的统计特性来代替这个区域的特征。通俗点以一个2x2的池化层来说,对于一个2x2的区域,一共有四个点,可以选则最大的值(最大池化)作为这个区域的代表生成一个节点,这样一个2x2的区域(4个点)就变成了一个点。此时可以把学习的数据不断变小,并且也增加了重要特征的影响,保证了图像的旋转等其他细微变化的不变性(当发生细微变化时不影响最大值的取舍,所以不会影响到下一层的学习)。当然池化的方法除了最大值还有平均值等,但是最大值一般比较常用。

2:判别函数:

卷积层结束后存在一个一维的全连接层,最后需要根据学习出来的特征进行判别。由于该学习的任务是将数字分为0——9共10类,因此属于多类问题,所以采用经典的softmax函数进行,具体如下:(为何采用该函数以及如果不是多类问题采用哪种函数建议可以阅读一下《统计学习方法》或者别的机器学习方法的资料)

 

3.  交叉熵:交叉熵用来衡量误差,p表示实际数据中真实结果的概率,q表示预测结果的概率。公式为:

4:dropout:dropout是一种避免过拟合的手段,通俗点来说就是通过设置一个参数使得模型在每次进行训练时只使用部分节点,这样每次随机的使用一部分节点就相当于衍生出了不同的子模型。同时又保证了参数不会过多以达到避免过拟合的目的。一般每个节点被使用的概率就是dropout的值。一般0.5较好,所有节点等可能使用。

5: 整流线性激活函数。对于神经网络,,激活层一般采用sigma函数和整流线性函数,但是sigma函数存在易于饱和的特点,因此在训练时往往会导致梯度消失。所以本文采用的是常规的线性激活函数,具体为 max(0,z)

三、模型具体参数:

输入的图片是28x28的,第一层卷积使用的是5x5的卷积核共32个(每一个卷积核学习一个特征),然后池化采用的是2x2的最大值池化方式。第二层卷积核采用的64个5x5的卷积核,池化依然采用2x2的池化方式。由于每次卷积计算采用的是SAME的方式,即每次在卷积计算过程中如果需要使用的点超过了图像的原有范围就补0。因此整个图像在卷积运算的过程中大小不变,但是经过了两次池化之后变成了原来的四分之一。全连接层采用的7x7x64行1024列的权矩阵。dropout层采用的是0.5的训练,1.0的测试概率。最后采用softmax函数进行分类。

四、具体代码:

 

#忽略掉CPU的告警信息
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
#导入tensorflow包下面的输入函数
from tensorflow.examples.tutorials.mnist import input_data
#导入tensorflow
import tensorflow as tf
#读入数据并把数据放在本地的MNIST_DATA/目录下,把标签变成one_hot的形式
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
#创建会话(调用tensorflow接口时必须的步骤)
sess = tf.InteractiveSession()

#定义以0.1为方差的随机数作为卷积核的初始化值(传入参数为卷积核的大小)


def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

#定义初始值为0.1的偏置向量(参数依然为该向量的大小)


def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

#定义卷积运算的方式,strides代表卷积模板划过的步长,均为一表示在运算过程中原始的矩阵点每个都不会漏掉。


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

#定义池化层函数,ksize表示池化层的大小,strides表示横竖取值时隔的像素点


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

#定义一些占位符,相当于先为变量开辟一块空间,然后使用feed函数来进行填充,NONE表是可以随便大小,-1也相当于none


x = tf.placeholder(tf.float32, [None, 784])
y_ = tf.placeholder(tf.float32, [None, 10])
x_image = tf.reshape(x, [-1, 28, 28, 1])

'''第一层卷积计算,with  tf.name_scope("name") as scope 表示下面的节点要放在一起组成一个节点在tensorboard中显示。
卷积层采用5x5的,32个卷积核,输入通道为1,输出通道为32
'''
with tf.name_scope("first_cov") as scope:
    W_conv1 = weight_variable([5, 5, 1, 32])
    b_conv1 = bias_variable([32])
    h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

'''第二层卷积层,卷积层采用5x5的,32个卷积核,输入通道为32,输出通道为64'''

with tf.name_scope("second_cov") as scope:
    W_conv2 = weight_variable([5, 5, 32, 64])
    b_conv2 = bias_variable([64])
    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

'''全连接层,根据上一层的输出,图片变成7x7的,含有64个输出单元所以整体变成一个7*7*64,1024的矩阵。'''
w_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
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层过滤,同样定义对应的占位符,在图的运算过程中再传入。
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

#输出层,对数据进行分类。
w_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, w_fc2) + b_fc2)

'''定义交叉熵,确定学习策略(学习率为1e-4,采用梯度下降最小化交叉熵
正确率:比较样本中的类和测试中的类是否相同,并将比较后的结果变为float型然后加和求平均。
'''
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))
#cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

'''定义可视化界面需要显示的东西
前两个:显示损失和准确率的变化趋势
中间两个:显示全连接层的权重和第一层卷积核的统计直方图
最后一个参数:显示训练的图片
'''
tf.summary.scalar("loss", cross_entropy)
tf.summary.scalar("accuracy", accuracy)
tf.summary.histogram("weight", w_fc2)
tf.summary.histogram("nn", W_conv1)
tf.summary.image("train", x_image)


#函数执行部分,首先全局初始化
tf.global_variables_initializer().run()

#对于summary需要先合并,然后把他写入对应的文件夹中,合并后的summary和会话一样也是需要执行的。
merged_summary_op = tf.summary.merge_all()
summary_write = tf.summary.FileWriter('F:/Mnist1', sess.graph)

for i in range(20000):
    #分批执行,每次训练时增加50个样本的数据进行,当所有样本都被使用后在执行该指令时就不在增加对应的样本数量。
    batch = mnist.train.next_batch(50)
    if i % 100 == 0:
        train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})
        summary_str = merged_summary_op.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})
       #将每次执行的summary添加到文件夹中
        summary_write.add_summary(summary_str, i)
        summary_write.flush()
        #输出训练步骤准确度
        print("step %d , training accuracy %g" % (i, train_accuracy))
    
    #开始训练    
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

#输出测试准确度
print("test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

五、运行结果:

1. tensorflow结果:具体结果如下:

有结果可以看出,最后测试准确度达到了99.2%。

 

2. tensorboard运行结果:

打开方式: tensorboard  --logdir = 路径,然后在浏览器中输入对应的网址,下划红线的,然后打开即可:下图为上述代码在tensorboard中每部分的展示结果。

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值