宁雨 http://ningyuwhut.github.io 2023-07-31T00:38:29+00:00 ningyuwhut@gmail.com candidate sampling http://ningyuwhut.github.io/cn/2023/06/candidate-sampling/ 2023-06-16T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2023/06/candidate-sampling 本文是对Candidate Sampling的翻译和整理

假设我们面临一个多分类或者多标签问题,类别集合为L。每个训练样本表示为\((x_i, T_i)\), \(x_i\)表示上下文(特征)向量,\(T_i\)为样本所属的类别(类别可以是一个集合set或者multiset)。比如给定句子前面的单词去预测下一个单词是什么(或者接下来的单词集合)。

我们希望可以学习一个函数\(F(x,y)\),该函数表示在给定上下文向量\(x\)时类别y的概率。

穷举式的训练方法是LR或者softmax,这需要我们对L中的所有类别都要计算\(F(x,y)\),当L数量很大时,计算成本会很高。

Candidate Sampling 解决该问题的方式是构造一个训练任务,对于每个训练样本\((x_i, T_i)\),我们只对一小部分候选类别\(C_i \in L\)计算\(F(x,y)\)。通常,候选类别\(C_i\)除了目标类别\(T_i\)之外,还包括随机采样的其他类别集合\(S_i \in L\),即 \(C_i = T_i \cup S_i\)。\(S_i\)的随机选取可能依赖也可能不依赖\(x_i\)和\(T_i\)。

我们使用神经网络作为训练模型,代表\(F(x,y)\)的那一层可以通过对损失函数的反向传播来训练。

Table of Candidate Sampling Algorithms

说明如下:

\(Q(y\vert x)\)是给定上下文x的情况下类别y在根据采样算法采样出来的类别集合中的概率(或者叫expect count)。

\(K(x)\)是不依赖候选类别的任意函数。因为Softmax包含了一个归一化项,所以加入这一个函数并不影响计算出来的概率。

logistic training loss

\[\begin{aligned} &-\sum_{i}(\sum_{y \in POS_i} log(\sigma(G(x_i, y))) +\sum_{y \in NEG_i} log(1-\sigma(G(x_i, y)))) = \\ &\sum_{i}(\sum_{y \in POS_i} log(1+exp(-G(x_i,y)) )+\sum_{y \in NEG_i} log(1+exp(G(x_i,y)) )) \end{aligned}\]

这是当y取1和-1时的logistic损失函数。

softmax training loss

\[\begin{aligned} &\sum_{i}(-log(\frac{exp(G(x_i,t_i))}{\sum_{y \in POS_i \cup NEG_i} exp(G(x_i,y))})) = \\ &\sum_{i}(-G(x_i,t_i) + log {\sum_{y \in POS_i \cup NEG_i} exp(G(x_i,y))}) \end{aligned}\]

NCE和负采样都可以扩展到T是一个multiset的场景。此时,\(P(y\vert x)\)表示\(T_i\)中y的期望数量(expected count)。类似地,NCE,负采样和Sampled Logistic 也可以扩展到 \(S_i\)是一个multiset的场景。此时,\(Q(y\vert x)\)表示\(S_i\)中y的期望数量。

问题: multiset是啥,在实际实现时有什么区别

Sampled Softmax

假设我们有一个单标签(single-label)问题。每个训练样本\((x_i,\{t_i\})\)包含一个上下文向量和一个目标label。\(P(y\vert x)\)表示给定上下文是x时目标类别是y的概率。

我们要训练一个函数\(F(x,y)\)来输出softmax logits,也就是给定上下文后目标类别的相对对数概率(relative log probabilities)。

\[F(x,y) = log(P(y|x)) + K(x)\]

\(K(x)\)是不依赖y的任意函数。

在完整的softmax训练中,对每个训练样本\((x_i,\{t_i\})\),我们需要计算L中所有类别\(y\)的logits \(F(x, y)\)。 当L中类别很多时这个计算成本会很高。

在Sampled Softmax中,每个训练样本\((x_i,\{t_i\})\)都根据采样函数\(Q(y\vert x)\)从L中采样一个负类集合\(S_i\)。L中的每个类别\(y\)都以概率\(Q(y\vert x)\)相互独立地包含在\(S_i\)中。

\[P(S_i = S | x_i) = \prod_{y\in S} Q(y|x_i) \prod_{y\in {L-S}}(1-Q(y|x_i))\]

