Softmax回归

1.Softmax的回归原理

Softmax回归是一个线性的多类分类模型,实际上白是直接从Logistic回归模型转化而来的。区别在于Logistic 回归模型为两类分类模型,而Softmax 模型为多类分类模型。

在手写数字体识别问题中,一共有10个类别(0~9),我们希望对输入的图像计算它属于每个类别的概率。如属于9的概率为70%,属于1的概率为10%等。最后模型预测的接轨就是概率最大的那个类别。

先来了解什么是s。如nax 函数。Softmax 函数的主要功能是将各个类别的“打分”转化成合理的概率值。例如,一个样本可能属于三个类别:第一个类别的打分为a ’第二个类别的打分为b ’第三个类别的打分为c 。打台越高代表属于这个类别的概率越高,但是打分本身不代表概率,因为打分的值可以是负数,也可以很大,但概率要求僵必须在0~ 1 ,并且三类的概率加起来应该等于1。那么,如何将(a, b, c)转换成合理的概率值呢?方法就是使用Softmax 函数。例如,对(a, b, c)使用Softmax 函数后,相应的值会变成这里写图片描述

假设 x x 是单个样本特征,Wb是Softmax模型的参数。在MNIST数据集中, x x 就代表输入图片,它是一个784维的向量,而W是一个矩阵,它的形状为(784, 10), b b <script type="math/tex" id="MathJax-Element-25">b</script>是一个10维的向量,10代表的是类别数。Softmax模型的第一步是通过下面的公式计算各类别的Logit:
这里写图片描述
Logit同样是一个10维的向量,它实际上可以看成样本对应于各类别的“打分”。接下来使用Softmax函数将它转换成各个类别的概率值:
这里写图片描述
Soft模型输出的y代表各个类别的概率,还可以直接用下面的式子来表示种鸽Softmax:
这里写图片描述

2.Softmax回归在TensorFlow中的实现

首先导入Tensor Flow 模块:

# 导入tensorflow。
import tensorflow as tf
# 导入MNIST教学的模块
from tensorflow.examples.tutorials.mnist import input_data
# 读入MNIST数据
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

下面的步骤是非常关键的几步,先来看代码:

# 创建x,x是一个占位符(placeholder),代表待识别的图片
x = tf.placeholder(tf.float32, [None, 784])

# W是Softmax模型的参数,将一个784维的输入转换为一个10维的输出
# 在TensorFlow中,变量的参数用tf.Variable表示
W = tf.Variable(tf.zeros([784, 10]))
# b是又一个Softmax模型的参数,我们一般叫做“偏置项”(bias)。
b = tf.Variable(tf.zeros([10]))

# y=softmax(Wx + b),y表示模型的输出
y = tf.nn.softmax(tf.matmul(x, W) + b)

# y_是实际的图像标签,同样以占位符表示。
y_ = tf.placeholder(tf.float32, [None, 10])

这里定义了一些占位符和变量(Variable)。在TensorFlow中,无论是占位符还是变量,他们实际上都是“tensor”。从TensorFlow的名字中,就可以知道tensor在整个系统处于核心地位。TensorFlow中的Tensor并不是具体的数值,他只是一些我们希望TensorFlow系统计算的“节点”。

这里的占位符和变量是不同类型的Tensor。先来讲解占位符。占位符不依赖于其它的Tensor,,它的值由用户自行传递给TensorFlow,通常用来存储数据和标签。如在这里定义了x = tf.placeholder(tf. float32, [None, 784]),它是用来存储训练图片数据的占位符。宫的形状为[None, 784], None 表示这一维的大小可以是任意的,也就是说可以传递任意张训练图片给这个占位符,每张图片用一个784 维的向量表示。同样的, y_= tf.placeholder(tf.float32,[None, 10])也是个占位符,它存储训练图片的实际标签。

再来看什么是变量。变量是指在计算过程中可以改变的值,每次计算之后的变量值会被保存下来,通常变量值用来存储模型的参数。如果这里创建了两个变量:W = tf.Variable(tf.zeros([784, 10]))、b = tf.Variable(tf.zeros([10]))。它们都是Softmax 模型的参数。创建变量时通常需要指定某些初始值。这里W的初始值是一个784 × 10 的全零矩阵, b 的初始值是一个10 维的0向量。

除了变量和占位符之外,还创建了一个y = tf.nn.softmax(tf.matmul(x, W) + b)。这个y 就是一个依赖x、W 、b 的Tensor 。如果要求TensorFlow 计算y的值,那么系统首先会获取L W 、b 的值,再去计算y 的值。

y实际上定义了一个Softmax回归模型,在此可以尝试写出y 的形状。假设输入x 的形状为(N, 784),其中N 表示输入的训练图像的数目。W 的形状为(784, 10),b 的形状为(10, ) 。那么, Wx + b 的形状是(N, 10) 。Softmax函数不改变结果的形状,所以得到y 的形状为例, 10) 。也就是说, y 的每一行是一个10 维的向量,表示模型预测的样本对应到各个类别的概率。

模型的输出是y ,而实际的标签为y_ , ‘8们应当越相似越好。在Softmax回归模型中,通常使用“交叉摘”损失来衡量这种相似性。损失越小,模型的输出就和实际标签越接近,模型的预测也就越准确。

