窗口大小与word2vec中实际句子长度之间的关系

时间:2015-08-28 17:35:08

标签: gensim word2vec

我正在尝试在.txt文件的语料库中运行word2vec(在gensim中实现的skip-gram模型,默认窗口大小为5)。我使用的迭代器看起来像这样:

class Corpus(object):
    """Iterator for feeding sentences to word2vec"""
    def __init__(self, dirname):
        self.dirname = dirname

    def __iter__(self):

        word_tokenizer = TreebankWordTokenizer()
        sent_tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
        text = ''

        for root, dirs, files in os.walk(self.dirname):

            for file in files:

                if file.endswith(".txt"):

                    file_path = os.path.join(root, file)


                    with open(file_path, 'r') as f:

                         text = f.read().decode('utf-8')
                         sentences = sent_tokenizer.tokenize(text)

                         for sent in sentences:
                             yield word_tokenizer.tokenize(sent)

这里我使用nltk包中的punkt标记器(使用无监督算法检测句子边界)将文本拆分成句子。然而,当我用一个简单的line.split()替换它时,即只考虑每个句子作为一行并拆分单词,我得到的时间效率比使用nltk解析器快1.5倍。 'with open'中的代码看起来像这样:

                 with open(file_path, 'r') as f:
                    for line in f:
                    line.decode('utf-8')
                    yield line.split()

我的问题是word2vec算法被赋予实际句子的句子(我试图用punkt tokenizer做的事情)有多重要?算法中的每个单词是否足以接收位于一行上的周围单词的上下文(这些单词在跨越多行的句子的情况下可能不一定是实际句子),而不是单词的上下文这个词可能在一个跨越几行的句子中。此外,窗口大小在这个中扮演什么样的角色。例如,当窗口大小设置为5时,句子迭代器产生的句子大小是否会停止发挥作用?只有窗口大小决定上下文单词吗?在这种情况下,我应该使用line.split()而不是尝试使用punkt tokenizer检测实际的句子边界?

我希望我能够充分描述这个问题,我真的很感激任何意见或指示或帮助。

1 个答案:

答案 0 :(得分:2)

窗口只是上下文窗口。如果window设置为5,那么对于当前单词w,将围绕10个单词作为上下文单词。根据原始的word2vec代码,该单词仅在句子中存在的上下文中训练。如果单词+上下文单词超出句子边界,那么其余的上下文单词将被忽略(近似)。

例如: 考虑一下句子:I am a boy 如果当前单词为boywindow为2,那么我们可以观察到没有正确的上下文。在这种情况下,代码将采用向量ama的平均值,并将其视为boy的上下文(参考word2vec的CBOW模型)。

对于第二个疑问,我使用了没有句子边界的文本语料库,而且word2vec仍然没问题。 (在维基百科语料库中测试过)

希望这可以解决您的疑问。