TensorFlow学习笔记3-从MNIST开始

TensorFlow学习笔记3-从MNIST开始学习softmax


本笔记内容为“从MNIST学习softmax regression算法的实现”。
注意:由于我学习机器学习及之前的书写习惯,约定如下:

  • \(X\)表示训练集的设计矩阵,其大小为m行n列,m表示训练集的大小(size),n表示特征的个数;
  • \(W\)表示权重矩阵,其大小是n行k列,n为输入特征的个数,k为输出(特征)的个数;
  • \(\boldsymbol{y}\)表示训练集对应标签,其大小为m行,m表示训练集的大小(size);
  • \(\boldsymbol{y’}\)表示将测试向量\(x\)输入后得到的测试结果;

    总之:
    注意区分这里的:\(\boldsymbol{y'}=XW+\boldsymbol{b}\) 表示矩阵形式的预测结果(\(\boldsymbol{y’}\)\(\boldsymbol{b}\)是向量);
    之前机器学习中的是(如《机器学习实战》中SVM一章):$y’=\omega^T x+b $ 表示向量形式的预测结果(\(y'\)\(b\)是标量);


算法部分:包括预测模型和优化目标

以手写输入MNIST为例:

预测模型

\[ \boldsymbol{y'}=softmax(\boldsymbol{z})=softmax(X \times W + \boldsymbol{b}) \]
其中softmax函数是归一化函数:

\[ softmax(x_i)=\frac{exp(x_i)}{\sum_j exp(x_j)} \]

其中\(i , j\)的范围为1~10。softmax函数将\(\boldsymbol{z}\)归一化之后变为\(\boldsymbol{y’}\)(预测值)。如下图。

  • 训练集:共55000条数据,每条数据中有784个特征(将28*28个像素点进行展开,忽略了像素间的结构关系),矩阵中m=55000,n=784;
  • 参数\(W\)中的元素\(W_{i,j}\)的含义是:第i个像素点在数字j中占的权重,意思是如果很多数字j的实例中都有i,说明像素点i很大可能代表数字j,那么其权重会很大。
  • 参数\(b\)中的元素\(b_{i,j}\)的含义是:第i个像素点在数字j的偏置量,意思是如果大部分数字都是0,则0的特征对应的bias值会很大。

优化目标:交叉熵的最小化

交叉熵:
\[ H_{y}(y')=-\sum{y_i log(y'_i)} \]

其中,
每个batch中的所有预测项的交叉熵的平均值为评价指标。


实现部分

用随机梯度下降优化器对评价指标进行优化。

每次随机选取训练集中的100个子集作为batch(桶)进行训练,共训练1000次。

预测模型的评价

统计准确率。

附代码:

# -*- coding: utf-8 -*-
"""
- [x] Created on Wed Oct 31 21:35:42 2018

@author: ccl
"""
# 下载数据集
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)  # 使用one-hot编码
print(mnist.train.assets.shape, mnist.train.labels.shape)
print(mnist.test.assets.shape, mnist.test.labels.shape)
print(mnist.validation.assets.shape, mnist.validation.labels.shape)


import tensorflow as tf
sess = tf.InteractiveSession()
# 第一步,定义算法公式
x = tf.placeholder(tf.float32, [None, 784])  # 构建占位符,None表示样本的数量可以是任意的
W = tf.Variable(tf.zeros([784, 10]))  # 构建一个变量,代表权重矩阵,初始化为0
b = tf.Variable(tf.zeros([10]))  # 构建一个变量,代表偏置,初始化为0
y_ = tf.nn.softmax(tf.matmul(x, W) + b)  # 构建了一个softmax的模型:y = softmax(Wx + b),y指样本标签的预测值

# 第二步,定义损失函数,选定优化器,并指定优化器优化损失函数
y = tf.placeholder(tf.float32, [None, 10])
# 交叉熵损失函数
cross_entropy = -tf.reduce_mean(tf.reduce_sum(y * tf.log(y_),reduction_indices=[1]))
# 使用梯度下降法最小化cross_entropy损失函数
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

# 第三步,迭代地对数据进行训练
tf.global_variables_initializer().run()
for i in range(1000):  # 迭代次数1000
    batch_xs, batch_ys = mnist.train.next_batch(100)  # 使用minibatch,一个batch大小为100
    train_step.run({x: batch_xs, y: batch_ys})
    if i%100 ==0:
        print("进度:%d%%" % (i//10))

# 第四步,在测试集或验证集上对准确率进行评测
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))  # tf.argmax()返回的是某一维度上其数据最大所在的索引值,在这里即代表预测值和真值
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  # 用平均值来统计测试准确率

# 你会得到大约92%的准确率
print(accuracy.eval({x:mnist.test.assets,y:mnist.test.labels}))
#关闭会话
sess.close()

#### 更进一步

  • 使用InteractiveSession将这个session注册为默认的session,之后的运算都默认跑在这个session里,不同session之间的运算与数据相互独立。
  • 比较
  batch_xs, batch_ys = mnist.train.next_batch(100)  # 使用minibatch,一个batch大小为100
  train_step.run({x: batch_xs, y: batch_ys})

  batch = mnist.train.next_batch(50)
  train_step.run(feed_dict={x: batch[0], y_: batch[1]})

的异同。

本质没有区别:也就是说只要是字典dict形式的写法,就是输入;否则就是输出。

猜你喜欢

转载自www.cnblogs.com/charleechan/p/11435099.html