自然语言处理-gensim

Gensim入门

介绍

  GensimPython 的一个三方库,旨在从文档中自动提取语义主题,以及处理原始的非结构化数字文本(纯文本

  在Gensim 的算法,比如Word2VecFastText,潜在语义分析(LSILSASEELSIModel),隐含狄利克雷分布(LDA)等,自动训练文档,检查统计共生模式发现的文件的语义结构,这些算法是无监督的,这意味着不需要人工输入。

  一旦找到这些统计模式,任何纯文本文档(句子,短语,单词……)都可以在新的语义中简单的表达,并查询与其他文档的主题相似性。

从字符串到向量

  从表示为字符串的文档开始:

documents = [
    "Human machine interface for lab abc computer applications",
    "A survey of user opinion of computer system response time",
    "The EPS user interface management system",
    "System and human system engineering testing of EPS",
    "Relation of user perceived response time to error measurement",
    "The generation of random binary unordered trees",
    "The intersection graph of paths in trees",
    "Graph minors IV Widths of trees and well quasi ordering",
    "Graph minors A survey",
]

  这是一个由九个文档组成的小型语料库,每个文档只包含一个句子。

  首先,对文档进行标记,删除常用单词以及在语料库中仅出现一次的单词:

from gensim import corpora

# 指定停止词集合
stoplist = set('for a of the and to in'.split(" "))
# 判断每个单词是否在停止词集合中,如果不是,则将其加入到新闻本中
texts = [[word for word in document.lower().split() if word not in stoplist]
             for document in documents]

print(stoplist, texts)
{'for', 'of', 'the', 'a', 'and', 'in', 'to'} [['human', 'machine', 'interface', 'lab', 'abc', 'computer', 'applications'], ['survey', 'user', 'opinion', 'computer', 'system', 'response', 'time'], ['eps', 'user', 'interface', 'management', 'system'], ['system', 'human', 'system', 'engineering', 'testing', 'eps'], ['relation', 'user', 'perceived', 'response', 'time', 'error', 'measurement'], ['generation', 'random', 'binary', 'unordered', 'trees'], ['intersection', 'graph', 'paths', 'trees'], ['graph', 'minors', 'iv', 'widths', 'trees', 'well', 'quasi', 'ordering'], ['graph', 'minors', 'survey']]
from collections import defaultdict

# 得到每个单词出现的次数
frequency = defaultdict(int)
for text in texts:
    for token in text:
        frequency[token] += 1
frequency
defaultdict(int,
            {'human': 2,
             'machine': 1,
             'interface': 2,
             'lab': 1,
             'abc': 1,
             'computer': 2,
             'applications': 1,
             'survey': 2,
             'user': 3,
             'opinion': 1,
             'system': 4,
             'response': 2,
             'time': 2,
             'eps': 2,
             'management': 1,
             'engineering': 1,
             'testing': 1,
             'relation': 1,
             'perceived': 1,
             'error': 1,
             'measurement': 1,
             'generation': 1,
             'random': 1,
             'binary': 1,
             'unordered': 1,
             'trees': 3,
             'intersection': 1,
             'graph': 3,
             'paths': 1,
             'minors': 2,
             'iv': 1,
             'widths': 1,
             'well': 1,
             'quasi': 1,
             'ordering': 1})
# 去掉仅出现一次的单词
texts = [[token for token in text if frequency[token] > 1]
         for text in texts]
print(texts)
[['human', 'interface', 'computer'],
 ['survey', 'user', 'computer', 'system', 'response', 'time'],
 ['eps', 'user', 'interface', 'system'],
 ['system', 'human', 'system', 'eps'],
 ['user', 'response', 'time'],
 ['trees'],
 ['graph', 'trees'],
 ['graph', 'minors', 'trees'],
 ['graph', 'minors', 'survey']]

  接下来,调用API建立预料特征的索引字典,并将文本特征的原始表达转化为词袋模型对应的稀疏向量的表达:

import os

dictionary = corpora.Dictionary(texts)
if not os.path.exists('./tmp'):
    os.mkdir('./tmp')
dictionary.save('./tmp/deerwester.dict')
print(dictionary)
Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...)

  这里,为语料库中出现的所有单词分配了一个唯一的整数id gensim.corpora.dictionary.Dictionary。这会扫描文本,收集字数和相关统计数据。最后,我们看到在处理过的语料库中由12个不同的单词,这意味着每个文档将有12个数字表示(即12-D向量),要查看单词及其ID之间的映射:

print(dictionary.token2id)
{'computer': 0,
 'human': 1,
 'interface': 2,
 'response': 3,
 'survey': 4,
 'system': 5,
 'time': 6,
 'user': 7,
 'eps': 8,
 'trees': 9,
 'graph': 10,
 'minors': 11}

将标记化文档实际转换为向量:

new_doc = "Human computer interaction"
new_vec = dictionary.doc2bow(new_doc.lower().split())
print(new_vec)
[(0, 1), (1, 1)]

  因为interaction没有出现在字典中,所以没有返回它的值。

  doc2bow() 只计算每个不同单词的出现次数,将单词转化为整数单词id,并将结果作为稀疏向量返回。因此稀疏向量[(0, 1), (1, 1)] 读取:在文档**“Human computer interaction”**中,单词computer(id 0) 和 human(id 1) 出现一次,其他十个字典单词隐含的出现零次。

