我正在使用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
答案 0 :(得分:0)
您确切问题的两个选项:
(1)
您不需要将您的语料库迭代器重新定义为完整的内存列表,并使用您的行:
train_corpus = list(AddressSentences("/data/corpus.csv"))
gensim Word2Vec模型可以直接使用您的iterable-object作为其语料库,因为它实现了__iter__()
(因此可以多次迭代)。所以你可以这样做:
train_corpus = AddressSentences("/data/corpus.csv")
然后将读取每一行,每次重复TaggedDocument重新yield()
ed,而不需要内存中的完整集。
(2)
或者,在这种情况下,您有时可能只想编写一个单独的例程来获取原始文件,而不是直接产生TaggedDocument
s,重复在磁盘上创建包含重复的有形文件。然后,使用更简单的可迭代读取器将该(已经重复的)数据集传输到模型中。
在这种特殊情况下,这种方法的否定之处在于它会增加(可能相对滞后)磁盘IO的数量。但是,如果迭代器执行的特殊处理成本更高 - 例如基于正则表达式的标记化 - 这种处理和重写可以帮助避免以后模型的重复工作。 (该模型需要扫描您的语料库一次用于词汇发现,然后再次iter
次进行训练 - 因此迭代器中的任何耗时工作都将冗余完成,并且可能成为阻碍其他训练线程空闲的瓶颈等待数据。)
但在这两个选项之后,还有一些特定于Doc2Vec的警告:
与简单地遍历完整的多样化集相比,重复这样的文档可能不会使Doc2Vec模型受益。这是对比的例子的拉锯战相互作用,它们导致Word2Vec / Doc2Vec模型中的单词向量/ doc向量找到有用的相对安排。
重复精确的文档/单词上下文是“超重”这些示例的合理方式,但即使这真的是你想要的,并且有助于你的最终目标,最好将这些重复改组为整体集。
连续重复一个例子就像在内部神经网络上应用该示例的单词共现,就像手提钻一样,没有任何机会让交错的替代例子找到相互预测的权重排列。通过所有不同实例的迭代梯度下降优化理想地更像是逐渐的水驱侵蚀&重新沉积价值观。
这表明采用第二种方法的另一个可能原因如上:在重复文件写入之后,您可以使用外部行重排工具(如Linux上的sort -R
或shuf
)洗牌文件。然后,一些示例的1000个重复行将在所有其他(重复)示例中均匀地分布,这是用于密集向量学习的更友好的布置。
在任何情况下,我都会尝试完全忽略重复,或者重复进行重复,并评估哪些步骤真正有助于实现真正的最终目标。