在TensorFlow 中,这样定义交叉烟损失:

# 至此,我们得到了两个重要的Tensor:y和y_。
# y是模型的输出,y_是实际的图像标签,不要忘了y_是独热表示的
# 下面我们就会根据y和y_构造损失

# 根据y, y_构造交叉熵损失
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y)))

构造完损失之后,下面一步是如何优化损失,让损失减小。这里使用梯度下降法优化损失,定义为

# 有了损失,我们就可以用随机梯度下降针对模型的参数(W和b)进行优化
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

因此程序将使用梯度下降法对W 、b 计算楠度并重新官们的值。
tf.train.GradientDescentOptimizer(0.01 )中的0.01 是梯度下降优化器使用的学习率( Learning Rate )。

在优化前,必须要创建一个会话( Session ),并在会话中对变量进行初
始化操作:

# 创建一个Session。只有在Session中才能运行优化步骤train_step。
sess = tf.InteractiveSession()
# 运行之前必须要初始化所有变量,分配内存。
tf.global_variables_initializer().run()
print('start training...')

会话是TensorFlow的有一个核心概念。前面提到Tensor是“希望”TensorFlow进行计算的节点。而会话就可以看成对这些节点进行计算的上下文。之前还提到过,变量在计算过程中可以改变值得Tensor,同时变量的值会被保存下来。事实上,变量的值就是被保存在会话中的。在对变量进行操作前必须对比那辆进行初始化,实际上是在会话中保存变量的初始值。初始化所有变量的语句是tf.global_variables_initializer().run()

有了会话,就可以对变量W 、b 进行优化了,优化的程序如下:

# 进行1000步梯度下降
for _ in range(1000):
    # 在mnist.train中取100个训练数据
    # batch_xs是形状为(100, 784)的图像数据,batch_ys是形如(100, 10)的实际标签
    # batch_xs, batch_ys对应着两个占位符x和y_
    batch_xs, batch_ys = mnist.train.next_batch(100)
    # 在Session中运行train_step,运行时要传入占位符的值
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

每次不使用全部训练数据,而是每次提取100 个数据进行训练,共训练1000 次。batch_xs, batch ys 分别是100 个训练圄像及其对应的标签。在训练时,需要把芭们放入对应的占位符x, y中,对应的语句是feed dict={x:
batch_ xs, y_: batch ys } 。

在会话中,不需要系统计算占位符的值,而是直接把占位符的值传递给会话。与变量不同的是,占位符的值不会被保存,每次可以给占位符传递不同的值。

运行完梯度下降后,可以检测模型训练的结果,对应的代码如下:

# 正确的预测结果
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
# 计算预测准确率,它们都是Tensor
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# 在Session中运行Tensor可以得到Tensor的值
# 这里是获取最终模型的正确率
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))  # 0.9185

模型预测y 的形状是(N, 10 ) , 而实际标签y_B~形状是(N, 10),冥中N 为
输入模型的样本个数。tf.argmax(y, 1),、tf.argmax(y_, 1)的功能是取出数组中
最大值的下标,可以用来将独热表示以及模型输出转焕为数字标签。假设传
入四个样本,它们的独热表示y_为(需要通过sess . run(y_) 才能获取此Tensor
的值,下同):

[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

tf.argmax(y_, 1)就是

[0, 2, 9, O]

也就是说,取出每一行最大值对应的下标位置,他们是输入样本的实际标签。假设此时模型的预测输出y为:

[[0.91, 0.01, 0.01, 0.01, 0.01 , 0.01, O.010.01, 0.01, 0.01],
 [0.91, 0.01, 0.01, 0.01, 0.01 , 0.01, O.010.01, 0.01, 0.01],
 [0.91, 0.01, 0.01, 0.01, 0.01 , 0.01, O.010.01, 0.01, 0.01],
 [0.91, 0.01, 0.01, 0.01, 0.01 , 0.01, O.010.01, 0.01, 0.01]]

tf.argmax(y_, 1)就是

[0, 0, 0, 0]

得到了预测的标签和实际标签,接下来通过tf.equal 函数来比较它们是否相等,并将结果保存到correct_prediction 中。在上述例子中,correct_prediction 就是:

[True, False, False, True]

即第一个样本和最后一个样本预测是正确的,另外两个样本预测错误。可以用tf.cast(correct_prediction, tf. float32 )将比较值转换成float32 型的变量,此时True 会被转换成1 , False 会被转接成0 。在上述例子中,tf.cast(correct_prediction, tf.float32 )的结果为:

[1., 0., 0., 1.]

最后,用tf.reduce_mea n 可以计算数组中的所高元素的平均值,相当于得到了模型的预测准确率,如[1., 0., 0., 1.]的平均值为0.5 ,即50% 的分类准确率。

在程序softmax_regression. py 中,传入占位符的值是feed_dict={x:
moist.test.images, y : mnist.test.labels }。也就是说,使用全体测试样本进行测
试。测试图片一共高10000 张,运行的结果为0.9185 ,即91.85% 的准确率。
因为Softmax 回归是一个比较简单的模型,这里预测的准确率并不高,在下
一节将学习如何使用卷积神经网络将预测的准确率提高到99% 。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值