gensim基础学习(一)

       最近参加了个长文本分类的比赛,然后开始使用gensim,一个很强大的NLP神器,用于从原始的非结构化的文本中,无监督地学习到文本隐层的主题向量表达,在此记录一下使用心得。

目录

基本概念

1.语料的处理

2.生成词典和向量转化

 3.主题向量的转化

      1)TFIDF(词频逆文档频率)

      2)LSI(潜在语义索引)

      3)LDA(隐含狄利克雷分配)

      4)RP(随即映射)

 4.相似度匹配

 5.转化为sklearn和scripy格式


基本概念

  • 语料(Corpus):一组原始文本的集合,用于无监督地训练文本主题的隐层结构。在Gensim中,Corpus通常是一个可迭代的对象,每一次迭代返回一个可用于表达文本对象的稀疏向量。
  • 向量(Vector):由一组文本特征构成的列表。是一段文本在Gensim中的内部表达。
  • 稀疏向量(Sparse Vector):通常,我们可以略去向量中多余的0元素。此时,向量中的每一个元素是一个(key, value)的tuple。key表示在字典中的索引值,value表示出现的次数。
  • 模型(Model):是一个抽象的术语。定义了两个向量空间的变换(即从文本的一种向量表达变换为另一种向量表达)

1.语料的处理

       对语料进行切分、去除停用词等基本处理,得到每一篇文档的特征列表。比如下面的列表

postingList = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
               ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
               ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him', 'my'],
               ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
               ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
               ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]

2.生成词典和向量转化

 from gensim import corpora

 dictionary = corpora.Dictionary(texts)

 print(dictionary)

     显示如下:

     Dictionary(32 unique tokens: ['dog', 'flea', 'has', 'help', 'my']...)

     其中字典还有很多实用的方法

print(dictionary.token2id)

# id2word print(dictionary.token2id)

# word2id print(dictionary.dfs) # 词频

     结果如下,词频的key值是字典中单词的索引值:

{'dog': 0, 'flea': 1, 'has': 2, 'help': 3, 'my': 4, 'please': 5, 'problems': 6, 'him': 7, 'maybe': 8, 'not': 9, 'park': 10, 'stupid': 11, 'take': 12, 'to': 13, 'I': 14, 'cute': 15, 'dalmation': 16, 'is': 17, 'love': 18, 'so': 19, 'garbage': 20, 'posting': 21, 'stop': 22, 'worthless': 23, 'ate': 24, 'how': 25, 'licks': 26, 'mr': 27, 'steak': 28, 'buying': 29, 'food': 30, 'quit': 31}
{4: 3, 0: 3, 2: 1, 1: 1, 6: 1, 3: 1, 5: 1, 8: 1, 9: 1, 12: 1, 7: 3, 13: 2, 10: 1, 11: 3, 16: 1, 17: 1, 19: 1, 15: 1, 14: 1, 18: 1, 22: 2, 21: 1, 23: 2, 20: 1, 27: 1, 26: 1, 24: 1, 28: 1, 25: 1, 31: 1, 29: 1, 30: 1}
 

 其他方法:

dictionary.filter_n_most_frequent(N) 过滤掉出现频率最高的N个单词

dictionary.filter_extremes(no_below=5, no_above=0.5, keep_n=100000)

    1.去掉出现次数低于no_below的

    2.去掉出现次数高于no_above的。注意这个小数指的是百分数

    3.在1和2的基础上,保留出现频率前keep_n的单词

dictionary.filter_tokens(bad_ids=None, good_ids=None)

有两种用法,一种是去掉bad_id对应的词,另一种是保留good_id对应的词而去掉其他词。

dictionary.compacity() 在执行完前面的过滤操作以后,可能会造成单词的序号之间有空隙,这时就可以使用该函数来对词典来进行重新排序,去掉这些空隙。

dictionary.merge_with(other)和其他字典合并

字典持久化和加载

dictionary.save("data/mydict.dic")

dictionary = corpora.Dictionary.load('data/mydict.dic')

将文本特征的原始表达转为词袋模型对应的稀疏向量的表达。

corpus = [dictionary.doc2bow(text) for text in postingList]
print(corpus)

 显示如下,其中(9,1)表示在字典中索引为9对应的单词,出现了1次:

[[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)], [(0, 1), (7, 1), (8, 1), (9, 1), (10, 1), (11, 1), (12, 1), (13, 1)], [(4, 2), (7, 1), (14, 1), (15, 1), (16, 1), (17, 1), (18, 1), (19, 1)], [(11, 1), (20, 1), (21, 1), (22, 1), (23, 1)], [(4, 1), (7, 1), (13, 1), (22, 1), (24, 1), (25, 1), (26, 1), (27, 1), (28, 1)], [(0, 1), (11, 1), (23, 1), (29, 1), (30, 1), (31, 1)]]

 语料的持久化和加载

