【问题标题】:Python Gensim LDAMallet CalledProcessError with large corpus (runs fine with small corpus)带有大型语料库的 Python Gensim LDAMallet CalledProcessError(在小型语料库中运行良好)
【发布时间】:2023-09-24 06:08:01
【问题描述】:

当我在大约 1600 万个文档的完整语料库上运行 Gensim LDAMallet 模型时,我收到 CalledProcessError“非零退出状态 1”错误。 有趣的是,如果我在大约 160,000 个文档的测试语料库上运行完全相同的代码,则代码运行得非常好。由于它在我的小型语料库上运行良好,我倾向于认为代码很好,但我不确定还有什么会/可能导致此错误...

我已尝试按照here 的建议编辑 mallet.bat 文件,但无济于事。 我还仔细检查了路径,但这应该不是问题,因为它适用于较小的语料库。

id2word = corpora.Dictionary(lists_of_words)
corpus =[id2word.doc2bow(doc) for doc in lists_of_words]
num_topics = 30
os.environ.update({'MALLET_HOME':r'C:/mallet-2.0.8/'})
mallet_path = r'C:/mallet-2.0.8/bin/mallet'
ldamallet = gensim.models.wrappers.LdaMallet(mallet_path, corpus=corpus, num_topics=num_topics, id2word=id2word)

这是完整的回溯和错误:

  File "<ipython-input-57-f0e794e174a6>", line 8, in <module>
    ldamallet = gensim.models.wrappers.LdaMallet(mallet_path, corpus=corpus, num_topics=num_topics, id2word=id2word)

  File "C:\ProgramData\Anaconda3\lib\site-packages\gensim\models\wrappers\ldamallet.py", line 132, in __init__
    self.train(corpus)

  File "C:\ProgramData\Anaconda3\lib\site-packages\gensim\models\wrappers\ldamallet.py", line 273, in train
    self.convert_input(corpus, infer=False)

  File "C:\ProgramData\Anaconda3\lib\site-packages\gensim\models\wrappers\ldamallet.py", line 262, in convert_input
    check_output(args=cmd, shell=True)

  File "C:\ProgramData\Anaconda3\lib\site-packages\gensim\utils.py", line 1918, in check_output
    raise error

CalledProcessError: Command 'C:/mallet-2.0.8/bin/mallet import-file --preserve-case --keep-sequence --remove-stopwords --token-regex "\S+" --input C:\Users\user\AppData\Local\Temp\2\e1ba4a_corpus.txt --output C:\Users\user\AppData\Local\Temp\2\e1ba4a_corpus.mallet' returned non-zero exit status 1.

【问题讨论】:

    标签: python gensim lda mallet


    【解决方案1】:

    很高兴您找到了我的帖子,很抱歉它对您不起作用。我遇到这个错误的原因有很多,主要是 Java 没有安装属性并且路径没有调用环境变量。

    由于您的代码在较小的数据集上运行,我将首先查看您的数据。 Mallet 很挑剔,因为它只接受可能遇到空值、标点符号或浮点数的最干净的数据。

    您是抽取了字典的样本量还是传入了整个数据集?

    这基本上就是它正在做的事情:句子变成单词 - 单词变成数字 - 然后计算频率,例如:

    [(3, 1), (13, 1), (37, 1)]

    单词 3(“辅助”)出现 1 次。 第 13 字(“付款”)出现 1 次。 Word 37(“帐户”)出现 1 次。

    然后,您的 LDA 会查看一个单词并根据它与字典中所有其他单词出现的频率来评分,并且它会为整个字典执行此操作,因此如果您让它查看数百万个单词,它是会很快崩溃。

    这就是我实现 mallet 并缩小字典的方式,不包括词干提取或其他预处理步骤:

    # we create a dictionary of all the words in the csv by iterating through
    # contains the number of times a word appears in the training set.
    
    dictionary = gensim.corpora.Dictionary(processed_docs[:])
    count = 0
    for k, v in dictionary.iteritems():
        print(k, v)
        count += 1
        if count > 10:
            break
    
    # we want to throw out words that are so frequent that they tell us little about the topic 
    # as well as words that are too infrequent >15 rows then keep just 100,000 words
    
    dictionary.filter_extremes(no_below=15, no_above=0.5, keep_n=100000)
    
    # the words become numbers and are then counted for frequency
    # consider a random row 4310 - it has 27 words word indexed 2 shows up 4 times
    # preview the bag of words
    
    bow_corpus = [dictionary.doc2bow(doc) for doc in processed_docs]
    bow_corpus[4310]
    
    os.environ['MALLET_HOME'] = 'C:\\mallet\\mallet-2.0.8'
    
    mallet_path = 'C:\\mallet\\mallet-2.0.8\\bin\\mallet'
    
    ldamallet = gensim.models.wrappers.LdaMallet(mallet_path, corpus=bow_corpus, num_topics=20, alpha =.1, 
                                                 id2word=dictionary, iterations = 1000, random_seed = 569356958)

    另外,我会将您的 ldamallet 分成一个单独的单元格,因为编译时间很慢,尤其是在这种大小的数据集上。我希望这有助于让我知道您是否仍然遇到错误:)

    【讨论】:

    • 感谢您的回复!为了创建我的字典,我从整个数据集开始,然后从我的语料库中删除最常用和最不常用的词(即,那些在 99.5% 的文档中,而那些不在至少 100 个文档中的词)。我没有想过一份文件可能会造成问题。它适用于多达 250 万个文档,因此我随机抽取了 10 个不同的样本,只要我没有超过 250 万个文档的样本,它就一直有效。所以看起来好像不是一个文档导致了错误。分离 ldamallet 单元是什么意思?
    • @ctim 我不确定您使用什么方法来清理数据,但我在我的一个数据集中遇到了类似的错误,这是因为 nltk 错过了第 700,000 行中的一个数字。我会包括一个 .dropna() 作为额外的措施