0

我正在训练一个模型gensim,我的语料库是许多短句,每个句子都有一个频率,表明它在整个语料库中出现的次数。如您所见,我将其实现如下,我只是选择重复freq次数。无论如何,如果数据很小,它应该可以工作,但是当数据增长时,频率可能会很大,它会占用太多内存,我的机器负担不起。

那么1.我可以只计算每条记录的频率而不是重复freq次数吗?2.或者有其他节省内存的方法吗?

class AddressSentences(object):
    def __init__(self, raw_path, path):
        self._path = path

    def __iter__(self):
        with open(self.path) as fi:
            headers = next(fi).split(",")
            i_address, i_freq = headers.index("address"), headers.index("freq")
            index = 0
            for line in fi:
                cols = line.strip().split(",")
                freq = cols[i_freq]
                address = cols[i_address].split()
                # Here I do repeat
                for i in range(int(freq)):
                    yield TaggedDocument(address, [index])
                index += 1

print("START %s" % datetime.datetime.now())
train_corpus = list(AddressSentences("/data/corpus.csv"))
model = gensim.models.doc2vec.Doc2Vec(size=50, min_count=2, iter=55)
model.build_vocab(train_corpus)
model.train(train_corpus, total_examples=model.corpus_count, epochs=model.iter)
print("END %s" % datetime.datetime.now())

语料库是这样的:

address,freq
Cecilia Chapman 711-2880 Nulla St.,1000
The Business Centre,1000
61 Wellfield Road,500
Celeste Slater 606-3727 Ullamcorper. Street,600
Theodore Lowe Azusa New York 39531,700
Kyla Olsen Ap #651-8679 Sodales Av.,300
4

1 回答 1

0

您的确切问题的两个选项:

(1)

您不需要使用以下行将语料库迭代器具体化为完全内存中的列表:

    train_corpus = list(AddressSentences("/data/corpus.csv"))

gensim Word2Vec 模型可以直接使用您的可迭代对象作为其语料库,因为它实现__iter__()了(因此可以迭代多次)。所以你可以这样做:

    train_corpus = AddressSentences("/data/corpus.csv")

然后将读取每一行,并重新读取每个重复的 TaggedDocument yield(),而不需要内存中的完整集。

(2)

或者,在这种情况下,您有时可能只想编写一个单独的例程来获取原始文件,而不是直接产生TaggedDocuments,而是执行重复以在磁盘上创建包含重复的有形文件。然后,使用更简单的可迭代阅读器将(已经重复的)数据集流式传输到您的模型中。

在这种特殊情况下,这种方法的一个缺点是它会增加(可能相对滞后)磁盘 IO 的数量。但是,如果您的迭代器正在执行的特殊处理成本更高——例如基于正则表达式的标记化——这种处理和重写可以帮助避免模型以后重复工作。(该模型需要扫描您的语料库一次以发现词汇,然后再扫描一次以iter进行训练——因此迭代器中的任何耗时工作都将冗余完成,并且可能成为其他训练线程空闲等待数据的瓶颈。)

但是在这两个选项之后,一些 Doc2Vec 特定的警告:

与简单地迭代完整的多样化集合相比,像这样重复文档可能不会使 Doc2Vec 模型受益。这是对比示例的拔河相互作用,导致 Word2Vec/Doc2Vec 模型中的词向量/文档向量找到有用的相对排列。

重复准确的文档/单词上下文是“超重”这些示例的一种合理方式,但即使这确实是您想要的,并且有助于您的最终目标,最好将这些重复在整个集合中打乱。

连续重复一个例子就像在内部神经网络上像手提钻一样应用那个例子的词共现,没有任何机会让交错的替代例子找到一个相互预测的权重排列。理想情况下,通过所有不同示例的迭代梯度下降优化更像是逐渐水驱动的侵蚀和值的重新沉积。

这暗示了采用上述第二种方法的另一个可能原因:在编写带有重复的文件之后,您可以使用外部换行工具(如Linuxsort -Rshuf在 Linux 上)对文件进行洗牌。然后,一些示例的 1000 行重复行将均匀分布在所有其他(重复)示例中,这对于密集向量学习来说是一种更友好的安排。

在任何情况下,我都会尝试完全省略重复,或改组重复,并评估哪些步骤真正有助于实现真正的最终目标。

于 2017-06-12T18:46:45.647 回答