corpora.MmCorpus.serialize("data/corpus.mm", corpus)  

corpus = corpora.MmCorpus("data/corpus.mm")

 3.主题向量的转化

       (1)首先是模型对象的初始化。通常,Gensim模型都接受一段训练语料(注意在Gensim中,语料对应着一个稀疏向量的迭代器)作为初始化的参数。

       (2)利用初始化的模型将语料转化为对象的向量

1)TFIDF(词频逆文档频率)

          from gensim import models

          tfidf = models.TfidfModel(corpus)

          tfidf.save("./model.tfidf")

          tfidf = models.TfidfModel.load("./model.tfidf")

2)LSI(潜在语义索引)

   将词袋模型或TFIDF空间映射到低维度的潜在空间,推荐200-500为金标准,在达观数据的长文本分类中,尝试350的维度分数得分优于其他维度。LSI可以进行增量训练,只要有新文档可以一直输入模型当中,通过add_document方法。如果python报memoryerror,那就是内存不够了,需要降低维度。

          lsi_model = models.LsiModel(corpus, id2word=dictionary, num_topics=2)

         #这是指的潜在主题(topic)的数目,也等于转成lsi模型以后每个文档对应的向量长度。转化以后的向量在各项的值,即为该文档   在该潜在主题的权重。

          documents = lsi_model[corpus]

          lsi_model.save("data/model1.lsi")

          lsi_model = models.LsiModel.load("data/model2.lsi")

3)LDA(隐含狄利克雷分配)

       LDA是LSA的概率扩展,也是向低纬度转化的方式

 

          lda_model = LdaModel(corpus=corpus, id2word=dictionary, num_topics=100)

          documents = lda_model[corpus]

          lda_model .save("data/model1.lsi")

          lda_model = models.LsiModel.load("data/model2.lsi")

4)RP(随即映射)

 目的在于减小空维度,通过随机性,近似的到文档之间的TFIDF距离,不过对于大数据量确实很慢,反正10万篇文档的数据我的小电脑是受不了

model=rpmodel.RpModel(corpus, num_topics=2)

 4.相似度匹配

  在得到文章对应的主题向量以后,就可以进行相似性匹配,我第一次是用在了长文本分类上,将多个文档遍历进行匹配,然后排序选择相似度最大的文章,取其在训练集中对应的分类编号,作为测试文档的类别。在单纯使用LSI向量,不加入TFIDF的情况下,准确率不高。

   如果单纯将corpus转化为LSI向量,主需要将测试文章用LSI模型转化一次:

   lsi_model = models.LsiModel(corpus, id2word=dictionary, num_topics=2)

  documents = lsi_model[corpus]  #训练数据转化为LSI向量

  query_vec = lsi_model[query]   #测试数据转化为LSI向量

  相似度匹配:

index = similarities.MatrixSimilarity(documents)

#网上说这个会占用大量的内存,如果内存不足可以改用similarities.Similarity

sims = index[query_vec]

predclass = listClasses[np.where(sims == np.max(sims))[0][0]]   #取对应训练数据的分类

 相似度矩阵的持久化(会生成多个文件,千万不要删除其中任何一个):

index.save('/data/deerwester.index')

index = similarities.MatrixSimilarity.load('/data/deerwester.index')

  如果加入TFIDF,在使用LSI,需要先转化为TFIDF向量,在转化为LSI向量

  tfidf_query = models.TfidfModel(query)

  query_vec = lsi_model[tfidf_query]

 5.转化为sklearn和scripy格式

     gensim的相似度匹配,用于文本分类时准确率不高,而在sklearn中有很多机器学习和深度学习算法,两者的数据格式不符。sklearn的输入和numpy和scripy相关,如果是密集矩阵,使用numpy.array格式,如果是稀疏矩阵,使用scipy.sparse.csr_matrix格式,可以去 scipy的官网查看相关文档,其中第四种方式比较简单:

def sparse2dense(lsi_corpus_total):

     data = []

     rows = []

     cols = []

     line_count = 0

     for line in lsi_corpus_total: # lsi_corpus_total 是之前由gensim生成的lsi向量

      for elem in line:

         rows.append(line_count)

         cols.append(elem[0])

         data.append(elem[1])

         line_count += 1

   lsi_sparse_matrix = csr_matrix(data, (rows,cols)) 

  其他方式

import gensim

import numpy as np

corpus = gensim.matutils.Dense2Corpus(numpy_matrix)

numpy_matrix = gensim.matutils.corpus2dense(corpus, num_terms=number_of_corpus_features)

import scipy.sparse

corpus = gensim.matutils.Sparse2Corpus(scipy_sparse_matrix)

scipy_csc_matrix = gensim.matutils.corpus2csc(corpus)

 

 

你可能感兴趣的:(gensim基础学习(一))