一、MNIST数据集简介
MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取, 它包含了四个部分:
1.Training set images: train-images-idx3-ubyte.gz (9.9 MB, 解压后 47 MB, 包含 60,000 个样本)
2.Training set labels: train-labels-idx1-ubyte.gz (29 KB, 解压后 60 KB, 包含 60,000 个标签)
3.Test set images: t10k-images-idx3-ubyte.gz (1.6 MB, 解压后 7.8 MB, 包含 10,000 个样本)
4.Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解压后 10 KB, 包含 10,000 个标签)
MNIST 数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST). 训练集 (training set) 由来自 250 个不同人手写的数字构成, 其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员. 测试集(test set) 也是同样比例的手写数字数据.在MNIST训练集中,mnist.train.images是一个形状为[60000,784]的张量,第一个维度用来索引图片,第二个维度用来索引图片的像素点。我们使用的标签数据是“one--hot vector",一个one--向量除了某一个位置的数字是1以外其余的数字全为0。所以mnist.train.labels是一个[60000,10]的数字矩阵。
二、逻辑回归
1.模型
逻辑回归是一个概率,线性分类器。它的参数包含一个权值矩阵
W和一个偏置向量b。分类器将输入向量映射到一系列超平面上,每个超平面对应一个类别。输入向量与超平面的距离反映了输入属于对应类别的概率。
在数学上,一个输入向量x属于类别i(概率变量Y的值)的概率,记为:
2.线性函数
当我们想把输入x转化为标签y的时候,比如,把图像分类成数字,我们会推导出一个函数 y=Wx+b。
x将是我们的像素值列表,y将是对数,对应每一个数字。让我们来看看y = Wx,其中权重W确定x在预测每个y时的影响。
y = Wx允许我们绘出一条直线将数据对应到各自的标签。 然而,这条线必须通过原点,因为当x等于0,y也等于0。
我们希望能够将线从原点移开以适应更复杂的数据。最简单的解决方案是给函数添加一个数字,我们称之为“bias”(偏差)。
3.定义损失函数
训练最优化模型参数,涉及到最小化损失函数。在多类别的分类问题中,很自然的想法是使用负对数似然作为损失函数。这等价于在参数为θ的模型下,最大化数据集D的似然。我们从定义似然L和损失ℓ始:
这里使用的是小批量的概率梯度方法(mini-batches Stochastic Gradient Descent, MSGD)。
三、tensorflow实现逻辑分类
训练神经网络的目的是修改权重和偏差以最好地预测标签。 为了使用权重和偏差,你需要一个可以修改的Tensor。也就是说不能使用tf.placeholder()和tf.constant(),因为那些Tensors不能被修改。所以这里应该使用tf.Variable。
tf.Variable()
x = tf.Variable(5)
tf.Variable类创建了一个具有可以修改的初始值的张量,很像一个普通的Python变量。 该张量在会话中存储其状态,因此您必须手动初始化张量的状态。
使用tf.global_variables_initializer()函数初始化所有可变张量的状态。
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
使用tf.Variable类允许我们改变权重和偏差,但是需要选择一个初始值。如上所示,使用session(会话)调用tf.global_variables_initializer()操作。tf.global_variables_initializer()会返回一个操作,从计算图中初始化所有TensorFlow变量。
用正态分布的随机数初始化权重是一个好的做法。而使权重随机化则有助于避免模型在每次训练时都卡在相同的位置。类似地,从正态分布选择权重可以防止任何一个权重压倒其他权重。
TensorFlow提供了一个tf.truncated_normal()函数从正态分布生成随机数。
tf.truncated_normal()
n_features = 120
n_labels = 5
weights = tf.Variable(tf.truncated_normal((n_features, n_labels)))
tf.truncated_normal()函数返回具有来自正态分布的随机值的张量,该正态分布的幅度与平均值相差不超过2个标准偏差。
由于权重已经帮助防止模型卡住,你不需要再随机化偏差。 在这里最简单的解决方案,将偏差设置为0。
tf.zeros()
_labels = 5
bias = tf.Variable(tf.zeros(n_labels))
tf.zeros()函数返回具有全零的张量。
具体代码如下:
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
print(mnist.train.images.shape, mnist.train.labels.shape)
print(mnist.test.images.shape, mnist.test.labels.shape)
print(mnist.validation.images.shape, mnist.validation.labels.shape)
X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32, [None, 10])
W1 = tf.Variable(tf.truncated_normal([784, 10], stddev=0.1))
b1 = tf.Variable(tf.zeros([10]))
print(b1.shape)
y_ = tf.nn.softmax(tf.matmul(X, W1) + b1)
loss = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(y_), reduction_indices=[1]))
step = tf.train.GradientDescentOptimizer(0.5).minimize(loss)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
costs = []
for i in range(1000):
batch_x, batch_y = mnist.train.next_batch(100)
cost, _ = sess.run([loss, step], feed_dict={X: batch_x, Y: batch_y})
if i % 50 == 0:
costs.append(cost)
correct_prediction = tf.equal(tf.argmax(Y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print("i=", i,"accuracy:", accuracy.eval({X: mnist.test.images, Y: mnist.test.labels}))
plt.xlabel("Iteration")
plt.ylabel("loss")
plt.title("learning_rate=0.3")
plt.plot(costs)
plt.show()
运行结果如下,