python中最有效的直方图代码

时间:2013-05-23 13:29:26

标签: python performance histogram tf-idf

我已经看过很多关于在干净的单行中制作直方图的问题,但我还没有发现任何人试图尽可能高效地制作直方图。我目前正在为搜索算法创建大量的tfidf向量,这涉及创建一些直方图和我当前的代码,同时非常简短和可读性并不像我想的那么快。可悲的是,我已经尝试了许多其他方法,结果远慢得多。你能更快地完成吗? cleanStringVector是一个字符串列表(全部小写,没有标点符号),masterWordList也是应该包含cleanStringVector中每个单词的单词列表。

from collections import Counter
def tfidfVector(cleanStringVector, masterWordList):
    frequencyHistogram = Counter(cleanStringVector)
    featureVector = [frequencyHistogram[word] for word in masterWordList]
    return featureVector

值得注意的是,Counter对象为不存在的键返回零而不是引发KeyError这一事实是一个严重的问题,其他问题中的大多数直方图方法都无法通过此测试。

示例:如果我有以下数据:

["apple", "orange", "tomato", "apple", "apple"]
["tomato", "tomato", "orange"]
["apple", "apple", "apple", "cucumber"]
["tomato", "orange", "apple", "apple", "tomato", "orange"]
["orange", "cucumber", "orange", "cucumber", "tomato"]

以及:

的主要词汇表
["apple", "orange", "tomato", "cucumber"]

我想分别从每个测试用例中返回以下内容:

[3, 1, 1, 0]
[0, 1, 2, 0]
[3, 0, 0, 1]
[2, 2, 2, 0]
[0, 2, 1, 2]

我希望有所帮助。

近似最终结果:

Original Method: 3.213
OrderedDict: 5.529
UnorderedDict: 0.190

2 个答案:

答案 0 :(得分:2)

使用Python 3将我的无代表性微基准测试中的运行时间提高了1个数量级:

mapping = dict((w, i) for i, w in enumerate(masterWordList))

def tfidfVector(cleanStringVector, masterWordList):    
    featureVector = [0] * len(masterWordList)
    for w in cleanStringVector:
        featureVector[mapping[w]] += 1
    return featureVector

答案 1 :(得分:0)

我认为循环显示主Word列表是一个问题。每次进行直方图时,都必须对主单词列表中的每个单词进行散列处理(大多数这些散列都是缺失的,这是一种计算成本高的返回0的方法)。

我会首先对主词表进行哈希处理,然后使用该哈希创建每个直方图,这样你只需要对字符串向量中的每个字进行哈希处理(两次,一次获取计数,一次重置主词表哈希) 。如果字符串向量小于主字表,则结果是散列操作的次数少得多:

from itertools import repeat

stringvecs=[["apple", "orange", "tomato", "apple", "apple"],
["tomato", "tomato", "orange"],
["apple", "apple", "apple", "cucumber"],
["tomato", "orange", "apple", "apple", "tomato", "orange"],
["orange", "cucumber", "orange", "cucumber", "tomato"]]

m=["apple", "orange", "tomato", "cucumber"]

md = dict(zip(m, repeat(0)))

def tfidfVector(stringvec, md):
    for item in stringvec:
        md[item]+=1
    out=md.values()
    for item in stringvec:
        md[item]=0
    return out

for stringvec in stringvecs:
    print tfidfVector(stringvec, md)

注意:只要我们不添加密钥,md.values()就应该是稳定的。