假设候选类别集合\(C_i\)包含了正类和所有采样得到的负类

\[C_i = S_i \cup \{t_i\}\]

我们的任务就变成了在给定候选类别集合\(C_i\)的情况下,\(C_i\)中的哪个类别是目标类别。

对\(C_i\) 中的每个类别\(y\) ,我们需要计算在给定\((x_i,C_i)\)的条件下,y是目标类别的后验概率,记为\(P(t_i = y\vert x, C_i)\)。

根据贝叶斯公式:

\[\begin{aligned} P(t_i = y|x_i, C_i) &= \frac{P(t_i = y, C_i|x_i)} { P(C_i\vert x_i)}\\ &= \frac{P(t_i = y|x_i) P(C_i|t_i= y, x_i)}{P(C_i\vert x_i)}\\ &= \frac{P(y|x_i) P(C_i|t_i= y, x_i)}{P(C_i\vert x_i)}\\ \end{aligned}\]

现在来计算\(P(C_i\vert t_i = y, x_i)\), \(S_i\)可以包含也可以不包含y,但是必须包含\(C_i\)中的其他类别,必须不包含不在\(C_i\)中的其他类别。

所以有

\[\begin{aligned} P(t_i = y|x_i, C_i) &= \frac{P(y|x_i) \prod_{y'\in{C_i-{y}}}Q(y'|x_i) \prod_{y'\in(L-C_i)}(1-Q(y'|x_i))}{P(C_i|x_i)} \\ &=\frac{\frac{P(y|x_i)}{Q(y|x_i)} \prod_{y'\in{C_i}}Q(y'|x_i) \prod_{y'\in(L-C_i)}(1-Q(y'|x_i))}{P(C_i|x_i)} \\ &=\frac{\frac{P(y|x_i)}{Q(y|x_i)}}{K(x_i, C_i)} \end{aligned}\]

\(K(x_i, C_i)\)是不依赖y的函数。所以

