我正在构建我在SVM中使用的n-gram训练向量。我运行了我的代码,但是我花了太多时间,超过10个小时。你有什么方法可以让它更快吗?
def wordNgrams(s,n):
"""Calculate word n-grams and return a dictionary"""
input = s.split(' ')
output = {}
for i in xrange(len(input)-n+1):
g = " ".join(input[i:i+n]).lower()
output.setdefault(g,0)
output[g] += 1
return output
res是10000个字符串的列表,每个字符串平均有300个字。 global_vector是一个200000字2-gram的排序列表。
X = []
for i in xrange(10000):
word_dic = wordNgrams(res[i], 2)
vector1 = {key : 1 if key in word_dic else 0 for key in global_vector}
od = OrderedDict(sorted(vector1.items(), key = lambda t : t[0]))
X.append(od.values())
说实话,如果需要2或3个小时,这是很常见的。但它花了我超过10个小时。我真的不应该做我应该做的事。请帮我。
答案 0 :(得分:1)
我认为你在循环中运行的sorted
调用是唯一可以优化的东西。其他所有东西似乎都是渐近最优的(可能有可能通过不同地方的小因素来改善,但不是大量的)。
如果您的global_vector
已经排序,您可以通过直接创建结果列表来避免对结果进行排序,而不是先通过无序字典。这是一个使用列表理解的快速版本:
X = []
for text in res:
word_dic = wordNgrams(text, 2)
X.append([1 if bigram in word_dic else 0 for bigram in global_vector])
这应该是O(M*N) + O(M*P)
,其中M
是res
的长度,N
是global_vector
的长度,P
是平均值文本的长度。由于额外的排序,您的原始代码在第一个字词中包含额外的log(N)
因子。