【发布时间】:2019-09-15 03:11:55
【问题描述】:
我想找到一种方法来更快地计算成对精度,即比较同一数组的元素(在本例中是 panda df 列)计算它们的差异,然后比较获得的两个结果。我将有一个数据框 df 与 3 列(id 的文档,Jugment 代表人类评估,它是一个 int 对象,PR_score 代表该文档的 pagerank 并且它是一个浮动对象),我想检查他们是否同意将一个文档更好/最差地分类另一个文档。
例如:
id:id1、id2、id3
判断 : 1, 0, 0
PR_score:0.18、0.5、0.12
在这种情况下,两个分数一致认为 id1 比 id3 更好,在 id1 和 id2 上不一致,并且 id2 和 id3 之间存在人为判断关系,因此我的成对准确度是:
协议 = 1
不同意 = 1
成对准确度 = 一致/(一致+不一致)=1/2 = 0.5
这是我的第一个解决方案的代码,其中我使用 df 的列作为数组(这有助于减少计算时间):
def pairwise(agree, disagree):
return(agree/(agree+disagree))
def pairwise_computing_array(df):
humanScores = np.array(df['Judgement'])
pagerankScores = np.array(df['PR_Score'])
total = 0
agree = 0
disagree = 0
for i in range(len(df)-1):
for j in range(i+1, len(df)):
total += 1
human = humanScores[i] - humanScores[j] #difference human judg
if human != 0:
pr = pagerankScores[i] - pagerankScores[j]#difference pagerank score
if pr != 0:
if np.sign(human) == np.sign(pr):
agree += 1 #they agree in which of the two is better
else:
disagree +=1 #they do not agree in which of the two is better
else:
continue;
else:
continue;
pairwise_accuracy = pairwise(agree, disagree)
return(agree, disagree, total, pairwise_accuracy)
我尝试使用列表推导以获得更快的计算,但它实际上比第一个解决方案慢:
def pairwise_computing_list_comprehension(df):
humanScores = np.array(df['Judgement'])
pagerankScores = np.array(judgmentPR['PR_Score'])
sign = [np.sign(pagerankScores[i] - pagerankScores[j]) == np.sign(humanScores[i] - humanScores[j] )
for i in range(len(df)) for j in range(i+1, len(df))
if (np.sign(pagerankScores[i] - pagerankScores[j]) != 0
and np.sign(humanScores[i] - humanScores[j])!=0)]
agreement = sum(sign)
disagreement = len(sign) - agreement
pairwise_accuracy = pairwise(agreement, disagreement)
return(agreement, disagreement, pairwise_accuracy)
我无法在整个数据集上运行,因为它需要太多时间,我希望能在理想情况下在 1 分钟内完成计算。
在我的计算机上计算 1000 行的一小部分达到了这个性能:
代码1: 每个循环 1.57 秒 ± 3.15 毫秒(平均值 ± 标准偏差。7 次运行,每个循环 1 个)
代码2: 每个循环 3.51 秒 ± 10.7 毫秒(平均值 ± 标准偏差,7 次运行,每个循环 1 个)
【问题讨论】:
-
您的列表理解方法会变慢,因为它会创建一个不必要的列表,您稍后必须对其进行总结,此外,您还需要多次重新计算
pagerankScores[i] - pagerankScores[j]。在任何情况下,您的第一种方法是在原始、数字numpy.ndarray对象上使用像numba这样的工具可能会产生改进,尽管您仍然会遇到二次时间复杂度,因为您正在进行成对比较。或许您可以提供一些示例数据? -
从根本上说,使用 Python for 循环迭代
numpy.ndarray对象,尤其是使用for i in range(len(df)-1)会慢。尝试使用list对象和您的第一种方法df['Judgement'].values.tolist(),您可能会看到显着的改进,但使用numba可以做得更好 -
谢谢你,我采纳了你的建议,它奏效了。我使用列表而不是 numpy 数组的第一种方法,并在函数
@jit(nopython = True)之前用作 numba 包中的装饰器 jit。我的整个数据集(58krow)的最终解决方案只需几秒钟 -
如果使用
numba,请使用numpy数组! -
@kmario23 here you can find a sample of 100 row,我不知道是否有更好的方法来共享文件,如果有,请告诉我。顺便说一句,我不明白你怎么能只用一个循环来做这个比较。
标签: python python-3.x pandas performance numpy