A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

本篇是我的LDA主题挖掘系列的第二篇,介绍如何利用gensim包提供的方法来训练自己处理好的语料。
gensim提供了多种方法:

速度较慢的:

具体参数说明及使用方法请参照官网:models.ldamodel – Latent Dirichlet Allocation

from gensim.models.ldamodel import LdaModel# 利用处理好的语料训练模型lda = LdaModel(corpus, num_topics=10)# 推断新文本的主题分布doc_lda = lda[doc_bow]# 用新语料更新模型lda.update(other_corpus)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
速度较快,使用多核心的:

具体参数说明及使用方法请参照官网:models.ldamulticore – parallelized Latent Dirichlet Allocation

>>> from gensim import corpora, models >>> lda = LdaMulticore(corpus, id2word=id2word, num_topics=100)  # train model>>> print(lda[doc_bow]) # get topic probability distribution for a document>>> lda.update(corpus2) # update the LDA model with additional documents>>> print(lda[doc_bow])
  • 1
  • 2
  • 3
  • 4
  • 5

使用多进程对性能的提升:

Wall-clock performance on the English Wikipedia (2G corpus positions, 3.5M documents, 100K features, 0.54G non-zero entries in the final bag-of-words matrix), requesting 100 topics:
(Measured on this i7 server with 4 physical cores, so that optimal workers=3, one less than the number of cores.)
algorithm
training time

LdaMulticore(workers=1)
2h30m

LdaMulticore(workers=2)
1h24m

LdaMulticore(workers=3)
1h6m

oldLdaModel
3h44m

simply iterating over input corpus = I/O overhead
20m

workers的值需要比电脑的核心数小1
本文代码使用多核心的方法。
有问题欢迎留言交流。
本文在将语料转化为corpus后,进行了如下操作:

tfidf = models.TfidfModel(corpus)corpusTfidf = tfidf[corpus]
  • 1
  • 2

这一步是用来调整语料中不同词的词频,将那些在所有文档中都出现的高频词的词频降低,具体原理可参见阮一峰老师的系列博客:TF-IDF与余弦相似性的应用(一):自动提取关键词,我经过这一步处理后,貌似效果提升不明显,而且这一步时间消耗较大,不建议采用。可直接将corpus作为训练数据传入lda模型中。

#-*-coding:utf-8-*-import sysreload(sys)sys.setdefaultencoding('utf-8')import osimport codecsfrom gensim.corpora import Dictionaryfrom gensim import corpora, modelsfrom datetime import datetimeimport platformimport logginglogging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s : ', level=logging.INFO)platform_info = platform.platform().lower()if 'windows' in platform_info:    code = 'gbk'elif 'linux' in platform_info:    code = 'utf-8'path = sys.path[0]class GLDA(object):    """docstring for GdeltGLDA"""    def __init__(self, stopfile=None):        super(GLDA, self).__init__()        if stopfile:            with codecs.open(stopfile, 'r', code) as f:                self.stopword_list = f.read().split(' ')            print ('the num of stopwords is : %s'%len(self.stopword_list))        else:            self.stopword_list = None    def lda_train(self, num_topics, datafolder, middatafolder, dictionary_path=None, corpus_path=None, iterations=5000, passes=1, workers=3):               time1 = datetime.now()        num_docs = 0        doclist = []        if not corpus_path or not dictionary_path: # 若无字典或无corpus,则读取预处理后的docword。一般第一次运行都需要读取,在后期调参时,可直接传入字典与corpus路径            for filename in os.listdir(datafolder): # 读取datafolder下的语料                with codecs.open(datafolder+filename, 'r', code) as source_file:                    for line in source_file:                        num_docs += 1                        if num_docs%100000==0:                            print ('%s, %s'%(filename, num_docs))                        #doc = [word for word in doc if word not in self.stopword_list]                        doclist.append(line.split(' '))                print ('%s, %s'%(filename, num_docs))        if dictionary_path:            dictionary = corpora.Dictionary.load(dictionary_path) # 加载字典        else:                        #构建词汇统计向量并保存            dictionary = corpora.Dictionary(doclist)            dictionary.save(middatafolder + 'dictionary.dictionary')        if corpus_path:            corpus = corpora.MmCorpus(corpus_path) # 加载corpus        else:            corpus = [dictionary.doc2bow(doc) for doc in doclist]            corpora.MmCorpus.serialize(middatafolder + 'corpus.mm', corpus) # 保存corpus        tfidf = models.TfidfModel(corpus)        corpusTfidf = tfidf[corpus]        time2 = datetime.now()        lda_multi = models.ldamulticore.LdaMulticore(corpus=corpusTfidf, id2word=dictionary, num_topics=num_topics, \            iterations=iterations, workers=workers, batch=True, passes=passes) # 开始训练        lda_multi.print_topics(num_topics, 30) # 输出主题词矩阵        print ('lda training time cost is : %s, all time cost is : %s '%(datetime.now()-time2, datetime.now()-time1))        #模型的保存/ 加载        lda_multi.save(middatafolder + 'lda_tfidf_%s_%s.model'%(2014, num_topics, iterations)) # 保存模型        # lda = models.ldamodel.LdaModel.load('zhwiki_lda.model') # 加载模型        # save the doc-topic-id        topic_id_file = codecs.open(middatafolder + 'topic.json', 'w', 'utf-8')        for i in range(num_docs):            topic_id = lda_multi[corpusTfidf][0][0] # 取概率最大的主题作为文本所属主题            topic_id_file.write(str(topic_id)+ ' ')if __name__ == '__main__':    datafolder = path + os.sep + 'docword' + os.sep # 预处理后的语料所在文件夹,函数会读取此文件夹下的所有语料文件    middatafolder = path + os.sep + 'middata' + os.sep    dictionary_path = middatafolder + 'dictionary.dictionary' # 已处理好的字典,若无,则设置为False    corpus_path = middatafolder + 'corpus.mm' # 对语料处理过后的corpus,若无,则设置为False    # stopfile = path + os.sep + 'rest_stopwords.txt' # 新添加的停用词文件    num_topics = 50    passes = 2 # 这个参数大概是将全部语料进行训练的次数,数值越大,参数更新越多,耗时更长    iterations = 6000    workers = 3 # 相当于进程数    lda = GLDA()    lda.lda_train(num_topics, datafolder, middatafolder, dictionary_path=dictionary_path, corpus_path=corpus_path, iterations=iterations, passes=passes, workers=workers)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

在训练好模型后该如何对模型进行评价,以选取合适的参数?


1 个回复

倒序浏览
奈斯
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马