我正在研究Python编程。 问题是我的代码太慢,无法在几天内获取数据。
我的代码如下。而词典数据就像这样; dic [0] = ['happy',100,[1234,1245,1515,1785,...... up to 100]]也就是说,dic [0] [1]表示dic [0]的长度[2] ]。我想要做的是计算DICE系数(单词相似度)(dic [i] [0]表示一个单词(在上面的例子中,'happy'),dic [i] [1]表示dic [i]的长度] [2](只是len(dic [i] [2])),dic [i] [2]表示该单词(dic [i] [0])出现的行号列表。这里的行仅表示语料库中的行号)
以这种方式计算DICE系数:句子中两个单词(word1,word2)的出现次数/(word1的总出现次数+ word2的总出现次数)。
总数据很大。我的程序已经工作了2天..但还没有结果......我必须尽快使用结果,因为这项工作的截止日期是下周...
我可以立即实施任何替代(更好)的算法吗? 谢谢。
for j in range(len(dic)):
for k in range(len(dic)):
score_temp = 0
for r in range(len(dic[j][2])):
if(dic[j][2][r] in dic[k][2]):
score_temp += 1
score_final = float(score_temp) / (dic[j][1] + dic[k][1])
dice_cursor.execute('insert into dices values(?,?,?)', (dic[j][0], dic[k][0], score_final))
答案 0 :(得分:3)
问题不是你的算法;这是你的数据结构。
如果我了解您的问题,则必须迭代所有j, k
组合;根本没有办法解决这个问题。因此,可能的最佳算法将是dic
的长度的二次方。
然而,对于每一对,您反复为dic[j][2][r] in dic[k][2]
进行一系列线性搜索。 部分是不必要的。如果您只是将每个dic[*][2]
列表更改为集合,则相同的查找将立即生效。
因此,代替O(N^2 * M^2)
,其中N
的长度为dic
,而M
的长度为dic[*][2]
的{平均值?},&#{1}} 39;将是O(N^2 * M)
。仍然很慢,但速度要快得多。
您还没有向我们展示您构建此巨型列表的位置,因此我无法向您展示如何以不同方式构建它...但通常只需要从{{1}开始并调用set()
而不是以.add
开头并调用[]
。
或者,如果您无法改变其构建方式,您可以随时更改它:
.append
我在这里假设你没有计算两次重复。如果您应该这样做,我认为您做错了 - 您计算dic = [[a, b, set(c)] for a, b, c in dic]
中的重复项,而不是j
中的重复项。但无论如何,你可以通过使用" multiset"来解决这个问题。类型;通常k
是最简单的方法。
您还可以通过使用集合交集而不是迭代一个集合来检查另一个集合,使其更简单(尽管只是更快一点)。而不是:
collections.Counter
......这样做:
for r in range(len(dic[j][2])):
if(dic[j][2][r] in dic[k][2]):
temp_score += 1
虽然我们不是在做temp_score += len(dic[j][2] & dic[k][2])
,而是在整个地方使用for j in range(len(dic))
,但您可以使用dic[j]
并使用for x in dic
。像这样:
x
或者,更简洁:
for x in dic:
for y in dic:
score_temp = len(x[2] & y[2])
score_final = float(score_temp) / (x[1] + y[1])
dice_cursor.execute('insert into dices values(?,?,?)',
(x[0], y[0], score_final))
答案 1 :(得分:1)
您的代码存在很多问题:
由于你正在使用range()
迭代你的dict的键,从0开始,看起来你最好只使用一个列表,实际上,这只是一个整数的映射到值,其中整数是连续的并从0开始。此外,键似乎在您的代码中没有扮演其他角色,而是为了解决词典中的条目。这意味着,您根本不必迭代range()
。相反,你应该像这样迭代(假设你使用列表而不是字典):
for a in the_list:
for b in the_list:
...
for value in a[2]:
if value in b[2]:
...
尽管如此,这只是稍好一些。如果您可以使用集合而不是列表作为数据中的第三个条目,那会更好。列表上的in
运算符的时间复杂度为O(n)。在套装上它平均只有O(1)。此外,您可以使用标准库中的正确功能。然后你会得到这样的东西:
from itertools import combinations
the_list = [
['happy', 100, set([<100 elements>)]],
['unhappy', 90, set([<90 elements>)]],
['green', 120, set([<120 elements>)]],
['red', 50, set([<50 elements>)]],
...
]
for a, b in combinations(the_list, 2):
score = len(a[2] & b[2])
dice_cursor.execute('insert into dices values(?,?,?)', (a[0], b[0], score))
dice_cursor.execute('insert into dices values(?,?,?)', (b[0], a[0], score))
# now the pairings we didn't generate so far:
for a in the_list:
dice_cursor.execute('insert into dices values(?,?,?)', (a[0], a[0], len(a[2])))