我需要一些帮助来优化 python 代码
Posted
技术标签:
【中文标题】我需要一些帮助来优化 python 代码【英文标题】:I need some help to optimize a python code 【发布时间】:2014-12-23 04:55:46 【问题描述】:我正在使用 Python 开发 KNN 分类器,但我遇到了一些问题。 以下代码需要 7.5s-9.0s 才能完成,我必须运行 60.000 次。
for fold in folds:
for dot2 in fold:
"""
distances[x][0] = Class of the dot2
distances[x][1] = distance between dot1 and dot2
"""
distances.append([dot2[0], calc_distance(dot1[1:], dot2[1:], method)])
“folds”变量是一个包含 10 个折叠的列表,总和包含 60.000 个 .csv 格式的图像输入。每个点的第一个值是它所属的类。所有值都是整数。 有没有办法让这条线跑得更快?
这里是calc_distance
函数
def calc_distancia(dot1, dot2, distance):
if distance == "manhanttan":
total = 0
#for each coord, take the absolute difference
for x in range(0, len(dot1)):
total = total + abs(dot1[x] - dot2[x])
return total
elif distance == "euclidiana":
total = 0
for x in range(0, len(dot1)):
total = total + (dot1[x] - dot2[x])**2
return math.sqrt(total)
elif distance == "supremum":
total = 0
for x in range(0, len(dot1)):
if abs(dot1[x] - dot2[x]) > total:
total = abs(dot1[x] - dot2[x])
return total
elif distance == "cosseno":
dist = 0
p1_p2_mul = 0
p1_sum = 0
p2_sum = 0
for x in range(0, len(dot1)):
p1_p2_mul = p1_p2_mul + dot1[x]*dot2[x]
p1_sum = p1_sum + dot1[x]**2
p2_sum = p2_sum + dot2[x]**2
p1_sum = math.sqrt(p1_sum)
p2_sum = math.sqrt(p2_sum)
quociente = p1_sum*p2_sum
dist = p1_p2_mul/quociente
return dist
编辑: 至少对于“manhanttan”方法,找到了一种使其更快的方法。而不是:
if distance == "manhanttan":
total = 0
#for each coord, take the absolute difference
for x in range(0, len(dot1)):
total = total + abs(dot1[x] - dot2[x])
return total
我放了
if distance == "manhanttan":
totalp1 = 0
totalp2 = 0
#for each coord, take the absolute difference
for x in range(0, len(dot1)):
totalp1 += dot1[x]
totalp2 += dot2[x]
return abs(totalp1-totalp2)
abs()
调用很重
【问题讨论】:
这里有几个链接可能会有所帮助:wiki.python.org/moin/PythonSpeed/PerformanceTipsnbviewer.ipython.org/github/rasbt/python_reference/blob/master/… 请编辑您的答案以包含整个代码。还包括输入(或至少部分输入)。 “优化python代码的一些帮助”不是这里的主题问题。 稍后我将不得不发布代码。我不确定我是否可以发布所有这些,因为这是一项学校作业。我得问问我的老师我能不能做到。他使用一个程序来验证抄袭。 同时,您是否考虑过(a)使用 NumPy 并重组您的程序,以便它可以在数组上按元素广播操作而不是循环,(b)在 PyPy 或其他一些 JIT 下运行基于实现而不是 CPython,或者 (c) 使用 Cython 编译内部循环? 【参考方案1】:“分析python”有很多指南;您应该搜索一些、阅读它们并完成分析过程,以确保您知道您的工作的哪些部分花费的时间最多。
但如果这真的是您工作的核心,那么可以肯定calc_distance
是消耗大部分运行时间的地方。
深度优化可能需要使用NumPy 加速数学或类似的低级方法。
作为一种需要较少侵入性分析和重写的快速而肮脏的方法,请尝试安装 Python 的 PyPy 实现并在其下运行。与标准 (CPython) 实现相比,我已经看到了 2 倍或更多的简单加速。
【讨论】:
【参考方案2】:我很困惑。您是否尝试过探查器?
python -m cProfile myscript.py
它将向您显示大部分时间都在哪里消耗,并提供可使用的硬数据。例如。重构以减少调用次数,重构输入数据,用这个函数代替那个,等等。
https://docs.python.org/3/library/profile.html
【讨论】:
我和我的老师谈过,他说时机成熟了。这需要很多时间。我使用了这些论点,它们对我有很大帮助。函数“calc_distance”需要大量时间来处理。我会努力让它更快。 你可以用 numpy array/s 改进很多。【参考方案3】:首先,您应该避免使用单个calc_distance
函数,该函数在每次调用时在字符串列表中执行线性搜索。定义独立的距离函数并调用正确的函数。正如 Lee Daniel Crocker 建议的那样,不要使用切片,只需从 1 开始循环范围即可。
对于余弦距离,我建议对所有点向量进行一次归一化。这样距离计算就减少到点积了。
这些微优化可以为您带来一些加速。但是通过切换到更好的算法应该可以获得更好的收益:kNN 分类器调用kD-tree,这将允许您快速从考虑中删除大部分点。
这更难实现(您必须稍微适应不同的距离;余弦距离会使它变得棘手。)
【讨论】:
以上是关于我需要一些帮助来优化 python 代码的主要内容,如果未能解决你的问题,请参考以下文章
在python中尝试使用mapreduce的程序,并需要一些帮助