主题模型Gensim入门系列之二:语料和向量空间

2024-08-24 01:48

本文主要是介绍主题模型Gensim入门系列之二:语料和向量空间,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

系列目录:

(1)主题模型Gensim入门系列之一:核心概念

(2)主题模型Gensim入门系列之二:语料和向量空间

(3)主题模型Gensim入门系列之三:主题和变换

(4)主题模型Gensim入门系列之四:文本相似度查询

————————————————————————————

 

本文主要介绍将文档(Document)转换为向量空间,同时介绍语料流(corpus streaming) 和通过多种格式存储到磁盘。

 

1、从字符串到向量

首先,假设作为字符串,有如下语料:

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",
]

该语料包含9个文档,每个文档包含1句话。

首先,和上一小节一样,将文档切分为词,并进行停止词和低频词的过滤(频率<=1)。

from pprint import pprint  # pretty-printer
from collections import defaultdict# 删除停止词和标点符号
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
]# 删除频率<=1的词
frequency = defaultdict(int)
for text in texts:for token in text:frequency[token] += 1texts = [[token for token in text if frequency[token] > 1]for text in texts
]pprint(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']]
"""

接下来就将预处理好的文档转换到向量空间,需要指出的是,文档转换成哪种向量空间取决于你想要提取到文档中的什么特性。以词袋向量(bag-of-word)为例,它忽略了单词出现在文档中的顺序,”你喜欢张三"和"张三喜欢你"会转换为同样的词袋向量,但是在一些对词序敏感的任务中,显然是不合适的。

作为示例,下面还是通过词袋模型进行说明,关于词袋模型,可以参考:01-gensim系列之一:核心概念

首先,利用原始的语料生成字典,并将字典保存成 .dict 文件。

from gensim import corpora
dictionary = corpora.Dictionary(texts)
dictionary.save('/tmp/test_corpora.dict')  # store the dictionary, for future reference
print(dictionary)#输出
"""
Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...)
"""

上述代码实际上是利用gensim.corpora.Dictionary类,输入原始的语料,生成语料的字典并保存。字典包含语料中的所有单词,每一个单词有一个独立的索引。

如果要查看词典中每个词的索引,可以通过以下代码:

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}
"""

有了词典之后,就可以把预处理后的语料转换为词袋向量,同时也可以将转换后的词袋向量保存成 .mm文件,方便以后加载使用:

