LDA的使用记录--gensim库

在之前的实验中,我们利用LDA库来实现了lda, 并且采用二种特征表述方法,一种是直接统计词频的方法,一种是利用TF-IDF来作为特征,并且在有限的测试集上取得了较为理想的效果,当然,这个效果是否真的好,我们需要持怀疑态度哈,需要进一步的验证,这才是严谨的科研态度啊,不管不管,我现在就任性的默认为它能用~~
现在我们需要考虑利用gensim库中的LDA方法,当然,他们都说,学习最好的文档,应该是官方的API和文档,好吧,我承认,在我不懂别人代码的时候,我还是会去查一下的~~gensim中的LDA的实现也有上述二种特征的表述。在这里,我们也是采用二种方式来解决。
实验的代码如下:

# -*- coding:utf-8 -*-

from nltk.tokenize import RegexpTokenizer
from stop_words import get_stop_words
from nltk.stem.porter import PorterStemmer
from gensim import corpora, models

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

if __name__ == "__main__":

    corpus = []   # 存储文档
    tokens = []   # 存储文档中的单词
    # 读取文档的操作
    for line in open('a.txt','r').readlines():
        if '\xef\xbb\xbf' in line:
            line = line.replace('\xef\xbb\xbf', ' ')
        corpus.append(line.strip())
    print corpus

    # 去标点符号,去截止词的操作
    en_stop = get_stop_words('en')   # 利用Pypi的stop_words包,需要去掉stop_words

    # # 提取主干的词语的操作
    # p_stemmer = PorterStemmer()

    # 分词的操作
    tokenizer = RegexpTokenizer(r'\w+')
    for text in corpus:
        raw = text.lower()
        token = tokenizer.tokenize(raw)
        stop_remove_token = [word for word in token if word not in en_stop]
        # stem_token = [p_stemmer.stem(word) for word in stop_remove_token]
        tokens.append(stop_remove_token)
    # print tokens

    # 得到文档-单词矩阵 (直接利用统计词频得到特征)
    dictionary = corpora.Dictionary(tokens)   # 得到单词的ID,统计单词出现的次数以及统计信息
    # print dictionary.token2id         # 可以得到单词的id信息  
    # print type(dictionary)            # 得到的是gensim.corpora.dictionary.Dictionary的class类型

    texts = [dictionary.doc2bow(text) for text in tokens]    # 将dictionary转化为一个词袋,得到文档-单词矩阵

    # # 直接利用词频作为特征来进行处理
    # lda_model = models.ldamodel.LdaModel(texts, num_topics=3, id2word=dictionary,  passes=500)
    # print lda_model.print_topics(num_topics=3,num_words=4)
    # corpus_lda = lda_model[texts]
    # for doc in corpus_lda:
    #     print doc

    # 利用tf-idf来做为特征进行处理
    texts_tf_idf = models.TfidfModel(texts)[texts]     # 文档的tf-idf形式(训练加转换的模式)
    # # for text in texts_tf_idf:            # 逐行打印得到每篇文档的每个单词的TD-IDF的特征值
    # #     print text
    # lda_tf_idf = models.LdaModel(texts_tf_idf, num_topics=3, id2word=dictionary, update_every=0, passes=200)
    # print lda_tf_idf.print_topics(num_topics=3,num_words=4)
    # # doc_topic = [a for a in lda_tf_idf[texts_tf_idf]]
    # # for topic_id in range(3):
    # #     print "topic:{}".format(topic_id+1)
    # #     print lda_tf_idf.show_topic(topic_id)
    # corpus_lda_tfidf = lda_tf_idf[texts_tf_idf]
    # for doc in corpus_lda_tfidf:
    #     print doc

    # 利用lsi做主题分类的情况
    print "**************LSI*************"
    lsi = models.lsimodel.LsiModel(corpus=texts, id2word=dictionary, num_topics=3)    # 初始化一个LSI转换
    texts_lsi = lsi[texts_tf_idf]                # 对其在向量空间进行转换
    print lsi.print_topics(num_topics=3, num_words=4)
    for doc in texts_lsi:
        print doc

    # 利用LDA做主题分类的情况
    print "**************LDA*************"
    lda = models.ldamodel.LdaModel(corpus=texts, id2word=dictionary, num_topics=3,update_every=0,passes=20)
    texts_lda = lda[texts_tf_idf]
    print lda.print_topics(num_topics=3, num_words=4)
    for doc1 in texts_lda:
        print doc1

