阿弥陀佛
分类: 大数据
2019-08-16 10:10:00
tensorflow的nce-loss的实现。所以总结一下。
先看看tensorflow的nce-loss的API:
-
def nce_loss(weights, biases, inputs, labels, num_sampled, num_classes,
-
num_true=1,
-
sampled_values=None,
-
remove_accidental_hits=False,
-
partition_strategy="mod",
-
name="nce_loss")
假设nce_loss之前的输入数据是K维的,一共有N个类,那么
nce_loss的实现逻辑如下:
再来看看TF里word2vec的实现,他用到nce_loss的代码如下:
loss = tf.reduce_mean( tf.nn.nce_loss(nce_weights, nce_biases, embed, train_labels, num_sampled, vocabulary_size))
可以看到,它这里并没有传sampled_values,那么它的负样本是怎么得到的呢?继续看nce_loss的实现,可以看到里面处理sampled_values=None的代码如下:
-
if sampled_values is None:
-
sampled_values = candidate_sampling_ops.log_uniform_candidate_sampler(
-
true_classes=labels,
-
num_true=num_true,
-
num_sampled=num_sampled,
-
unique=True,
-
range_max=num_classes)
所以,默认情况下,他会用log_uniform_candidate_sampler去采样。那么log_uniform_candidate_sampler是怎么采样的呢?他的实现在这里:
可以看到,k越大,被采样到的概率越小。那么在TF的word2vec里,类别的编号有什么含义吗?看下面的代码:
-
def build_dataset(words):
-
count = [['UNK', -1]]
-
count.extend(collections.Counter(words).most_common(vocabulary_size - 1))
-
dictionary = dict()
-
for word, _ in count:
-
dictionary[word] = len(dictionary)
-
data = list()
-
unk_count = 0
-
for word in words:
-
if word in dictionary:
-
index = dictionary[word]
-
else:
-
index = 0 # dictionary['UNK']
-
unk_count += 1
-
data.append(index)
-
count[0][1] = unk_count
-
reverse_dictionary = dict(zip(dictionary.values(), dictionary.keys()))
-
return data, count, dictionary, reverse_dictionary
可以看到,TF的word2vec实现里,词频越大,词的类别编号也就越大。因此,在TF的word2vec里,负采样的过程其实就是优先采词频高的词作为负样本。
在提出负采样的原始论文中, 包括word2vec的原始C++实现中。是按照热门度的0.75次方采样的,这个和TF的实现有所区别。但大概的意思差不多,就是越热门,越有可能成为负样本。