\[log(P(t_i=y |x_i, C_i)) = log(P(y|x_i)) - log(Q(y|x_i)) + K'(x_i, C_i)\]

这个就是输入给softmax 函数的logits,该softmax函数预测C中的哪个候选类别是正类。

softmax:

\[P(t_i=y |x_i, C_i) = softmax(\theta_i) = \frac{exp ( \theta_i)} {\sum_{j=1}^V exp(\theta_j)}\]

log softmax:

\[log\ P(t_i=y |x_i, C_i) = log\ softmax(\theta_i) = \theta_i - log {\sum_{j=1}^V exp(\theta_j)}\]

\(\theta_i\)就是输入给softmax函数的logits,也就是\(log(P(y\vert\ x_i)) - log(Q(y\vert\ x_i))+ K'(x_i, C_i)\),后面的\(K'(x_i, C_i)\)由于和目标类别无关,是一个公共项,可以从softmax中提取出去,所以输入给softmax 的logits也就变成了\(log(P(y\vert\ x_i)) - log(Q(y\vert\ x_i))\)。

因为我们训练函数\(F(x,y)\)来近似\(log(P(y\vert x))\),我们用DNN中的一层隐藏层来表示\(F(x,y)\),减去\(log(Q(y\vert x))\),把结果作为softmax函数的输入。

即:

\[Training\ Softmax\ Input = F(x, y) − log(Q(y|x))\]

Noise Contrastive Estimation(NCE)

每个训练样本\((x_i,T_i)\)包含一个上下文向量和一个目标类别集合。\(T_i\)可能只包含一个类别,也可能是一个集合(set),为了一般性这里使用multiset。

\(P(y\vert x)\)还是表示在给定上下文向量的条件下目标类别集合中某个类别的expected count。如果目标类别集合中没有重复元素,那么\(P(y\vert x)\)是一个概率。

\[P(y\vert x) = E(T(y) \vert x)\]

我们需要训练一个函数\(F(x,y)\)来近似给定上下文向量时目标类别集合中某个类别的expected count,当目标类别集合没有重复元素时,近似的就是log概率\(log(P(y\vert x))\)。

\[F(x,y) = log(P(y|x))\]

对每个样本\((x_i, T_i)\),我们挑选一个采样类别集合\(S_i\),这个类别集合是一个multiset,也就是集合中的元素存在重复。一般情况下集合中的类别是无重复的,这里为了一般性集合中的元素可重复。采样算法依赖不依赖\(x_i\)都可以,但是不会依赖\(T_i\)。 我们构造一个multiset集合\(C_i = T_i + S_i\),包含了所有的正类和采样得到的负类集合。

我们的训练任务是从所有候选采样类别中区分出真正的类别。对于正类集合\(T_i\)中的每个类我们都有一个正样本,对于采样的负类集合\(S_i\)中的每个类我们都有一个负样本。

我们用\(Q(y\vert x)\)表示采样后的类别集合中某个类别的期望次数。如果\(S\)不包含重复元素,那么\(Q(y\vert x)\)就是一个概率。

\[Q(y\vert x) := E(S(y)|x)\]

对数几率如下:

\[log\ odds (y 来自 T\ vs\ S\ \vert x) = log \frac{P(y|x)}{Q(y|x)} = log(P(y|x)) - log(Q(y|x))\]

\(log(P(y\vert x))\)我们通过训练\(F(x,y)\)来近似,DNN中的一个隐层表示\(F(x,y)\)。加上第二项\(-log(Q(y\vert x))\),这一项可以有解析解,然后把结果作为logistic函数的输入,label表示y来自于T还是S。

\[Logistic\ Regression\ Input = F(x, y) − log(Q(y|x))\]

也是通过DNN的反向传播来训练\(F(x,y)\)。

这里说下为什么用log odds,因为在LR中,log odds得到的就是线性部分的值,也就是LR的输入。

这里也可以看到,NCE中负采样中是可以包含正类的。

Negative Sampling

这个是NCE的简化版本,在训练时忽略掉\(-logQ(y\vert x)\)这一项。所以F(x,y)用来近似\(log(E(y\vert x) - log(Q(y\vert x)))\)。

值得注意的是,这里我们优化\(F(x,y)\)用来近似依赖于采样分布\(Q(y\vert x)\)的某个量,会导致结果高度依赖采样分布的选择,而其他算法并没有这个问题。

Sampled Logistic

这个是NCE的一个变体,区别在于采样过程中丢弃了刚好是目标类别的采样。(这里的without replacement 是不放回采样,但是不太明白这里的影响是啥,这里应该是说采样时是无放回的,所以采样到的类别是不会重复的),这就要求\(T_i\)是一个集合,而不是multiset,当然\(S_i\)可以是 一个multiset。这样,我们学习到的其实是一个类别的log odds,而不是log-probability(区别是啥?)。具体的数学表达式也就从NCE的形式变成了如下形式:

\[log\ odds(y\ 来自\ T\ vs\ (S − T) | x) = log \frac{P(y|x)}{Q(y|x)(1−P(y|x)}) = log(\frac{P(y|x)}{1-P(y|x)}) - log(Q(y|x))\]

分母中的\(Q(y\vert x)\)表示从S中采样得到类别y的概率,\(1-P(y\vert x)\)表示S中是不不包含类别\(y\)的。

此时,F(x,y)要预估的量就变成了\(log\frac{P(y\vert x)}{1-P(y\vert x)}\)。

\[Logistic\ Regression\ Input = F(x, y) − log(Q(y|x))\]

Context‐Specific vs. Generic Sampling

上面讨论的采样算法可以依赖于上下文。对于某些模型来说,上下文相关的采样可能会很有用,这样可以产生依赖上下文的hard negative,提供更有用的训练信息。到目前位置,这些算法的作者只关注使用通用采样算法比如均匀采样或者unigram采样,没有考虑利用上下文信息。

Batchwise Sampling

上述算法对于一个batch内的样本都使用相同的采样结果。这有点反直觉,因为按照直觉来说每个样本使用不同的采样结果会收敛更快。而现在整个batch使用相同的采样结果的原因主要是计算效率上的考虑。

在我们的模型中,F(x,y)是通过上下文的特征向量(神经网络的最后一个隐层)和类别的embedding向量的内积来计算的。多个特征向量和多个embedding向量之间的内积是通过矩阵乘法计算的, 在现在的硬件尤其是GPU上速度很快。在batch维度执行这个操作即使使用成百上千个采样类别也不会有显著的速度下降。

另外一个原因是不同设备之间拉取类别的embedding向量的开销比计算成百上千的特征向量的内积要高。 参考:

https://www.tensorflow.org/extras/candidate_sampling.pdf

https://www.zhihu.com/question/50043438

]]>
KKT条件 http://ningyuwhut.github.io/cn/2021/08/KKT-condition/ 2021-08-15T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/08/KKT-condition https://zhuanlan.zhihu.com/p/32429623

]]>
Dice 激活函数 http://ningyuwhut.github.io/cn/2021/08/Dice-activation/ 2021-08-15T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/08/Dice-activation 由于relu激活函数在输出值小于0时梯度为零,此时参数就不会得到更新,导致神经元dead问题,为了解决该问题,出现了Leaky ReLU激活函数。改动点是将小于0的部分给予一个很小的斜率,保证梯度不为0。但是这个斜率是固定的,属于超参。PReLu 相比Leaky ReLu的改动点是自适应的学习这个斜率。 三种激活函数的图形如下:

