抱怨就像搬起石头砸自己的脚,于人无益,于己不利,于事无补。
全文字数:2448字
阅读时间:12分钟
前言
实战语言模型系列:
a
Softmax层
在介绍完了如何处理数据以及如何构造样本之后,就可以构建我们的神经网络语言模型了,下面是使用LSTM构建的语言模型的大体结构:
▲使用循环神经网络实现自然语言模型的示意图
那可以看出上面着重写出来的两层:
那接下来介绍softmax层。使用循环神经网络训练语言模型,对于每个cell,其实都相当于是一个有监督的多分类任务,每个词汇表中的单词代表一个类别。如下图所示:
▲单步cell示意图
当训练的时候,我们要做的就是使得输出向量和期望向量(样本label)越接近越好,那交叉熵就是评判两个概率分布之间的距离的常用方法之一。然而神经网络的输出确不一定是一个概率分布,所以这就有了softmax,softmax能够将神经网络前向传播的结果变成一个概率分布,其实可以把softmax当成一个额外的处理层,他把神经网络的输出变成了一个概率分布,也就是每一个输出都是(0~1)之间的小数,并且所有输出的结果之和为1。通过这样的处理,我们就可以轻松的使用交叉熵损失函数来计算真实分布与期望分布的距离,并通过梯度下降算法通过降低交叉熵损失以拟合样本训练模型。
下面看一看softmax是怎么计算的:
▲softmax层
现在我的神经网络有四个输出
,那么经过softmax处理后的输出为:
,通过softmax我们可以计算出
的值。
通过上面的描述我们可以知道,加入softmax层是为了将神经网络的输出转换为概率分布,进而使用交叉熵来计算神经网络输出的概率分布和期望的概率分布之间的距离。
对于使用softmax层处理,可以分成两个步骤:
);
b
Softmax与交叉熵
在训练语言模型以及对训练好的语言模型的评估好坏(perplexity实际上也是一个交叉熵)的时候,都会用到交叉熵损失函数。而由于softmax和交叉熵损失函数经常一起使用,所以tensorflow对这两个功能进行了统一的封装,并提供了两个函数(当然你也可以分成两步写,先获得经过softmax层得到的结果,然后放入交叉熵的计算公式中进行计算):
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(lables = y_,logits = y)
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(lables = y_,logits = y)
那这两个函数有什么区别呢,我们现在一个个的介绍:
import tensorflow as tf
word_prob_distribution = tf.constant([[0.0,0.0,1.0,0.0],[1.0,0.0,0.0,0.0]])
#假设模型对两个单词的预测时,产生logits分别是[2.0,-1.0,3.0,2.0],[1.0,0.0,-0.5,4.0]
#这个时候的predict_logits是没有经过softmax层处理的y1,y2,y3,y4
predict_logits = tf.constant([[2.0,-1.0,3.0,2.0],[1.0,0.0,-0.5,4.0]])
#使用softmax_cross_entropy_with_logits
loss = tf.nn.softmax_cross_entropy_with_logits(logits = predict_logits,labels = word_prob_distribution)
sess = tf.InteractiveSession()
print(loss.eval())
sess.close()
'''[ 0.56194139 3.07623076]'''
import tensorflow as tf
#假设词汇表的大小为4,语料中包含两个单词[2,0],单词在词汇表中的ID编号
word_prob_distribution = tf.constant([2,0])
#假设模型对两个单词的预测时,产生logits分别是[2.0,-1.0,3.0,2.0],[1.0,0.0,-0.5,4.0]
#这个时候的predict_logits是没有经过softmax层处理的y1,y2,y3,y4
predict_logits = tf.constant([[2.0,-1.0,3.0,2.0],[1.0,0.0,-0.5,4.0]])
#使用sparse_softmax_cross_entropy_with_logits
loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits = predict_logits,labels = word_prob_distribution)
sess = tf.InteractiveSession()
print(loss.eval())
sess.close()
'''[ 0.56194139 3.07623076]'''
会发现两个函数的输出结果是相同的,那这两个函数的唯一区别就在于表示真实单词分布的不同,在第一个函数中,我们使用one-hot的表示方式,而在第二个函数中我们使用单词在向量中的最大值的位置,从输出的结果相同也可以看出来,这两种表示方式其实是一样的,在我们的样例中在处理文本的时候,只是将其转换为了词汇表中的对应ID号,并没有将其转换为one-hot(其实他们是等价的),因为其实我们可以使用sparse_softmax_cross_entropy_with_logits函数通过对应单词的词汇表的ID编号也可以轻松的得到交叉熵的loss值。
那softmax + 交叉熵有什么效果呢?下面一个使用softmax+交叉熵的三个输出的神经网络计算流程,只需看最后一行,可以看出梯度下降更新的结果:
▲按比例推所有拉一个
顺便说一句,由于softmax层以及embedding层的参数占所有参数的比重很大,所以通常我们共享embedding层以及softmax层的参数,这样不仅可以大幅度的减少参数数量而且还能够提高最终模型的效果。
本文分享自 AI机器学习与深度学习算法 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有