如何让word2vec模型的加载时间和内存使用效率更高?
How to make word2vec model's loading time and memory use more efficient?
我想在网络服务器(生产)中以两种不同的变体使用 Word2vec,我从网络上获取两个句子并进行实时比较。目前,我正在具有 16GB RAM 的本地计算机上对其进行测试。
场景:
w2v = 加载 w2v 模型
If condition 1 is true:
if normalize:
reverse normalize by w2v.init_sims(replace=False) (not sure if it will work)
Loop through some items:
calculate their vectors using w2v
else if condition 2 is true:
if not normalized:
w2v.init_sims(replace=True)
Loop through some items:
calculate their vectors using w2v
我已经阅读了有关将词汇量减少到较小规模的解决方案,但我想使用所有词汇量。
是否有新的解决方法来处理这个问题?有没有办法在最初的 1-2 分钟内加载一小部分词汇,然后同时继续加载整个词汇?
作为您应该能够安排在任何服务请求之前发生的一次性延迟,我建议您不要过分担心第一次 load()
时间。 (将大量数据从磁盘加载到 RAM 本来就需要花费大量时间——但一旦到达那里,如果它被保存并在进程之间很好地共享,那么就不会再为任意长的服务正常运行时间花费成本。 )
"load a small portion of the vocabulary for first 1-2 minutes and in parallel keep loading the whole vocabulary" 没有多大意义——一旦需要任何相似性计算,就需要访问整个向量集以获得任何前 N 个结果。 (所以 "half-loaded" 状态不是很有用。)
请注意,如果您这样做 init_sims(replace=True)
,则模型的原始原始向量幅度会被新的单位归一化(幅度相同)向量破坏。所以看看你的伪代码,两条路径之间的唯一区别是显式 init_sims(replace=True)
。但是,如果您真的在请求之间在内存中保留相同的共享模型,那么一旦 condition 2
发生,模型就会被规范化,此后 condition 1
下的调用也会使用规范化向量进行。此外,condition 2
下的其他调用只是冗余地(并且代价高昂地)就地重新规范化向量。因此,如果规范化比较是您唯一的关注点,最好在服务启动时就地进行比较 init_sims(replace=True)
- 而不是受请求顺序的支配。
如果您使用 gensim 的原生 save()
(而不是 save_word2vec_format()
)保存模型,并且作为未压缩的文件,则可以选择 'memory-map' -加载。这意味着不是立即将完整的向量数组复制到 RAM 中,而是将磁盘上的文件简单地标记为提供寻址 -space。这有两个潜在的好处:(1)如果您甚至只访问数组的某些有限范围,则只会按需加载这些范围; (2) 许多单独的进程都使用相同的映射文件将自动重用加载到 RAM 中的任何共享范围,而不是潜在地复制相同的数据。
(1) 一旦您需要对整个词汇表进行全面扫描,就没有太大优势了——因为它们都被带入了 RAM,并且在访问时更进一步(这将比您只是预加载它们有更多的服务延迟)。但是 (2) 在多进程 webserver 场景中仍然是一个优势。在
我之前的回答中有更多关于如何有效使用内存映射 word2vec 模型的详细信息
我想在网络服务器(生产)中以两种不同的变体使用 Word2vec,我从网络上获取两个句子并进行实时比较。目前,我正在具有 16GB RAM 的本地计算机上对其进行测试。
场景: w2v = 加载 w2v 模型
If condition 1 is true:
if normalize:
reverse normalize by w2v.init_sims(replace=False) (not sure if it will work)
Loop through some items:
calculate their vectors using w2v
else if condition 2 is true:
if not normalized:
w2v.init_sims(replace=True)
Loop through some items:
calculate their vectors using w2v
我已经阅读了有关将词汇量减少到较小规模的解决方案,但我想使用所有词汇量。
是否有新的解决方法来处理这个问题?有没有办法在最初的 1-2 分钟内加载一小部分词汇,然后同时继续加载整个词汇?
作为您应该能够安排在任何服务请求之前发生的一次性延迟,我建议您不要过分担心第一次 load()
时间。 (将大量数据从磁盘加载到 RAM 本来就需要花费大量时间——但一旦到达那里,如果它被保存并在进程之间很好地共享,那么就不会再为任意长的服务正常运行时间花费成本。 )
"load a small portion of the vocabulary for first 1-2 minutes and in parallel keep loading the whole vocabulary" 没有多大意义——一旦需要任何相似性计算,就需要访问整个向量集以获得任何前 N 个结果。 (所以 "half-loaded" 状态不是很有用。)
请注意,如果您这样做 init_sims(replace=True)
,则模型的原始原始向量幅度会被新的单位归一化(幅度相同)向量破坏。所以看看你的伪代码,两条路径之间的唯一区别是显式 init_sims(replace=True)
。但是,如果您真的在请求之间在内存中保留相同的共享模型,那么一旦 condition 2
发生,模型就会被规范化,此后 condition 1
下的调用也会使用规范化向量进行。此外,condition 2
下的其他调用只是冗余地(并且代价高昂地)就地重新规范化向量。因此,如果规范化比较是您唯一的关注点,最好在服务启动时就地进行比较 init_sims(replace=True)
- 而不是受请求顺序的支配。
如果您使用 gensim 的原生 save()
(而不是 save_word2vec_format()
)保存模型,并且作为未压缩的文件,则可以选择 'memory-map' -加载。这意味着不是立即将完整的向量数组复制到 RAM 中,而是将磁盘上的文件简单地标记为提供寻址 -space。这有两个潜在的好处:(1)如果您甚至只访问数组的某些有限范围,则只会按需加载这些范围; (2) 许多单独的进程都使用相同的映射文件将自动重用加载到 RAM 中的任何共享范围,而不是潜在地复制相同的数据。
(1) 一旦您需要对整个词汇表进行全面扫描,就没有太大优势了——因为它们都被带入了 RAM,并且在访问时更进一步(这将比您只是预加载它们有更多的服务延迟)。但是 (2) 在多进程 webserver 场景中仍然是一个优势。在