推荐系统-召回-负采样python代码

class UnigramSampler:
    def __init__(self, corpus, power, sample_size):
        self.sample_size = sample_size
        self.vocab_size = None
        self.word_p = None

        counts = collections.Counter()
        for word_id in corpus:
            counts[word_id] += 1

        vocab_size = len(counts)
        self.vocab_size = vocab_size

        self.word_p = np.zeros(vocab_size)
        for i in range(vocab_size):
            self.word_p[i] = counts[i]

        self.word_p = np.power(self.word_p, power)
        self.word_p /= np.sum(self.word_p)

    def get_negative_sample(self, target):
        batch_size = target.shape[0]

        negative_sample = np.zeros((batch_size, self.sample_size), dtype=np.int32)

            for i in range(batch_size):
                p = self.word_p.copy()
                target_idx = target[i]
                p[target_idx] = 0
                p /= p.sum()
                negative_sample[i, :] = np.random.choice(self.vocab_size, size=self.sample_size, replace=False, p=p)

        return negative_sample

负采样首先要做的事随机抽取负例,随机抽取负例有个技巧,就是要让语料库中经常出现的单词容易被抽到,让语料库中不经常出现的单词难以被抽到。所以,通常的抽取方式是基于语料库中单词使用频率的采样方法会先计算语料库中各个单词的出现次数,并将其表示为“概率分布”,然后使用这个概率分布对单词进行采样, 随机抽取负例由下面的UnigramSampler 类来实现。

UnigramSampler 类中,简单的介绍一下np.random.choice()方法,np.random.choice() 可以用于随机抽样,如果指定 size 参数,将执行多次采样,如果指定 replace=False,将进行无放回采样,通过给参数 p 指定表示概率分布的列表,因此通过语料库中词不同的概率,将进行基于概率分布的负采样。

为什么

Word2vec 中 负采样 的采样方式?

NS是一种概率采样的方式,可以根据词频进行随机抽样,我们倾向于选择词频比较大的负样本,比如“的”,这种词语其实是对我们的目标单词没有很大贡献的。

Word2vec则在词频基础上取了0.75次幂,减小词频之间差异过大所带来的影响,使得词频比较小的负样本也有机会被采到。

极大化正样本出现的概率,同时极小化负样本出现的概率,以sigmoid来代替softmax,相当于进行二分类,判断这个样本到底是不是正样本。

源:https://guohongyi.com/2020/11/19/%E7%94%A8Python%E6%89%8B%E6%92%95word2vec/#%E8%B4%9F%E9%87%87%E6%A0%B7%E7%9A%84%E5%AE%9E%E7%8E%B0

posted @ 2022-04-18 22:28  今夜无风  阅读(519)  评论(0编辑  收藏  举报