当前位置: 首页 > 科技观察

深度学习库TensorFlow(TF)中的候选抽样

时间:2023-03-19 10:33:56 科技观察

在深度学习的过程中,如果我们要训练一个类别很多的分类器(比如词汇量很大的语言模型),正常的训练过程会要很慢。这是因为所有课程都需要在训练期间进行评估。为了解决这个问题,发明了候选抽样技术,一次只评估所有类别的一小部分。深度学习库TensorFlow(TF)实现了候选采样技术并提供了一些API。1.候选抽样函数候选抽样函数根据一定的原则从庞大的类别库中随机抽取一个类别子集。TF提供了以下候选采样函数,前三个的参数和返回值相同,第四个类似。具体参数和返回值可以移到TF文档中。1.tf.nn.uniform_candidate_sampler统一采样类别的子集。2.tf.nn.log_uniform_candidate_sampler根据对数均匀(Zipfian)分布进行采样。该函数主要用于处理单词作为类别的情况。在语言学中,单词按照出现频率排序后服从Zipfian分布。在使用该功能之前,您需要将类别按频率降序排列。3.tf.nn.learned_unigram_candidate_sampler根据训练数据中的类别分布进行采样。具体实现方法:1)初始化一个[0,range_max]数组,数组元素初始为1;2)训练时遇到类别时,将对应的数组元素加1;3)每次都根据数组归一化得到的概率进行采样。4.tf.nn.fixed_unigram_candidate_sampler根据用户提供的概率分布进行采样。如果类别服从均匀分布,我们使用uniform_candidate_sampler;如果这个词是一个类别,我们知道这个词服从Zipfian,我们使用log_uniform_candidate_sampler;如果我们可以通过统计或者其他渠道知道类别满足一定的分布,我们使用nn.fixed_unigram_candidate_sampler;如果我们真的不知道类别分布,我们也可以使用tf.nn.learned_unigram_candidate_sampler。其实我很好奇tf内部是如何实现快速采样的,尤其是tf.nn.learned_unigram_candidate_sampler的概率分布在变化的时候。我知道最快的采样算法也是O(n)。不知道tf有没有更快的算法。2.候选抽样损失函数候选抽样函数生成类别子集。需要将类别子集送入候选抽样损失函数计算损失,通过最小化候选抽样损失来训练模型。TF提供了以下两种候选采样损失函数。这两个采样损失函数的参数和返回值是一致的,具体参数和返回值可以移到TF文档中。1、函数tf.nn.sampled_softmax_loss传递模型的交叉熵损失。候选类别的子集由样本类别和真实类别组成,即。模型最后一层的输出是将softmax激活函数转化为模型输出的概率得到的。因为只有一个候选类别的子集,而没有完整的类别集L,我们无法计算,然后计算交叉熵损失。对于候选类的子集,我们只能计算。那么如何优化相关的损失函数,我们得到什么呢?.其中K是独立于y的数。我们得到概率计算公式和交叉熵损失。最小化J以训练模型。2.tf.nn.nce_lossNCELoss和SampledSoftmaxLoss的出发点是一样的,都是想做模型输出。它们的区别在于SampledSoftmaxLoss只支持Single-Label分类,而NCE支持Multi-Label分类。候选类别子集由采样类别和groundtruth类别组成,即。对于候选类别子集中的每个类别,建立Logistic二元分类问题,损失函数最小化J来训练模型。3.候选抽样约束很多时候,负类是由问题给出的。例如,我们训练分类器玩扑克游戏,具有以下属性:游戏中有很多可能的动作;对于一副牌来说,所有的可选动作最多只有几百个;对于一副牌,我们选择人类大师的出牌动作为正类,我们将人类大师没有选择的出牌动作作为负样本;根据当前游戏构建的训练样本,正类只有一个,负类最多几百个,由当前游戏决定。上述问题中,不同游戏的候选动作个数不同,我们不能使用候选抽样的方法进行训练。候选抽样只能对相同数量的类别进行抽样。一方面,TF的基本单位是Tensor,要求所有维度保持一致。另一方面,由于候选抽样是针对Word2Vec中的Negativesampling等场景设计的,这些场景只需要选择一些负类就可以体现非正类的特征。4.总结候选抽样加速了类别数量巨大的训练过程。TF提供了候选抽样相关的API供大家使用。【本文为专栏作家“李莉”原创稿件,转载请联系授权】点此查看该作者更多好文