测试的例子同样取之前的八条,对结果的分析如下:
呜呜,看到结果之后,我的感受就是没有好好的看API,所以处理的特别不优雅啊,看起来好麻烦啊,还是应该好好瞅瞅官方的文档啊,不然,分析的好恼火呀·~

[(0, u'0.063*"chemic" + 0.058*"prepar" + 0.056*"attack" + 0.047*"potenti"'), (1, u'0.050*"us" + 0.041*"love" + 0.039*"global" + 0.038*"salahuddin"'), (2, u'0.041*"us" + 0.041*"salahuddin" + 0.040*"terrorist" + 0.035*"global"')]
[(0, 0.90658676065083843), (1, 0.047411882484675261), (2, 0.046001356864486448)]
[(0, 0.86302714965184002), (1, 0.070556766093404014), (2, 0.066416084254756008)]
[(0, 0.91210642231730266), (1, 0.043610822378047205), (2, 0.044282755304650076)]
[(0, 0.86744641908125031), (1, 0.069397773162269388), (2, 0.063155807756480248)]
[(0, 0.043375749164465169), (1, 0.90793994717599336), (2, 0.0486843036595416)]
[(0, 0.05044633363796186), (1, 0.20910467380871967), (2, 0.74044899255331853)]
[(0, 0.10394131046804331), (1, 0.56844844364726166), (2, 0.32761024588469495)]
[(0, 0.05616344410959289), (1, 0.88549815864827286), (2, 0.058338397242134278)]

第一个部分是主题-单词的情况,第一个主题,识别出来我猜是化学袭击的情况,第二个识别出来的应该是。。。我保持中立的意见,呜呜,好伤心哦,第三个识别出来的应该是恐怖分子的主题。好吧,这结果,,我也是醉了~
看每篇文章的分类的结果,1–1,2–1,3–1,4–1,5–2,6–3,7–2,8–2,分出的主题是什么鬼~,,与数据集相关性应该很大。
分析TF-IDF作为特征时候的结果:

[(0, u'0.030*"white" + 0.029*"hous" + 0.028*"chemic" + 0.028*"warn"'), (1, u'0.029*"warn" + 0.028*"love" + 0.028*"white" + 0.027*"prepar"'), (2, u'0.035*"declar" + 0.033*"global" + 0.032*"terrorist" + 0.031*"salahuddin"')]
[(0, 0.60280303631598264), (1, 0.23264180833579853), (2, 0.16455515534821896)]
[(0, 0.57184076647381388), (1, 0.260392660280028), (2, 0.16776657324615807)]
[(0, 0.70437217147464493), (1, 0.15341478080028573), (2, 0.14221304772506937)]
[(0, 0.49227310925114359), (1, 0.24206026486565432), (2, 0.26566662588320206)]
[(0, 0.14355241530931395), (1, 0.14326808829206358), (2, 0.71317949639862233)]
[(0, 0.15180196360281939), (1, 0.18008857355122568), (2, 0.66810946284595507)]
[(0, 0.16618324997971065), (1, 0.17202120977997759), (2, 0.66179554024031184)]
[(0, 0.19706906263334936), (1, 0.63159497067591563), (2, 0.17133596669073495)]

这个应该是算比直接词频作为特征的效果要好吧,识别出的三个主题分别是:第一是按理说应该是化学攻击吧,第二个按理说应该是普通生活主题吧,第三个应该是恐怖分子的主题。效果要稍微好那么一点点,好吧,其实从主题的单词角度来看,其实效果真心不太好了,也许是我的数据太小了,当然有这个的原因呀~
继续坚持不懈,没关系的,你可以的,,内心的小人一直不停的给我加油打气。
此处将代码的参数进行调节:

lda_model = models.ldamodel.LdaModel(texts, num_topics=3, id2word=dictionary,  passes=20)

测试结果为:

[(0, u'0.104*"love" + 0.060*"life" + 0.060*"sun" + 0.060*"member"'), (1, u'0.083*"prepar" + 0.083*"attack" + 0.083*"chemic" + 0.064*"white"'), (2, u'0.098*"us" + 0.079*"global" + 0.079*"salahuddin" + 0.079*"terrorist"')]
[(0, 0.027977394225595528), (1, 0.94414088371220772), (2, 0.027881722062196825)]
[(0, 0.041935576115165241), (1, 0.91625751139611755), (2, 0.041806912488717263)]
[(0, 0.025845300331770484), (1, 0.94840637487690949), (2, 0.025748324791320096)]
[(0, 0.03371619747230116), (1, 0.86205146046230308), (2, 0.10423234206539569)]
[(0, 0.025883371892911556), (1, 0.02574844612871539), (2, 0.94836818197837303)]
[(0, 0.030570745082050623), (1, 0.030422855916645987), (2, 0.93900639900130334)]
[(0, 0.05587469290842844), (1, 0.055726454693212024), (2, 0.88839885239835947)]
[(0, 0.92572157096933061), (1, 0.037128377481131472), (2, 0.037150051549537738)]

在TF-IDF中的测试结果:我觉得很神奇,为什么都收敛不到最终的结果,这个是可以收敛的嘛?需要在这个地方打一个大大的问号?
单从较短的文本的主题识别而言,在gensim模块中,LSI的表现效果要优于LDA的。
在做的其中,发现问题:对于gensim库的使用,不太明确,确实应该重新回去好好读一遍,在这里感谢一下,翻译了gensim使用的各位大佬,给你们端茶送水。
在做测试的过程中,发现一个问题,就是每次运行都会有不同的运行结果,我不太确定是不是不收敛的问题,在查阅官方资料时,发现,可能这就是一个系统的特性吧,需要用save 和load 函数来保证模型的持久性。所以,好的模型就保存吧·~
LSI的模型测试结果:

**************LSI*************
[(0, u'0.379*"preparations" + 0.379*"attack" + 0.379*"chemical" + 0.309*"potential"'), (1, u'-0.421*"us" + -0.402*"terrorist" + -0.402*"salahuddin" + -0.312*"india"'), (2, u'-0.632*"love" + -0.316*"need" + -0.316*"raise" + -0.316*"life"')]
[(0, 0.65876181227697583), (1, 0.081476913735450227)]
[(0, 0.47791111838303052), (1, 0.061910883552043598)]
[(0, 0.69974581396716673), (1, 0.077626511321183214)]
[(0, 0.55118831491103282), (1, -0.071913390289939941)]
[(0, 0.049382949835345025), (1, -0.68656004823418748)]
[(0, 0.050109243537853169), (1, -0.63339257912137159)]
[(0, 0.054617058841135928), (1, -0.54128519609559911)]
[(2, -1.0000000000000007)]

LSI模型识别出三个主题:第一个主题是化学攻击,第二个主题是恐怖主义,第三个主题是普通生活的话题。
LDA的再次测试结果,,这样总找好的,难道不会过拟合嘛·~担心中

**************LDA*************
[(0, u'0.101*"love" + 0.058*"family" + 0.058*"sun" + 0.058*"life"'), (1, u'0.096*"terrorist" + 0.096*"salahuddin" + 0.088*"us" + 0.068*"global"'), (2, u'0.071*"preparations" + 0.071*"attack" + 0.071*"chemical" + 0.054*"syrian"')]
[(0, 0.083663228178849941), (1, 0.083306516125512264), (2, 0.83303025569563771)]
[(0, 0.10029266702065466), (1, 0.099850794997724576), (2, 0.79985653798162082)]
[(0, 0.080450036750787532), (1, 0.080110865342045284), (2, 0.8394390979071672)]
[(0, 0.091010311845458436), (1, 0.094361937681609179), (2, 0.81462775047293234)]
[(0, 0.079324177164037044), (1, 0.24368223170437681), (2, 0.67699359113158619)]
[(0, 0.084102295616690345), (1, 0.83211795134498212), (2, 0.08377975303832752)]
[(0, 0.1088822395776104), (1, 0.78223763566625715), (2, 0.1088801247561326)]
[(0, 0.81053905780759494), (1, 0.094815306334920385), (2, 0.094645635857484672)]

对于主题识别而言,第一个是普通生活主题的,第二个是恐怖分子的主题,第三个是化学袭击的主题。

你可能感兴趣的:(自然语言处理相关)