tensorflow MNIST softmax 实战

MNIST机器学习入门

MNIST是一个入门级的计算机视觉数据集,它包含各种手写数字图片:
images

MNIST 数据下载
文件内容
train-images-idx3-ubyte.gz训练集图片 - 55000 张 训练图片, 5000 张 验证图片
train-labels-idx1-ubyte.gz训练集图片对应的数字标签
t10k-images-idx3-ubyte.gz测试集图片 - 10000 张 图片
t10k-labels-idx1-ubyte.gz测试集图片对应的数字标签
MNIST数据集

MNIST数据集的官网:MNIST数据集
引入数据集:

import tensorflow.examples.tutorials.mnist.input_data as input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

数据集被分成两部分:60000行的训练数据集(mnist.train)和10000行的测试数据集(mnist.test)。
这样的切分很重要,在机器学习模型设计时必须有一个单独的测试数据集不用于训练而是用来评估这个模型的性能,从而更加容易把设计的模型推广到其他数据集上(泛化)。

每一个MNIST数据单元有两部分组成:一张包含手写数字的图片和一个对应的标签。我们把这些图片设为“xs”,把这些标签设为“ys”。训练数据集和测试数据集都包含xs和ys,比如训练数据集的图片是 mnist.train.images ,训练数据集的标签是 mnist.train.labels。image

这个数组展开成一个向量,长度是 28x28 = 784。如何展开这个数组(数字间的顺序)不重要,只要保持各个图片采用相同的方式展开。从这个角度来看,MNIST数据集的图片就是在784维向量空间里面的点, 并且拥有比较复杂的结构 (提醒: 此类数据的可视化是计算密集型的)。

在MNIST训练数据集中,mnist.train.images 是一个形状为 [60000, 784] 的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点。在此张量里的每一个元素,都表示某张图片里的某个像素的强度值,值介于0和1之间。image

相对应的MNIST数据集的标签是介于0到9的数字,用来描述给定图片里表示的数字。为了用于这个教程,我们使标签数据是"one-hot vectors"。 一个one-hot向量除了某一位的数字是1以外其余各维度数字都是0。所以在此教程中,数字n将表示成一个只有在第n维度(从0开始)数字为1的10维向量。比如,标签0将表示成([1,0,0,0,0,0,0,0,0,0,0])。因此, mnist.train.labels 是一个 [60000, 10] 的数字矩阵。
image
数学模型:Softmax Regression

Softmax回归介绍

softmax回归(softmax regression)分两步:

第一步

为了得到一张给定图片属于某个特定数字类的证据(evidence),我们对图片像素值进行加权求和。如果这个像素具有很强的证据说明这张图片不属于该类,那么相应的权值为负数,相反如果这个像素拥有有利的证据支持这张图片属于这个类,那么权值是正数。

下面的图片显示了一个模型学习到的图片上每个像素对于特定数字类的权值。红色代表负数权值,蓝色代表正数权值。
image

我们也需要加入一个额外的偏置量(bias),因为输入往往会带有一些无关的干扰量。因此对于给定的输入图片 x 它代表的是数字 i 的证据可以表示为

evidence_i = \sum_j W_i,_jx_j+b_i

其中

W_i

代表权重,

b_i

代表数字类的偏置量,j 代表给定图片 x 的像素索引用于像素求和。然后用softmax函数可以把这些证据转换成概率 y:

y=softmax(evidence)

这里的softmax可以看成是一个激励(activation)函数或者链接(link)函数,把我们定义的线性函数的输出转换成我们想要的格式,也就是关于10个数字类的概率分布。因此,给定一张图片,它对于每一个数字的吻合度可以被softmax函数转换成为一个概率值。softmax函数可以定义为:

softmax(x) = normalize(exp(x))

展开等式右边的子式,可以得到:

softmax(x)_i = \frac{exp(x_i)}{\sum_jexp(x_j)}

