Python:高效实现特征向量

2 投票
1 回答
1988 浏览
提问于 2025-04-16 15:37

我正在为一组文档实现特征向量,使用的是位图的方式。我已经有了整个文档集合的词汇表(以列表或集合的形式),还有每个文档中的词语列表。

举个例子,如果整个文档集合的词汇表是 ['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

在测试某个词是否存在时没有额外的开销,你只需要遍历所有文档中的所有词。


说到这里,根据语料库的大小,你应该看看numpyscipy。很可能你会遇到内存问题,而scipy提供了专门的稀疏矩阵数据类型(而不是使用列表的列表),这可以节省很多内存。
你可以使用上面提到的方法,但不是把数字加到列表元素中,而是加到矩阵元素中(例如,行代表文档,列代表语料库中的词)。

如果你想应用局部或全局加权方案,还可以利用numpy提供的一些矩阵操作。

希望这些能帮助你入门 :)

撰写回答