现在我们终于步入正轨,了解了那么多铺垫知识后,来和神经网络来次亲密接触:
作为工科机械狗,务实一些,咱们上来就从代码搞起:
(官方形容了很多关于TensorFlow的优点,和我这种超级小白没啥关系,知道TensorFlow很好就ok了)
# -*- coding:utf-8 -*-
import tensorflow as tf # 使用TensorFlow先导入TensorFlow
# 这两句就是前面改写过的引入mnist数据库的代码
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# 这里理解为先给输入x占个坑位,none代表一个不定的值,也就是可以从60,000个图片中任意输入
# 784就不说了,肯定是对应某个的某个像素值
x = tf.placeholder(tf.float32, [None, 784])
# W,就是我们说过的权重
# b,就是偏差了
# 重点说一下Vvariable,这是一个可以在运行过程中被修改的值,为何用它呢?
# 因为我们训练的目的就是找到最合适的W和b的值,这就需要训练模型来得到,而最终得到的W和b
# 在反过来写到这里。因此我们将W和b初始化为0(zero)
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
# !!!重中之重来了,tf.matmul表示x乘以W,然后再加上b 就是我们之前说的那一套
# 然后将结果输入到softmax函数中 至此 模型搭建完毕
y = tf.nn.softmax(tf.matmul(x,W) + b)
代码的每一句都注释了,配合之前的知识,已经很好理解,不多赘述。
完成上述代码,我们只是构建了一个网络,并没有训练它,也不知道它是否达到要求。别担心,现在就让我们训练模型。
训练模型之前需要有个目标,即一个评估方法让我们知道训练结果是否正确。
这里再说一下吴恩达老师的课程上讲解的思路,我们将预测结果设定为y,准确结果设定为y'。那么y与y'之间必定有个误差,我们目的就将这个误差缩到最小。为了减小这个误差,我们引入一个损失/损失函数(cost function)。
(官方手册说,我们并不是评价我们模型多好,而是评价它有多差。没事,我觉得只需要知道就是将y与y'之间的误差缩到最小就好, [●´Å`●] )
那么带着这个思路,我们将损失函数定义为:
叫交叉熵(cross-entropy),无视这个复杂的名字,我们牢牢把握前进目标就好。
了解这些背景资料,继续注释代码来解读:
# 开始训练模型,哔卟哔卟....
# 有了交叉熵的概念,我们继续引入y_,目的是给准确的结果提供一个坑位(就是y')
y_ = tf.placeholder("float", [None,10])
# 然后回顾交叉熵的公式,我们开始计算交叉熵
# 这里官方手册说计算的是100张图片的交叉熵,开始的我:???
# 对于100这个范围有点懵,后来发现我们的每一次计算都是抽样100幅图片进行的,也就是
# 语句batch_xs, batch_ys = mnist.train.next_batch(100)中的100.
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
# 到这,使用反向传播(初步理解就是从结果反向求参数),还记得我们说过的话吗?
# 就是W,b是可以被修改的值? 这里就是在自动获得能让成本(误差)最小的W,b的值
# 按照我现在的理解,训练模型就是在训练参数。 同时这里有个0.01代表学习速率
# 何为学习速率呢?当前理解为梯度下降中的每一步的步长,学习速率过小会训练的很慢,过大会出现找不到最优解的情况
# 再次安利太大李宏毅教授的ppt
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
# 这句语句是初始化变量
# 需要说明一点 官方给的语句是:init = tf.initialize_all_variables()
# 查阅资料说官方的是针对旧版TensorFlow,新版使用我用那个语句
# 但是我是tensorflow-gpu (1.6.0) 两个语句都可以用
init = tf.global_variables_initializer()
# 这里是启动模型,初始化变量
sess = tf.Session()
sess.run(init)
# 然后循环1000次
for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
# 这里需要注意tf.argmax这个函数
# y_代表正确的标签,那么对于我们需要的数字它是这样的【已下都是主观理解】
# 比如我们需要3 那么它形成的矩阵组就是[0,0],[1,0],[2,0],[3,1]....
# 通过对比就会得到3这个标签,而对于y,如果我们也是输入3的图片
# 那么得到矩阵可能是:[0,0.1],[1,0.01],[2,0.01],[3,0.8]...(数据均为瞎掰)
# ok,通过argmax函数,我们也会得到3这个标签。 就是将argmax第二个参数理解为1,为行对比;0为对比
# 基于上述描述,我们要看得到的两个标签是否相同(equal)
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
# 多次对比后,我们可能会得到这样的布尔值[True,False,True,Ture],我们将它变为浮点数
# 妥妥的0.75(3/4)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
# 最后,陕甘宁会师:打印上述结果----显示正确率,结束!收工
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
至此,对于入门级的mnist极简神经网络构建就到这里。 这是一个没有隐藏层的最简单的神经网络模型。
输出结果:
官方说91.41%的准确率并不美丽。(つД`)感觉这个网络内心委屈的像个孩子,考了90+怎么就不美丽呢?
原来构建更复杂的网络,加入卷积(CNN)后可以达到99.9%左右,emmm,蒂花之秀,造化钟神秀,陈独秀的秀。
最后附上代码,没有被注释的千疮百孔的处子版:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x,W) + b)
y_ = tf.placeholder("float", [None,10])
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
谢谢观看٩(๑❛ᴗ❛๑)۶