但是更多的时候把softmax模型函数定义为前一种形式:把输入值当成幂指数求值,再正则化这些结果值。这个幂运算表示,更大的证据对应更大的假设模型(hypothesis)里面的乘数权重值。反之,拥有更少的证据意味着在假设模型里面拥有更小的乘数系数。假设模型里的权值不可以是0值或者负值。Softmax然后会正则化这些权重值,使它们的总和等于1,以此构造一个有效的概率分布。(更多的关于Softmax函数的信息,可以参考Michael Nieslen的书里面的这个部分,其中有关于softmax的可交互式的可视化解释。)

对于softmax回归模型可以用下面的图解释,对于输入的xs加权求和,再分别加上一个偏置量,最后再输入到softmax函数中:
image
如果把它写成一个等式,我们可以得到:image

我们也可以用向量表示这个计算过程:用矩阵乘法和向量相加。这有助于提高计算效率。(也是一种更有效的思考方式)
image

更进一步,可以写成更加紧凑的方式:

y = softmax(Wx+b)
训练模型

为了训练我们的模型,我们首先需要定义一个指标来评估这个模型是好的。其实,在机器学习,我们通常定义指标来表示一个模型是坏的,这个指标称为成本(cost)或损失(loss),然后尽量最小化这个指标。但是,这两种方式是相同的。

一个非常常见的,非常漂亮的成本函数是“交叉熵”(cross-entropy)。交叉熵产生于信息论里面的信息压缩编码技术,但是它后来演变成为从博弈论到机器学习等其他领域里的重要技术手段。它的定义如下:

H_{y'} = - \sum_iy'_ilog(y_i)

y 是我们预测的概率分布, y’ 是实际的分布(我们输入的one-hot vector)。比较粗糙的理解是,交叉熵是用来衡量我们的预测用于描述真相的低效性

实现回归模型
# -*- coding: utf-8 -*-
'''
	@Author: king
	@email: wang_shubing@126.com
	@Date:   2018-11-07 17:36:10
	@desc:
'''
import tensorflow.examples.tutorials.mnist.input_data as input_data
import tensorflow as tf
# 获取数据
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)
# 构造x变量(tf.placeholder() 创建占位符.)能够输入任意数量的MNIST图像

# 每一张图展平成784维的向量。我们用2维的浮点数张量来表示这些图,这个张量的形状是[None,784 ]。
#(这里的None表示此张量的第一个维度可以是任何长度的。)
x = tf.placeholder("float", [None, 784])

# 构建权重 W 与偏置值 b,Variable 创建变量
# 用全为零的张量来初始化W和b
# W的维度是[784,10] b的类型是[10]
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

# 实现模型

# tf.matmul(X,W)表示x乘以W
y = tf.nn.softmax(tf.matmul(x,W) + b)

# 训练模型

y_ = tf.placeholder("float", [None,10])
# 计算交叉熵

# tf.log 计算 y 的每个元素的对数
# y_ 的每一个元素和 tf.log(y_) 的对应元素相乘
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

# 梯度下降算法(gradient descent algorithm)以0.01的学习速率最小化交叉熵。
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

# 初始化变量
init = tf.initialize_all_variables()
# 启动模型
sess = tf.Session()
sess.run(init)

# 训练模型


# 随机抓取训练数据中的100个批处理数据点,
# 然后我们用这些数据点作为参数替换之前的占位符来运行train_step
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})
    #每隔50次打印一次
    if i % 50 ==0:
        # 评估模型

        # tf.argmax给出某个tensor对象在某一维上的其数据最大值所在的索引值
        # tf.argmax(y,1)返回的是模型对于任一输入x预测到的标签值 而tf.argmax(y_,1) 代表正确的标签
        # tf.equal 来检测我们的预测是否真实标签匹配(索引位置一样表示匹配)。
        correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
        # 将布尔值转换为浮点数然后取平均值 eg:[True, False, True, True] 会变成 [1,0,1,1] ,取平均值后得到 0.75
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
        # 计算所学习到的模型在测试数据集上面的正确率。
        print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

使用一小部分的随机数据来进行训练被称为随机训练(stochastic training)- 在这里更确切的说是随机梯度下降训练

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值