prelu

prelu 公式如下:

prelu

以上三种激活函数都在原点作为分界点。这一点其实也是可以进行优化的,这个分界点其实也应该是根据数据自适应调整的。在DIN模型中,Dice激活函数就是为了解决这个问题提出来的。

Dice的表达式如下:

image

\(f(s)\)就是Dice激活函数了。和PReLu相比,多了一个\(p(s)\),这是一个概率值,对于大于0和小于0两种情况下的输出值进行加权。而这个概率值就是通过batch normalization学习到的。

]]>
EE http://ningyuwhut.github.io/cn/2021/07/EE/ 2021-07-08T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/07/EE https://zhuanlan.zhihu.com/p/32429623

]]>
xgboost 调参 http://ningyuwhut.github.io/cn/2021/06/xgboost-parameter-tuning/ 2021-06-29T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/06/xgboost-parameter-tuning xgboost的官方文档中,参数分成了三类,下面对三类参数做简要的介绍,由于参数太多,所以只介绍了比较常见的几个,具体可以参考官方文档。

1.通用参数:

booster [default = gbtree] 还有gblinear。

nthread

num_pbuffer

num_feature

2.学习任务参数

这里参数比较少,放到前面来。

objective

reg : linear,线性回归

reg : logistic,逻辑回归

binary : logistic,使用LR二分类,输出概率

binary : logitraw,使用LR二分类,输出Logistic转换之前的分类得分 。

eval_metric

验证集上的评价指标,比如rmse、mae、error、logloss、auc等

3.booster参数

这里的参数是调参的重点

比较重要的有

eta:学习率
gamma:特征分割时损失函数下降的阈值
max_depth:树的最大深度
min_child_weight:叶子节点的最小权重和
subsample:行采样
colsample_bytree, colsample_bylevel, colsample_bynode:列采样
colsample_bytree:每棵树采样的特征比重
colsample_bylevel:每棵树的每一层分裂时采样的特征比重
colsample_bynode:树的每个节点分裂时采样的特征比重
lambda:L2正则系数
alpha:L1正则系数
tree_method: exact 表示精确查找,aprrox表示近似,hist表示使用直方图,Lightgbm同样使用该方法
grow_policy:按层生长或者按叶子生长

调参

下面的内容主要翻译自complete-guide-parameter-tuning-xgboost-with-codes-python

1.刚开始选择一个相对较高的学习率,比如通常设置为0.1就可以,可以根据问题的不同在0.05到3之间进行调整。然后确定在当前学习率下的最优弱分类器数量。
xgboost有一个cv函数在每次迭代时进行交叉验证,最终返回最优的决策树数量
2.确定学习率和决策树数量后,调整boosting参数(包括max_depth, min_child_weight, gamma, subsample, colsample_bytree),
3.调整正则化参数(lambda、alpha)
4.降低学习率并确定最佳参数

下面是摘自文中的调参示例:

1.根据默认参数确定最优迭代次数
2.确定最大深度和叶子节点最小权重
3.确定gamma(分裂时损失函数下降的最小值)
4.确定采样相关参数
5.确定正则化参数
6.减小学习率,提高最大迭代次数

参考:

https://xgboost.readthedocs.io/en/latest/parameter.html

https://www.analyticsvidhya.com/blog/2016/03/complete-guide-parameter-tuning-xgboost-with-codes-python/

https://ask.hellobi.com/blog/ai_shequ/33676

https://snaildove.github.io/2018/12/18/get_started_feature-engineering/

https://zhuanlan.zhihu.com/p/196213786

]]>
价格挤压因子 http://ningyuwhut.github.io/cn/2021/06/price-squash-factor/ 2021-06-25T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/06/price-squash-factor 《计算广告》中有提到价格挤压因子,具体形式是在ecpm的ctr上加了一个指数因子:

\[ctr^k * bid\]

并提到:

当k趋近于无穷时,相当于只根据点击率来排序;为0时,相当于只根据出价来排序。

也就是k越大,ctr的影响越大,出价对ecpm的影响越小,从而对出价具有挤压作用。

关于挤压因子的作用,书中论述如下:

价格挤压因子的作用主要是能够根据市场情况更主动地影响竞价体系向着需要的方向发展。比如说,如果发现市场上存在大量的出价较高但品质不高的广告主,则可以通过调高κ来强调质量和用户反馈的影响;如果发现市场的竞价激烈程度不够,则可以通过降低κ来鼓励竞争,如果存在短期的财务压力,这样就可以短期使得整体营收有所上升;如果为了鼓励广告主提高广告质量和相关性,则可以通过提高κ来降低出价的影响。 刘鹏; 王超. 计算广告:互联网商业变现的市场与技术 (Kindle位置1850). 人民邮电出版社. Kindle 版本.

我的疑问是k越大,ctr项越小,为啥在ecpm的作用会越大?这个看起来很反直觉,不过,仔细想一下也就明白了。虽然在ecpm里面权重变小了,但是竞价是在多个广告之间进行的,指数运算会拉大底数之间的距离,导致本来大一点的ctr经过指数运算之后会比之前大很多,从而在竞价中ctr的作用更大。 举个例子吧,给的两个广告,一个ctr=0.5,bid=3,一个ctr=0.6,bid=1。那么我们将价格挤压因子慢慢调大,看下效果:

image

红色曲线是ctr=0.5在不同挤压因子下的值,绿色为ctr=0.6在不同挤压因子下的值。蓝色为0.6和0.5在不同挤压因子下的比值。可以看到,挤压因子越大,ctr=0.6和ctr=0.5的比值越来越大,也就是ctr=0.6对应的ecpm比ctr=0.5对应的ecpm大的越多,这样本来排在ctr=0.5后面的,现在就可以排在前面了。

结合这个图就可以理解价格挤压因子的作用了。

代码如下:

import math
from matplotlib import pyplot as plt
import numpy as np
f = lambda x: math.pow(0.5,x)
f1 = lambda x: math.pow(0.6,x)
x = np.linspace(0, 10, 100)
y_3 = [f(x_i) for x_i in x]
y_4 = [f1(x_i) for x_i in x]
y_5 = [f1(x_i)/f(x_i) for x_i in x]
plt.plot(x, y_3, 'r')
plt.plot(x, y_4, 'g')
plt.plot(x, y_5, 'b')
plt.show()
]]>
时间序列预估 http://ningyuwhut.github.io/cn/2021/06/time-series-forecast/ 2021-06-22T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/06/time-series-forecast 简单指数平滑

适用于没有趋势和周期性的数据

过去所有时刻的数据的加权平均。权重是随着时间推移指数衰减的,即离当前时刻越远,权重越小。

衰减的速度由平滑参数\(\alpha\)控制。该值越大,说明距离近的时刻权重越大,反之,越小。

\[\begin{equation} \hat{y}_{T+1|T} = \alpha y_T + \alpha(1-\alpha) y_{T-1} + \alpha(1-\alpha)^2 y_{T-2}+ \cdots, \tag{7.1} \end{equation}\]

另一种表达形式:

\[\begin{align*} \text{Forecast equation} && \hat{y}_{t+h|t} & = \ell_{t}\\ \text{Smoothing equation} && \ell_{t} & = \alpha y_{t} + (1 - \alpha)\ell_{t-1}, \end{align*}\]

带有趋势的时间序列预估,又叫二阶指数平滑

\[\begin{align*} \text{Forecast equation}&& \hat{y}_{t+h|t} &= \ell_{t} + hb_{t} \\ \text{Level equation} && \ell_{t} &= \alpha y_{t} + (1 - \alpha)(\ell_{t-1} + b_{t-1})\\ \text{Trend equation} && b_{t} &= \beta^*(\ell_{t} - \ell_{t-1}) + (1 -\beta^*)b_{t-1}, \end{align*}\]

\(\ell_t\)是在t时刻该时间序列的水平的估计值,\(b_t\)是t 时刻的趋势(斜率)的估计,\(\alpha\)是水平方向的平滑参数,\(\beta\)是趋势的平滑参数。

holt-winter算法(三阶指数平滑)