corpus = [dictionary.doc2bow(text) for text in texts]
corpora.MmCorpus.serialize('/tmp/deerwester.mm', corpus)  # store to disk, for later use
print(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)]
]
"""

 

2、语料流(corpus streaming)—一次一个文档

在上面的小型样例语料的处理中,是一次性将语料加载到内存进行处理的。实际情况中,我们往往会碰到大规模的语料,难以一次性加载到内存。通常情况下,我们会把语料存储到一个文件中,文件的每一行代表一个文档,此时我们可以利用gensim进行逐行处理,代码如下:

class MyCorpus(object):def __iter__(self):for line in open('tmp/mycorpus.txt'):# assume there's one document per line, tokens separated by whitespaceyield dictionary.doc2bow(line.lower().split())

gensim 可以输入任何形式的语料,不限于list、dataframe、array等,只要是可迭代的对象,都可以作为gensim的输入。

接下来,就可以通过MyCorpus创建迭代器,该迭代器将语料中的文档逐条转换为词袋向量:

corpus_memory_friendly = MyCorpus()  # doesn't load the corpus into memory!
print(corpus_memory_friendly)#输出
<__main__.MyCorpus object at 0x7f2f3d6fcc50># 通过迭代的方式打印出每一条文档的词袋向量
for vector in corpus_memory_friendly:  # load one vector into memory at a timeprint(vector)# 输出
"""
[(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 six import iteritems# 对语料中的单词进行统计
dictionary = corpora.Dictionary(line.lower().split() for line in open('tmp/mycorpus.txt'))# 找出停止词的索引
stop_ids = [dictionary.token2id[stopword]for stopword in stoplistif stopword in dictionary.token2id
]once_ids = [tokenid for tokenid, docfreq in iteritems(dictionary.dfs) if docfreq == 1]
dictionary.filter_tokens(stop_ids + once_ids)  # remove stop words and words that appear only once
dictionary.compactify()  # remove gaps in id sequence after words that were removed
print(dictionary)# 输出
"""
Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...)
"""

 

3、语料格式

语料转化到向量空间之后可以保存成功多种格式的文件,方便后续调用。其中用的最多的格式为矩阵市场格式(Market Matrix format),一个保存的样例如下:

corpus = [[(1, 0.5)], []]  # 将一个文档设为空,just for fan
corpora.MmCorpus.serialize('/tmp/corpus.mm', corpus)

相应的,加载保存的语料代码如下:

corpus = corpora.MmCorpus('/tmp/corpus.mm')

其它的保存格式还包括 Joachim’s SVMlight 格式, Blei’s LDA-C 格式 and GibbsLDA++ 格式,相应的代码如下:

corpora.SvmLightCorpus.serialize('/tmp/corpus.svmlight', corpus)
corpora.BleiCorpus.serialize('/tmp/corpus.lda-c', corpus)
corpora.LowCorpus.serialize('/tmp/corpus.low', corpus)

加载的语料是一个流的对象,所以不能直接打印出转换后的文档,通过以下两个方法可以获取文档中的原始内容:

# 第1种方法,将整个语料加载到内存中
print(list(corpus))#输出
"""
[[(1, 0.5)], []]
"""# 第2种方法逐个加载,逐个打印,占用内存较小
for doc in corpus:print(doc)"""
[(1, 0.5)]
[]
"""

从上面的代码可以看出,gensim同样可以作为一种语料格式转换的工具,加载一种格式的语料,然后转换为另外一种格式的语料。

 

4、和 Numpy、Scipy的兼容性

Gensim 的语料可以从 Numpy或者scipy的矩阵中转换而来,它本身提供的简单易用的函数。一个示例代码如下:

import gensim
import numpy as np
numpy_matrix = np.random.randint(10, size=[5, 2])  # 作为示例的numpy随机矩阵# 将numpy矩阵转换为gensim的corpus
corpus = gensim.matutils.Dense2Corpus(numpy_matrix)# 将gensim的corpus转换为numpy的矩阵
numpy_matrix = gensim.matutils.corpus2dense(corpus, num_terms=number_of_corpus_features)

同样的,scipy矩阵和gensim corpus之间转换的示例代码如下:

import scipy.sparse# 作为样例的随机稀疏矩阵
scipy_sparse_matrix = scipy.sparse.random(5, 2)# 将scipy的稀疏矩阵转换为gensim的corpus
corpus = gensim.matutils.Sparse2Corpus(scipy_sparse_matrix)# 将gensim的corpus转换为scipy的稀疏矩阵
scipy_csc_matrix = gensim.matutils.corpus2csc(corpus)

 

翻译和编辑自:Corpora and Vector Spaces

这篇关于主题模型Gensim入门系列之二:语料和向量空间的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101102

相关文章

Ubuntu如何分配​​未使用的空间

《Ubuntu如何分配​​未使用的空间》Ubuntu磁盘空间不足,实际未分配空间8.2G因LVM卷组名称格式差异(双破折号误写)导致无法扩展,确认正确卷组名后,使用lvextend和resize2fs... 目录1:原因2:操作3:报错5:解决问题:确认卷组名称​6:再次操作7:验证扩展是否成功8:问题已解

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

MySQL之InnoDB存储页的独立表空间解读

《MySQL之InnoDB存储页的独立表空间解读》:本文主要介绍MySQL之InnoDB存储页的独立表空间,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、独立表空间【1】表空间大小【2】区【3】组【4】段【5】区的类型【6】XDES Entry区结构【

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Redis 配置文件使用建议redis.conf 从入门到实战

《Redis配置文件使用建议redis.conf从入门到实战》Redis配置方式包括配置文件、命令行参数、运行时CONFIG命令,支持动态修改参数及持久化,常用项涉及端口、绑定、内存策略等,版本8... 目录一、Redis.conf 是什么?二、命令行方式传参(适用于测试)三、运行时动态修改配置(不重启服务

MySQL DQL从入门到精通

《MySQLDQL从入门到精通》通过DQL,我们可以从数据库中检索出所需的数据,进行各种复杂的数据分析和处理,本文将深入探讨MySQLDQL的各个方面,帮助你全面掌握这一重要技能,感兴趣的朋友跟随小... 目录一、DQL 基础:SELECT 语句入门二、数据过滤:WHERE 子句的使用三、结果排序:ORDE

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求

苹果macOS 26 Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色

《苹果macOS26Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色》在整体系统设计方面,macOS26采用了全新的玻璃质感视觉风格,应用于Dock栏、应用图标以及桌面小部件等多个界面... 科技媒体 MACRumors 昨日(6 月 13 日)发布博文,报道称在 macOS 26 Tahoe 中