python中最有效的直方图代码
我已经看到了一些关于在干净的一行程序中制作直方图的问题,但我还没有发现有人试图尽可能高效地制作直方图。我目前正在为一个搜索算法创建很多tfidf向量,这涉及到创建大量直方图和我当前的代码,而非常简短和可读性并没有我想要的那么快。可悲的是,我尝试了许多其他方法,结果慢得多。你能快点吗?cleanStringVector是一个字符串列表(全小写,无标点符号),masterWordList也是一个单词列表,应该包含cleanStringVector中的每个单词python中最有效的直方图代码,python,performance,histogram,tf-idf,Python,Performance,Histogram,Tf Idf,我已经看到了一些关于在干净的一行程序中制作直方图的问题,但我还没有发现有人试图尽可能高效地制作直方图。我目前正在为一个搜索算法创建很多tfidf向量,这涉及到创建大量直方图和我当前的代码,而非常简短和可读性并没有我想要的那么快。可悲的是,我尝试了许多其他方法,结果慢得多。你能快点吗?cleanStringVector是一个字符串列表(全小写,无标点符号),masterWordList也是一个单词列表,应该包含cleanStringVector中的每个单词 from collections imp
from collections import Counter
def tfidfVector(cleanStringVector, masterWordList):
frequencyHistogram = Counter(cleanStringVector)
featureVector = [frequencyHistogram[word] for word in masterWordList]
return featureVector
值得注意的是,计数器对象为不存在的键返回零,而不是引发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
使用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
我认为循环浏览主单词列表是一个问题。每次制作直方图时,都必须对主单词列表中的每个单词进行散列(大多数散列都丢失了,返回0的计算代价很高) 我会先对主单词列表进行散列,然后使用该散列创建每个直方图,这样您只需要对stringvector中的每个单词进行散列(两次,一次获取计数,一次重置主单词列表散列)。如果StringVector小于主单词列表,则会导致哈希操作大大减少:
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()应该是稳定的,只要我们不添加键。cleanStringVector是什么样子的?哦,它只是一个字符串列表。现在是一个简单的python列表,但如果您愿意,可以假设它是一个numpy数组。您对这些方法进行了基准测试吗?我已经运行了大多数方法,而不是所有方法。我删除了一些完全不可读的内容。这似乎是其中最快的,但还是很慢。你看到了吗?虽然关于信件,这些方法可能很有用。我在回答中试图实现的想法是一样的。。但是要优雅得多(也许更快),哦,太棒了。在调用它的代码中对缓存局部性做了一些小的调整,并设法将速度提高了20倍左右。我喜欢这个想法,但它比当前的实现慢得多。(大约需要两倍的时间)是的,我刚刚检查过,使用
orderedict
比使用dict
慢10倍,而且没有必要,在没有orderedict
的情况下进行测试这接近Thomas Jung的答案,但仍然有点慢。