\[\begin{align*} \hat{y}_{t+h|t} &= \ell_{t} + hb_{t} + s_{t-m+h_{m}^{+}} \\ \ell_{t} &= \alpha(y_{t} - s_{t-m}) + (1 - \alpha)(\ell_{t-1} + b_{t-1})\\ b_{t} &= \beta^*(\ell_{t} - \ell_{t-1}) + (1 - \beta^*)b_{t-1}\\ s_{t} &= \gamma (y_{t}-\ell_{t-1}-b_{t-1}) + (1-\gamma)s_{t-m}, \end{align*}\] \[\begin{align*} \hat{y}_{t+h|t} &= (\ell_{t} + hb_{t})s_{t-m+h_{m}^{+}} \\ \ell_{t} &= \alpha \frac{y_{t}}{s_{t-m}} + (1 - \alpha)(\ell_{t-1} + b_{t-1})\\ b_{t} &= \beta^*(\ell_{t}-\ell_{t-1}) + (1 - \beta^*)b_{t-1} \\ s_{t} &= \gamma \frac{y_{t}}{(\ell_{t-1} + b_{t-1})} + (1 - \gamma)s_{t-m} \end{align*}\]

ARIMA

http://www.dathinking.com/cn/2014/05/Exponential-Smoothing/

https://otexts.com/fppcn/holt.html

]]>
几种特征处理方法 http://ningyuwhut.github.io/cn/2021/06/feature-engineering/ 2021-06-18T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/06/feature-engineering 1.coec特征

coec即click over expected click,可以用来处理某些bias问题,比如最简单的位置偏置。 以解决位置偏置的coec为例,假设计算广告商家的coec,先统计每个位置上的点击率,然后广告商家在每个位置上的曝光乘以各个位置上的点击率,得到广告商家的期望点击数,最后,广告商家的实际点击数除以期望点击数就是coec的ctr了。通过这种方式计算出来的ctr,去除了位置的影响,之前因为位置排名靠前而导致ctr虚高的广告商家的coec特征就会变低,而因为位置排名靠后而导致ctr偏低的广告商家的coec特征就会变高,更能反映真实的广告质量。

coec的分母是期望点击数,其实是一个基于总体统计出来的点击数均值,而coec就是衡量当前商家的点击数相对总体点击均值的比值。该值越大,说明该商家在总体上的排名越靠前。

2.特征平滑

主要是贝叶斯平滑

贝叶斯平滑的公式如下:

\[\hat \gamma = \frac{C+\alpha}{I+\alpha + \beta}\] \[\alpha = \overline X(\frac{\overline X(1-\overline X)}{S^2}-1)\] \[\beta = (1-\overline X)(\frac{\overline X(1-\overline X)}{S^2}-1)\]

\(\overline X\)为均值,\(S^2\)为样本方差

看了一下,

参考:

http://www.cs.cmu.edu/~xuerui/papers/ctr.pdf

https://blog.csdn.net/jinping_shi/article/details/78334362

]]>
word2vec的tf实现 http://ningyuwhut.github.io/cn/2021/04/word2vec-tf/ 2021-04-08T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/04/word2vec-tf nce loss : https://github.com/tensorflow/tensorflow/blob/v1.15.0/tensorflow/python/ops/nn_impl.py

nce loss 也是为了解决输出层使用softmax计算所有候选word的概率时效率过低的问题。他把基于softmax的一个超大规模的分类问题转换为少量类别的二分类。具体来说,对于一个窗口中的某个中心词,其中的context word为正样本,全局随机负采样几个word作为负样本。然后分别计算正样本和负采样出来的几个负样本为正样本的概率,并计算交叉熵损失。这就是NCE Loss了。

tensorflow中还有一种实现,就是sampled_softmax_loss。这个和nce loss的区别在于这个不再是二分类了,而是一个类别数目变小了的softmax。

这两个损失都只在训练时这么用,在测试和评估时计算完整的sigmoid交叉熵或者softmax损失。

因为这两个损失是为了加速训练,减少计算量,在评估或者测试时我们还是需要计算所有候选类别的概率,在所有类别中选择最优的。

]]>
EGES http://ningyuwhut.github.io/cn/2021/03/EGES/ 2021-03-21T00:00:00+00:00 宁雨 http://ningyuwhut.github.io/cn/2021/03/EGES 代码:https://github.com/wangzhegeek/EGES

]]>