这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战
Word2Vec那一节我们知道了它的缺点是softmax计算起来太慢了,现在我们来看一种改进方法:负采样 | Negative sampling
负采样要做的是建立一个新的监督学习任务。方法主要来源于论文:[1310.4546v1] Distributed Representations of Words and Phrases and their Compositionality (arxiv.org)
从例子引入负采样
给定一对单词。我们要预测是否是一对context - target。
先来获取我们的训练集。
我们需要。寻找一个context word。然后跟上一节一样,在一定的词句之内选择一个target word。
使用例句:
I want a glass of orange juice to go along with my cereal.
比如我们选择orange作为context word,然后选择juice作为target word。
Orange和juice就是我们的正样本。之后我们在词典中进行随机采样,选取K个单词放入表格作为负样本。
context word | word | target? |
---|---|---|
Orange | juice | 1 |
Orange | King | 0 |
Orange | Men | 0 |
Orange | The | 0 |
Orange | Of | 0 |
这里你会发现of其实离orange也非常近,但是不用担心。除了你选取的target word之外,剩下的词可以随机的从字典中取,并且设置为负样本。
在这里我们K选择的是4。
论文中原文作者的建议是,少的数据集K可以取值大一点,大的数据集K就取值小一点。小一点的数据集K取5~20,大一点的取2~5。
对于负样本的选择方法:
你当然可以选择从单词表中使用均匀分布进行随机选取,但是这样随机性实在是太大。所以你可以考虑一下其他的选择方法。比如按照词频来选择。
如果你按照词频从高到低开始选择的话,那你很可能遇到一个问题,就是那些常用的词都是the、of、and之类的。另一个极端是你从低到高开始选择,那你这样会遇到一些特别生僻的词,平时根本就用不太着。
原文的建议是使用:
对于词频的次方除以整体的值进行采样。如果是观测到的语料库中的某个单词,通过计算之后会使其处于均匀分布和训练集的观测分布两个极端之间。
模型:
- 是与输出t有关的参数,即某个输出词汇t和标签相符的概率是多少。
- 是word embedding向量。
- 这里在激活函数使用的是sigmoid。
现在这个问题就转化成了计算target等于1的概率。如果你有K个样本,也可以看作是个正负样本的比例,并将其训练成一个类似于logistic回归的模型。
首先我们是获得一个orange的one-hot向量,之后我们得到的一个word embedding矩阵,再得到一个word embedding向量。下一步不是进入一个softmax,而是将其转换成一万个logistic回归的二分类。
并且我们不是每次都要计算1万个,而是在每次迭代中进行训练K+1个值。这样相比原来要训练1万维度的softmax计算量会小很多。
总结
当词表规模较大且计算资源有限时,之间讲的word2vec模型,不管是skip-gram还是CBOW的训练过程会受到输出层概率归一化(Normalization)计算效率的影响,即在softmax那里出现巨大计算量。负采样方法则提供了一种新的任务视角:给定当前词与其上下文,最大化两者共现的概率。这样一来,问题就被简化为二元分类问题。
拓展
关于负采样,我前几天看了一篇文章,包括静态负采样、强负采样、对抗式负采样等等,有一大堆相关论文提供阅读。因为是我在别人公众号看到的文章也不是我自己写的,大家感兴趣的可以自己去搜一下。