Python:高效实现特征向量
我正在为一组文档实现特征向量,使用的是位图的方式。我已经有了整个文档集合的词汇表(以列表或集合的形式),还有每个文档中的词语列表。
举个例子,如果整个文档集合的词汇表是 ['a', 'b', 'c', 'd']
,而文档 d1 中的词语是 ['a', 'b', 'd', 'd']
,那么 d1 的特征向量应该是 [1, 1, 0, 2]
。
为了生成特征向量,我会遍历整个词汇表,检查每个词是否在文档的词语列表中,然后在特征向量的正确位置上设置相应的值。
那么,最有效的实现方法是什么呢?我考虑了一些方案:
- 使用
set
可以让检查词汇是否存在变得非常高效,但set
是无序的,而特征向量的值需要按照排序后的词汇表的顺序排列。 - 使用
dict
来存储词汇表(将每个词汇映射到一个任意值,比如1
)可以让我通过sorted(dict.keys())
来遍历,这样我就能跟踪索引。不过,这样会占用额外的空间来存储dict.values()
。 - 使用
sorted(list)
来检查词汇是否存在会效率很低。
StackOverflow 会有什么建议呢?
1 个回答
2
我觉得最有效的方法是遍历每个文档中的词,找到这些词在(已排序的)语料库中的位置,然后相应地设置标记。
已排序的语料库词汇表可以存储为一个字典,里面有 词 -> 索引
的映射(基本上就是一个倒排索引)。
你可以这样创建:
corpus = dict(((term, index) for index, term in enumerate(sorted(all_words))))
对于每个文档,你需要生成一个全是 0
的列表,作为特征向量:
num_words = len(corpus)
fvs = [[0]*num_words for _ in docs]
然后构建特征向量的过程是:
for i, doc_terms in enumerate(docs):
fv = fvs[i]
for term in doc_terms:
fv[corpus[term]] += 1
在测试某个词是否存在时没有额外的开销,你只需要遍历所有文档中的所有词。
说到这里,根据语料库的大小,你应该看看numpy和scipy。很可能你会遇到内存问题,而scipy提供了专门的稀疏矩阵数据类型(而不是使用列表的列表),这可以节省很多内存。
你可以使用上面提到的方法,但不是把数字加到列表元素中,而是加到矩阵元素中(例如,行代表文档,列代表语料库中的词)。
如果你想应用局部或全局加权方案,还可以利用numpy提供的一些矩阵操作。
希望这些能帮助你入门 :)