【问题标题】:Batch-train word2vec in gensim with support of multiple workers在 gensim 中批量训练 word2vec 并支持多个工人
【发布时间】:2019-11-12 15:56:58
【问题描述】:

上下文

关于如何使用 gensim 和流数据训练 Word2Vec 存在几个问题。无论如何,这些问题并没有解决流不能使用多个工作线程的问题,因为没有数组可以在线程之间拆分。

因此,我想创建一个为 gensim 提供此类功能的生成器。我的结果如下:

from gensim.models import Word2Vec as w2v

#The data is stored in a python-list and unsplitted.
#It's too much data to store it splitted, so I have to do the split while streaming.
data = ['this is document one', 'this is document two', ...]

#Now the generator-class
import threading

class dataGenerator:
    """
    Generator for batch-tokenization.
    """

    def __init__(self, data: list, batch_size:int = 40):
        """Initialize generator and pass data."""

        self.data = data
        self.batch_size = batch_size
        self.lock = threading.Lock()


    def __len__(self):
        """Get total number of batches."""
        return int(np.ceil(len(self.data) / float(self.batch_size)))


    def __iter__(self) -> list([]):
        """
        Iterator-wrapper for generator-functionality (since generators cannot be used directly).
        Allows for data-streaming.
        """
        for idx in range(len(self)):
            yield self[idx]


    def __getitem__(self, idx):

        #Make multithreading thread-safe
        with self.lock:

            # Returns current batch by slicing data.
            return [arr.split(" ") for arr in self.data[idx * self.batch_size : (idx + 1) * self.batch_size]]


#And now do the training
model = w2v(
             sentences=dataGenerator(data),
             size=300,
             window=5,
             min_count=1,
             workers=4
            )

这会导致错误

TypeError: unhashable type: 'list'

由于dataGenerator(data) 如果我只生成一个拆分文档就可以工作,我假设 gensims word2vec 将生成器包装在一个额外的列表中。在这种情况下,__iter__ 看起来像:

def __iter__(self) -> list:
    """
    Iterator-wrapper for generator-functionality (since generators cannot be used directly.
    Allows for data-streaming.
    """
    for text in self.data:
        yield text.split(" ")

因此,我的批次也会被包装成类似 [[['this', '...'], ['this', '...']], [[...], [...]]] (=> list of list of list) 之类的东西,gensim 无法处理。




我的问题:

我可以“流”传递批次以使用多个工人吗? 如何相应地更改我的代码?

【问题讨论】:

    标签: python nlp batch-processing gensim word2vec


    【解决方案1】:

    看来我太不耐烦了。我运行了上面编写的流式函数,它只处理一个文档而不是批处理:

    def __iter__(self) -> list:
        """
        Iterator-wrapper for generator-functionality (since generators cannot be used directly.
        Allows for data-streaming.
        """
        for text in self.data:
            yield text.split(" ")
    

    启动w2v-函数后,大约需要十分钟,直到所有内核都正常工作。

    似乎构建词汇表不支持多核,因此,这项任务只使用了一个。据推测,它花了这么长时间,因为 auf 语料库大小。 gensim 构建词汇后,所有核心都用于训练。

    因此,如果您也遇到了这个问题,也许一些耐心会有所帮助:)

    【讨论】:

    • 是的,第一次词汇扫描是单线程的。您可以通过 (1) 在不提供语料库的情况下实例化模型来手动将其拆分出来,以使日志/监控更加清晰; (2) 调用build_vocab() 提供您的语料库(单线程); (3) 调用train() 提供您的语料库(多线程)。一次产生一个项目的简单可迭代语料库将可接受地提供多个线程 - 模型本身使用 1 个读取器线程,该线程批处理到许多工作线程。不幸的是,由于 Python GIL(等),这只会获得一些并行性,而不是使所有内核饱和。但是最近的 gensim 版本……
    • ...可以使用备用的corpus_file 参数(如果您的语料库位于带有空格分隔标记和换行符分隔文本的磁盘文件中),该参数允许多个线程在不同范围内执行自己的 IO文件 - 因此在用 8 个以上的工作线程饱和 8 个以上的内核时要好得多(最多你有多少个内核)。
    • 哇,这是对我问题的非常详细的见解,非常感谢!如果您将其写在答案中,我肯定会将其标记为正确答案:)
    【解决方案2】:

    只是想重申一下 @gojomo's comment 是要走的路:使用大型语料库和多个 cpus,使用 corpus_file 参数而不是 sentences 来训练 gensim word2vec 会快得多,如 the docs 中所述:

    • corpus_file (str, optional)LineSentence 格式的语料库文件的路径。您可以使用此参数而不是句子来提高性能。只需要传递一个句子或 corpus_file 参数(或者一个都不传递,在这种情况下,模型未初始化)。

    LineSentence 格式基本上每行只有一个句子,单词以空格分隔。纯文本,.bz2 或 gz。

    【讨论】:

    • 有没有办法拥有多个这样的 LineSentence 文件?
    猜你喜欢
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 2021-10-22
    • 2018-11-27
    • 2019-02-07
    • 1970-01-01
    相关资源
    最近更新 更多