corpus = [dictionary.doc2bow(text) for text in texts]
corpora.MmCorpus.serialize('./tmp/deerwester.mm', corpus)
corpus
[[(0, 1), (1, 1), (2, 1)],
 [(0, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)],
 [(2, 1), (5, 1), (7, 1), (8, 1)],
 [(1, 1), (5, 2), (8, 1)],
 [(3, 1), (6, 1), (7, 1)],
 [(9, 1)],
 [(9, 1), (10, 1)],
 [(9, 1), (10, 1), (11, 1)],
 [(4, 1), (10, 1), (11, 1)]]

主题和转换

转换接口

from gensim import models, corpora, similarities

dictionary = corpora.Dictionary.load('./tmp/deerwester.dict')
corpus = corpora.MmCorpus('./tmp/deerwester.mm')

  对文本向量的变换是Gensim的核心。通过挖掘语料中隐藏的语义结构特征,我们最终可以变换出一个简洁高效的文本向量。

  在Gensim中,每一个向量变换的操作都对应着一个主题模型,例如上一小节提到的对应着词袋模型的doc2bow变换。每一个模型又都是一个标准的Python对象。下面以TF-IDF模型为例,介绍Gensim模型的一般使用方法。

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

tfidf = models.TfidfModel(corpus)

  corpus 是一个返回bow 向量的迭代器。这两行代码将完成对corpus中出现的每一个特征的IDF值的统计工作。

  接下来,我们可以调用这个模型将任意一段预料(依然是bow向量的迭代器)转化成TFIDF向量的迭代器,这里的bow向量必须与训练语料的bow向量共享同一个特征字典(即共享同一个向量空间)

doc_bow = [(0, 1), (1, 1)]
tfidf[doc_bow]
[(0, 0.7071067811865476), (1, 0.7071067811865476)]

  或者将转换应用于整个语料库

corpus_tfidf = tfidf[corpus]
for doc in corpus_tfidf:
    print(doc)
[(0, 0.5773502691896257), (1, 0.5773502691896257), (2, 0.5773502691896257)]
[(0, 0.44424552527467476), (3, 0.44424552527467476), (4, 0.44424552527467476), (5, 0.3244870206138555), (6, 0.44424552527467476), (7, 0.3244870206138555)]
[(2, 0.5710059809418182), (5, 0.4170757362022777), (7, 0.4170757362022777), (8, 0.5710059809418182)]
[(1, 0.49182558987264147), (5, 0.7184811607083769), (8, 0.49182558987264147)]
[(3, 0.6282580468670046), (6, 0.6282580468670046), (7, 0.45889394536615247)]
[(9, 1.0)]
[(9, 0.7071067811865475), (10, 0.7071067811865475)]
[(9, 0.5080429008916749), (10, 0.5080429008916749), (11, 0.695546419520037)]
[(4, 0.6282580468670046), (10, 0.45889394536615247), (11, 0.6282580468670046)]

  Gensim 内置了多种主题模型的向量变换,包括LDALSIRPHDP等。这些模型通常以bow向量或tfidf向量的语料为输入,生成相应的主题向量。所有的模型都支持流式计算。

文档相似度的计算

  在得到每一篇文档对应的主题向量后,我们就可以计算文档之间的相似度,进而完成如文本聚类,信息检索之类的任务。在Gensim中,也提供了这一类任务的API接口

  以信息检索为例。对于一篇待检索的query,我们的目标是从文本集合中检索出主题相似度最高的文档。

  首先,我们需要将待检索的query和文本放在同一个向量空间里表达(以LSI 向量空间为例):

lsi = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=2)
corpus_lsi = lsi[corpus_tfidf]

  用待检索的文档向量初始化一个相似度计算的对象:

index = similarities.MatrixSimilarity(lsi[corpus])

如果待检索的目标文档过多,使用similarities.MatrixSlimilarity类往往会带来内存不够的问题。此时,可以改用similarities.Similarity类。二者接口基本一致。

  通过潜在语义索引将我们的TF-IDF语料库转换为潜在的2D空间(设置了num_topics=2)。这两个潜在的维度代表为:

lsi.print_topics(2)
[(0,
  '0.703*"trees" + 0.538*"graph" + 0.402*"minors" + 0.187*"survey" + 0.061*"system" + 0.060*"time" + 0.060*"response" + 0.058*"user" + 0.049*"computer" + 0.035*"interface"'),
 (1,
  '-0.460*"system" + -0.373*"user" + -0.332*"eps" + -0.328*"interface" + -0.320*"response" + -0.320*"time" + -0.293*"computer" + -0.280*"human" + -0.171*"survey" + 0.161*"trees"')]

  根据LSI的说法,treesgraphminors都是相关词,且对第一个主题方向贡献最大。前五个文件与第二个主题关联性更强,而剩下四个文件与第一个主题相关:

for doc in corpus_lsi:
    print(doc)
[(0, 0.06600783396090293), (1, -0.5200703306361845)]
[(0, 0.19667592859142477), (1, -0.7609563167700054)]
[(0, 0.08992639972446376), (1, -0.7241860626752504)]
[(0, 0.07585847652178108), (1, -0.6320551586003421)]
[(0, 0.10150299184980141), (1, -0.5737308483002963)]
[(0, 0.7032108939378311), (1, 0.16115180214025757)]
[(0, 0.877478767311983), (1, 0.16758906864659354)]
[(0, 0.9098624686818575), (1, 0.1408655362871895)]
[(0, 0.6165825350569278), (1, -0.05392907566389435)]

1, -0.6320551586003421)]
[(0, 0.10150299184980141), (1, -0.5737308483002963)]
[(0, 0.7032108939378311), (1, 0.16115180214025757)]
[(0, 0.877478767311983), (1, 0.16758906864659354)]
[(0, 0.9098624686818575), (1, 0.1408655362871895)]
[(0, 0.6165825350569278), (1, -0.05392907566389435)]


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值