文章目录
前言
- 基于表征(Representation)形式的文本匹配、信息检索、向量召回的方法总结(用于召回、或者粗排)
- 文本匹配开山之作-DSSM论文笔记及源码阅读(类似于sampled softmax训练方式思考)
前面两篇关于文本匹配的博客中,都用到了Sampled-softmax训练方法来加速训练,Sampled-softmax简单点来说,就是通过采样,来减少我们训练计算loss时输出层的运算量。从第一篇博客中的不知其然,到后面看到DSSM代码中Sampled softamax的知其然,这篇博客目的是在知其所以然,从Sampled softmax的数学原理思考,为什么DSSM中的训练代码可以这样写,代码还能怎么改进。
这段时间也一直在思考,如何才能不随波逐流,如何才能成为一名独当一面的算法工程师,我想对于一个问题的浅尝辄止肯定是远远不够的,不仅要知其然还要知其所以然,光是读懂这几篇论文是不够的,进一步的要理解代码工程实现,更进一步,去理解代码背后的数学原理,为什么代码这样做一定能保证结果正确或者收敛,了解了这些,我们才能够根据自己的想法去做优化,我想对于现在日益成熟的深度学习,难的可能不是如何实现,而是对于自己的实际场景去调整优化。
上面有点扯远了,回归正题,这篇博客主要基于Tensorflow官方对于Sampled softmax文档,建议大家有问题不懂的时候多看官方文档,写的非常通俗易懂,下面我就说说自己对Sampled Softmax数学原理的理解。
What is Candidate Sampling Tensorflow 官方文档
什么是Sampled Softmax
1、logits与softmax
当我们做分类问题时,假设我们需要分类的类别数为 ∣ L ∣ |L| ∣L∣,那么我们做法通常如下,假设我们的输入为 x x x:
- 神经网络最后一层输出层神经元个数为 ∣ L ∣ |L| ∣L∣,每个神经元输出分别表示各个类别的
logits
, 这里的logits
其实代表的就是各个类别未经归一化的概率分布(也就是加起来不为1),网络就是学习出一个映射 f θ ( x ) = l o g i t s f_{\theta}(x) = logits fθ(x)=logits - 将上述输出的
logits
作为softmax
的输入进行归一化操作,softmax
的输出则是表示各个类别上的概率分布 - 根据这个概率分布计算损失函数,如交叉熵损失
还是采用之前博客中的Query-Doc Softmax作为说明,从logtis
进行softmax
归一化公式如下:
- q , d \bold q,\bold d q,d 表示我们的输入, f θ ( ∗ ) f_{\theta}(*) fθ(∗)表示我们的模型, f θ ( q , d ) f_{\theta}(\bold q,\bold d) fθ(q,d)即是给定 q \bold q q情况下,输出类别为 d \bold d d的
logits
- 我们注意分母中 D \mathcal D D即为所有文档集合,也就是我们的总类别数 ∣ L ∣ |L| ∣L∣
这个公式的具体解释可以参考之前的两篇博客,下面分析一下上面这个公式,下面是重点:
- 当我们类别数非常大时,也就是 D \mathcal D D非常大时,那么我们分母的计算量就会非常大,因为需要在整个类别全集上求和。比如假设我们有100W个文档,那么如果我们不做任何处理,对于每个Query,分母中我们就要计算对这100W个文档的logits,然后求和进行归一化,这样的训练速度我们是不能接受的。Sampled Softmax思想就是,从全部类别集合 D \mathcal D D中采样出一个子集,比如100个,然后在子集上计算logits并进行
softmax
归一化 - 我们如果对每个类别
logits
加上一个与类别无关的常数,结果将不会变化。这个很好理解,当我们对每个logits
均加上同一个常数K
,那么分子分母可以约去这个常数K
,结果不变 - 分母其实是一个归一化因子,如果看过PRML同学应该熟悉,有点类似于指数族分布中的
partition function
,分母与类别无关,因为分母中对整个类别集合进行了求和,给定输入后,分母归一化因子也就确定了。
从上面分析可以知道,我们的关键词是logits
、softmax归一化
。logits
本质上就是未归一化的概率,softmax
目的就是计算归一化因子(分母),对logtis
进行归一化,从而得到一个概率分布。问题就在于需要对整个类别集合 D \mathcal D D计算logtis
并求和,当类别集合比较大时(比如上面的Query-Doc预测,以及语言模型训练),计算量会非常大。
2、Sampled Softmax
Sampled Softmax
的核心思想就在于 Sampled
,既然类别全集太大,那么能不能采样一个类别子集,然后在计算在子集上的logtis
然后进行softmax
归一化呢?假设我们类别全集为 L L L,输入为 ( x , T i ) (x,T_i) (x,Ti),其中 T i T_i Ti就是我们的输入类别标签,那么我们可以在 L L L上随机采样一个子集 S i ⊂ L S_i \subset L Si⊂L,并且与我们的输入类别 T i T_i Ti,共同组成候选类别子集 C i C_i Ci
C i = T i ∪ S i C_i = T_i \cup S_i Ci=Ti∪Si
我们在训练模型时,只要在这个采样出来的 C i C_i Ci上计算logits
和softmax
就可以了,大大减少了计算量,加快训练过程。现在问题是:
- 当我们进行采样之后,各个类别
logits
应该如何计算,和使用类别全集时的logtis
有什么对应关系?
Sampled Softmax背后的数学原理
从上面可以看出,当我们进行采样后,按理来说logtis
计算方法也需要改变,这样才能最后得到正确的概率分布。前方公式预警!!!!
1、数学符号约定
- ( x , t i ) (x,{t_i}) (x,ti) 表示我们的一个训练样本, x x x为输入模型的特征, t i t_i ti为标签,目标类别
- P ( y ∣ x ) P(y|x) P(y∣x) 给定输入 x x x,输出类别为 y y y的条件概率
- F ( x , y ) F(x,y) F(x,y) 给定输入 x