Keras Word2Vec子采样——实现

Keras Word2Vec子采样——实现,keras,word2vec,tf.keras,subsampling,Keras,Word2vec,Tf.keras,Subsampling,我正在Pytorch和Tensorflow2中实现该模型。我对频繁单词的二次抽样的实施有疑问。从论文中逐字计算,对单词wi进行二次抽样的概率为 其中,t是一个自定义阈值(通常是一个小值,如0.0001),而f是文档中单词的频率。尽管作者以一种不同但几乎相同的方式实现了它,但让我们坚持这个定义 当计算p(wi)时,我们可以得到负值。例如,假设我们有100个单词,其中一个单词的出现频率比其他单词高(我的数据集就是这样) 将numpy导入为np 导入seaborn作为sns np.random.se

我正在Pytorch和Tensorflow2中实现该模型。我对频繁单词的二次抽样的实施有疑问。从论文中逐字计算,对单词
wi
进行二次抽样的概率为

其中,
t
是一个自定义阈值(通常是一个小值,如0.0001),而
f
是文档中单词的频率。尽管作者以一种不同但几乎相同的方式实现了它,但让我们坚持这个定义

当计算
p(wi)
时,我们可以得到负值。例如,假设我们有100个单词,其中一个单词的出现频率比其他单词高(我的数据集就是这样)

将numpy导入为np
导入seaborn作为sns
np.random.seed(12345)
#在[1,20]中生成计数
计数=np.random.randint(低=1,高=20,大小=99)
#加上一个非常大的数字
计数=np.插入(计数,0,100000)
#计算频率
f=计数/计数。总和()
#在纸上定义阈值
t=0.0001
#如本文所述计算概率
probs=1–np.sqrt(t/f)
sns.distplot(probs);
Q:使用这种“概率”进行二次抽样的正确方法是什么

作为补充信息,我在函数
keras.preprocessing.sequence.make_sampling_table
中看到了不同的方法:

def制造取样表(尺寸、取样系数=1e-5):
“”“生成基于词列的概率抽样表。”。
用于为'skipgrams'生成'sampling_table'参数。
`抽样表[i]`是抽样的概率
数据集中第i个最常见的单词
(为了平衡起见,应减少对更常见词语的抽样频率)。
采样概率是根据
对于word2vec中使用的采样分布:
```
p(字)=(最小值1,sqrt(字频率/采样系数)/
(单词频率/采样系数)
```
我们假设词频遵循Zipf定律(s=1)推导
频率(秩)的数值近似值:
`频率(秩)~1/(秩*(对数(秩)+伽马)+1/2-1/(12*秩))`
其中'gamma'是Euler-Mascheroni常数。
#论据
大小:Int,要采样的可能字数。
采样系数:word2vec公式中的采样系数。
#返回
长度为'size'的一维Numpy数组,其中第i个条目
是一个等级为i的单词被抽样的概率。
"""
伽马=0.577
等级=np.arange(尺寸)
秩[0]=1
inv_fq=秩*(np.log(秩)+伽马)+0.5-1./(12.*职级)
f=抽样系数*投资额
返回np.最小值(1,f/np.sqrt(f))

我倾向于相信已部署的代码而不是书面报告,特别是在像word2vec这样的情况下,在这种情况下,由论文作者发布的原始作者的版本已被广泛使用,并被用作其他实现的模板。如果我们看看它的子采样机制

if(示例>0){
实数ran=(sqrt(vocab[word].cn/(sample*train\u words))+1)*(sample*train\u words)/vocab[word].cn;
下一个随机=下一个随机*(无符号长-长)25214903917+11;
如果(ran<(next_random&0xFFFF)/(real)65536)继续;
}
…我们看到,那些具有微小计数(
.cn
)的单词在原始公式中可能给出负值,而在这里给出的值大于
1.0
,因此永远不能小于
长的
-随机屏蔽并缩放到永远不会超过
1.0
(next_random&0xFFFF)/(real)65536
)。因此,作者的意图似乎是让原始公式中的所有负值都表示“永不放弃”

根据keras
make_sampling_table()
comment&implementation,他们根本没有咨询实际的词频。取而代之的是,他们假设一个基于词序的Zipf分布来合成一个模拟的词频

如果他们的假设成立——相关单词来自具有类似Zipf频率分布的自然语言语料库——那么我希望他们的抽样概率接近根据真实频率信息计算的抽样概率。对于大多数目的来说,这可能“足够接近”

我不知道他们为什么选择这个近似值。也许他们通常过程的其他方面在这一步中没有保持真实的频率,他们希望总是与自然语言文本一起工作,假设的频率通常是真实的

(幸运的是,由于人们经常想将频率归算到公共的词向量集合中,这些词向量的真实计数已经下降,但仍然是从最频繁到最不频繁排序的,就在几天前我写的,类似于keras代码所做的。)

但是,如果你使用的数据与他们的假设不匹配(比如你的合成或描述的数据集),他们的抽样概率将与你自己计算的概率大不相同,任何形式的原始公式都使用真实的词频

特别是,想象一个发行版有一百万次一个代币,然后一百个代币都只出现10次。这一百个标记在“排名”列表中的顺序是任意的——的确,它们的频率都是并列的。但基于模拟的方法,通过在该顺序上拟合齐普夫分布,实际上将对它们中的每一个进行非常不同的采样。一个出现次数为10次的单词幸运地处于第二级的位置,它的抽样率会低很多,好像频率会高得多。而第1级“高头”值,通过其真实频率*低于-*近似值,将比其他情况下更少进行下采样。这两种效果似乎都没有好处