神经网络学习(二)神经网络-手写字体识别
框架:Tensorflow 1.10.0
数据集:mnist数据集
策略:交叉熵损失
优化:梯度下降
五个模块:拿数据、搭网络、求损失、优化损失、算准确率
一、拿数据
1、下载数据集
下载数据集点这里:mnist数据集官网下载。将下图四项下载下来。放入接下来代码所在的文件夹。
2、导入数据
把tensorflow和input_data给导进来,tensorflow就不作解释了,input_data是用来操作mnist数据集的。代码如下。( ps:全部代码在最下面,不要着急,先按照下面的思路走完,然后再看代码也不迟。代码里也加了注释。静心往下看。)
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
将上面下载的四项数据文件的路径写进去代码如下,目标值使用独热编码(one_hot)
mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)
3、数据集简介
手写数字的MNIST数据库有一个包含60,000个示例的训练集和一个包含10,000个示例的测试集。它是NIST中更大集合的子集。在固定大小的图像中,数字已被大小归一化并居中。
里面都是手写的数字(从0到9)的图片。
二、搭建网络
1、建立占位符
tf.variable_scope可以认为是一个空间或者是op管理器,在此范围内创建的变量都属于这个空间,注意:不可创建相同名称的变量。其中x与y_true 作用是占座位或是分割数据,是为训练样本跟其对应的特征值(样本所所属的类别)准备的。784是如何来的呢?mnist数据集中包含很多图片,图片 长*宽=28×28=784,即像素为784。上面提到 mnist数据集里面包含6000个示例,其中一个示例就是一张照片, 一张照片就是28×28=784,那就可以把mnist数据集看做是一个6000×784的矩阵。 None(矩阵的行)在这的表示为任意值或不确定值,因为这关系到我们每一次训练模型时所用到的样本大小(batch)。
with tf.variable_scope("data"):
x = tf.placeholder(tf.float32, [None, 784])
y_true = tf.placeholder(tf.int32, [None, 10])
2、搭建全连接层神经网络
简单的来说就是wx+b:w为权重,b为偏置。
神经网络训练的过程 其实就是通过对比预测值(y_predict)与目标值(y_true)间的差异来不断优化w跟b的一个过程。那么下面第一步就是初始化w跟b。
其中tf.random_normal([784, 10]两个变量784跟10,784为特征点(一张图片的784个像素点或一张图片的784个特征)数量,10为其目标值(0-9)的数量。
y_predict即为一次预测所得到的结果。
with tf.variable_scope("fc_model"):
# 随即初始化权重和偏置
weight = tf.Variable(tf.random_normal([784, 10], dtype=float, name="w"))
bias = tf.Variable(tf.constant(0.0, shape=[10]))
y_predict = tf.matmul(x, weight) + bias # tf.matmul是矩阵乘法
三、计算损失(loss)
求平均交叉熵损失(先经过softmax得到概率,后交叉熵拿损失,后求平均损失)
什么是损失,损失就是我们的预测值跟其对应的目标值(其真实值)之间的差异。
这里我们用到了交叉熵损失函数数学公式如下:
在求损失之前我们先计算预测值的概率,这里用到的是softmax函数,数学公式看不明白没事 tensorflow一行代码就解决,tf.nn.softmax_cross_entropy_with_logits(这一行代码就把softmax跟交叉熵损失函数包括了)
with tf.variable_scope("soft_cross"):
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))
四、梯度下降减小损失
0.1是学习率 不要太大了,再将损失传进去。个人认为这个过程才是真正的训练过程。
with tf.variable_scope("optimizer"):
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
五、计算准确率
with tf.variable_scope("acc"):
# 分别拿到预测样本跟目标样本每一行的最大下标 ,若下表相等 返回1 不相等返回0
equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
六、效果
1、用了测试集的100张照片进行测试,准确率为85%。
七、代码
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
FlAGS = tf.flags.FLAGS
tf.flags.DEFINE_integer("is_train", 0, "指定程序是预测还是训练")
# 单层(全连接阶层)
def full_connected():
# 获取数据
mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)
# 1、建立数据占位符 x [None,784] y_true[None,10]
with tf.variable_scope("data"): # tf.variable_scope算是个命名空间或者是op管理器,在此范围内创建的变量都属于这个空间,注意:不可创建相同名称的变量。
x = tf.placeholder(tf.float32, [None, 784]) # 占位符,【none,784】表示任意行,取784列
y_true = tf.placeholder(tf.int32, [None, 10])
# 2、建立一个全连接层的神经网络 w = [784,10] b = [10]
with tf.variable_scope("fc_model"):
# 随即初始化权重和偏置
weight = tf.Variable(tf.random_normal([784, 10], dtype=float, name="w"))
bias = tf.Variable(tf.constant(0.0, shape=[10]))
# (前向传播)预测None个样本的输出结果matrix [None,784]*[784,10]+[10] = [None,10]
y_predict = tf.matmul(x, weight) + bias # tf.matmul矩阵乘法
# 3、求所有样本的损失、然后求平均值
with tf.variable_scope("soft_cross"):
# 求平均交叉熵损失(先经过softmax得到概率,后交叉熵拿损失,后求平均损失)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))
# 4、梯度下降求出损失
with tf.variable_scope("optimizer"):
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
# 5、计算准确率
with tf.variable_scope("acc"):
# 分别拿到预测样本跟目标样本每一行的最大下标 ,若下表相等 返回1 不相等返回0
equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
# 准确率=算平均值 None个样本 [1,0,1,0,1,1,0,1,..............................]
accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
# 收集变量 (一维)单个数字值收集
tf.summary.scalar("losses", loss)
tf.summary.scalar("acc", accuracy)
# 收集变量 高纬度变量收集
tf.summary.histogram("weightes", weight)
tf.summary.histogram("biases", bias)
# 定义一个合并变量的操作operation
merged = tf.summary.merge_all()
# 定一个初始化变量的op
init_op = tf.global_variables_initializer()
# 定义一个saver用于保存模型
saver = tf.train.Saver()
correct = 0
# 6、开启会话去训练
with tf.Session() as sess:
# 初始化变量
sess.run(init_op)
# 建立events文件,然后写入
filewriter = tf.summary.FileWriter("./temp/summary/test/", graph=sess.graph)
# 设置一个标志位用于判断是进行训练 还是进行测试机预测
# 如果是1 则训练,0则预测
if FlAGS.is_train == 1:
# 迭代步数去训练,更新参数 预测
for i in range(2000):
# 取出真实存在的目标值和特征值
mnist_x, mnist_y = mnist.train.next_batch(50)
# 运行train_op训练
sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})
# 写入每一步训练的值
summary = sess.run(merged, feed_dict={x: mnist_x, y_true: mnist_y})
filewriter.add_summary(summary, i)
print("训练地%d步,准确率为:%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))
# 保存模型
saver.save(sess, "./temp/ckpt/fc_model")
else:
saver.restore(sess, "./temp/ckpt/fc_model")
# 如果是0,则作出预测
for i in range(100):
# 每次测试一张图片
x_test, y_test = mnist.test.next_batch(1)
print("第%d张图片目标是%d,预测结果是:%d" % (
i,
tf.argmax(y_test, 1).eval(),
tf.argmax(sess.run(y_predict, feed_dict={x: x_test, y_true: y_test}), 1).eval()
))
if (tf.argmax(y_test, 1).eval() == tf.argmax(sess.run(y_predict, feed_dict={x: x_test, y_true: y_test}),
1).eval()):
correct += 1
print("100样本预测准确率:%f" % (correct/100))
return None
if __name__ == "__main__":
full_connected()