CTR模型中的正负样本构建之负采样

最好的trick就是保证数据精准前提下,如无必要,不要采样。既然数据是模型的上限,就不应该破坏这个上限。

聊聊什么是精准。

很多号称数据清洗的工作,都是工程体系太弱的后果,其实不是算法的问题。比如,没有曝光日志,用了服务端日志,伪曝光做了负样本;没有准确的曝光日志,比如卡片漏出了一个头用户根本没看到就记录了曝光日志,充当了负样本;场景里有引流模块,把用户在场景外的点击强插到前面,这个物品的样本是应当丢掉的,或者在特征上做一些处理,防止把高点击率归因给物品,造成整个模型的溃败。

在精准上,有一个不能称之为trick的常识,就是处理好点击事件的delay。构造CTR样本就是拿曝光日志去join点击日志,无论这这个日志是在批处理平台还是流式计算平台,由于用户点击天然比曝光事件滞后,加上系统本身的延迟,点击日志会比曝光日志晚到,如果按照一个时间戳截断两个日志,会有一些正样本被误认为负样本。如果是天级的样本,23点之后的样本有一些是错的。如果是小时级或流式,曝光日志要delay等待点击日志多久,要好好评估一下,看看等待多久能让绝大多数样本正确。

聊聊什么是必要。

数据量太大,你train不动了,这时候做负样本的下采样,但是绝对没有正向的效果,这也可能是工程体系不够强大的表现。采样稍有不慎,还会造成负向效果。做了采样均值就变了,还要重新矫正预估值,麻烦。

某个用户行为多,要采样怕影响整体分布?采样了才影响整体分布吧,如果数据本身是精准的,我不相信这能有用。

还有人讲,说负样本太多,要采样。假如是1:1k,其实也没什么问题。假如是1:1w,那有一亿个样本里才有1w的正例,这个正例本身就太少太偏,业务上这个指标有意义吗?这个预估不能拆成两个预估的乘积吗?如果都不行,我觉得可能用点规则效果更好。

数据弥足珍贵,如无必要,不要采样,既然数据是模型的上限,就不应该破坏这个上限。好好利用每一条用户反馈,不出错,不乱搞,结硬寨,打呆仗,这往往就是最好的策略。

from 知乎@九老师,https://www.zhihu.com/question/324986054/answer/1746373510
 

负采样 
训练一个神经网络意味着要输入训练样本并且不断调整神经元的权重,从而不断提高对目标的准确预测。每当神经网络经过一个训练样本的训练,它的权重就会进行一次调整。

所以,词典的大小决定了我们的Skip-Gram神经网络将会拥有大规模的权重矩阵,所有的这些权重需要通过数以亿计的训练样本来进行调整,这是非常消耗计算资源的,并且实际中训练起来会非常慢。

负采样(negative sampling)解决了这个问题,它是用来提高训练速度并且改善所得到词向量的质量的一种方法。不同于原本每个训练样本更新所有的权重,负采样每次让一个训练样本仅仅更新一小部分的权重,这样就会降低梯度下降过程中的计算量。

当我们用训练样本 ( input word: “fox”,output word: “quick”) 来训练我们的神经网络时,“ fox”和“quick”都是经过one-hot编码的。如果我们的词典大小为10000时,在输出层,我们期望对应“quick”单词的那个神经元结点输出1,其余9999个都应该输出0。在这里,这9999个我们期望输出为0的神经元结点所对应的单词我们称为“negative” word。

当使用负采样时,我们将随机选择一小部分的negative words(比如选5个negative words)来更新对应的权重。我们也会对我们的“positive” word进行权重更新(在我们上面的例子中,这个单词指的是”quick“)。

PS: 在论文中,作者指出对于小规模数据集,选择5-20个negative words会比较好,对于大规模数据集可以仅选择2-5个negative words。

我们使用“一元模型分布(unigram distribution)”来选择“negative words”。个单词被选作negative sample的概率跟它出现的频次有关,出现频次越高的单词越容易被选作negative words。

每个单词被选为“negative words”的概率计算公式:

在代码负采样的代码实现中,unigram table有一个包含了一亿个元素的数组,这个数组是由词汇表中每个单词的索引号填充的,并且这个数组中有重复,也就是说有些单词会出现多次。那么每个单词的索引在这个数组中出现的次数该如何决定呢,有公式,也就是说计算出的负采样概率*1亿=单词在表中出现的次数。

有了这张表以后,每次去我们进行负采样时,只需要在0-1亿范围内生成一个随机数,然后选择表中索引号为这个随机数的那个单词作为我们的negative word即可。一个单词的负采样概率越大,那么它在这个表中出现的次数就越多,它被选中的概率就越大。

从上述表达式可以看出,负样本我们不需要取所有的都拿来训练,我们只需要每个中心词抽几个负样本就可以了,这样可以大大降低计算的复杂度。这就是word2vec训练过程中的Negative Sampling 负采样技巧,可以大大减小梯度下降的时间复杂度,这就有点像SGD随机梯度下降,就是随机一个样本进行梯度下降,大体的方向还是朝着最低点下降。

拿随机采样做负样本

以下很重要:

 

 

 实现:

 

 

 

 

 

 

posted @ 2021-03-30 21:16  今夜无风  阅读(1853)  评论(0编辑  收藏  举报