Python: 提高class中的欧式距离计算速度
Python: Improve the speed of Euclidean distance calculation in a class
我有一个 class 组件,用于计算 2 个字典中数组中最后一个元素之间的欧氏距离。一个字典包含 blob 的跟踪轨迹 (r
),另一个字典包含 blob 的更新值 (b
)。 class 的方法根据欧氏距离找到出现或消失的轨迹。最后,他们将 r
字典重新排序为与 b
字典的最佳匹配。
我测试了这个 colab notebook 中的功能,它按预期工作,但是当我在我的代码中实现它时,程序变慢了。
- 有什么方法可以提高这个 class 的速度?
- 有没有更好的方法来解决这个问题?这是什么?
谢谢。
from scipy.spatial import distance as dist
class finder:
def disappeared(self,r,b):
values = {}
indexes = {}
diss = {}
new_results = {}
new_positions = {}
le = len(r) - len(b)
for i in r:
xr = r[i]["x"][-1]
yr = r[i]["y"][-1]
for k in b:
xb = b[k]["x"][-1]
yb = b[k]["y"][-1]
D = dist.cdist([(xb,yb)],[(xr,yr)])
values[str(i) +"/" + str(k)] = D
indexes[str(i) +"/" + str(k)] = (i,k)
if le > 0:
le -= 1
maxval = max(values,key=values.get)
r_ind = indexes[maxval][0]
b_ind = indexes[maxval][1]
print("Found Disappeared", maxval)
diss[r_ind] = r[r_ind]
else:
minval = min(values,key=values.get)
r_ind = indexes[minval][0]
b_ind = indexes[minval][1]
new_positions[b_ind] = r[r_ind]
del values[minval]
for m,n in enumerate(new_positions):
new_results[m] = new_positions[n]
return(new_results,diss)
def appeared(self,r,b):
values = {}
indexes = {}
appr = {}
new_results = {}
new_positions = {}
le = len(b) - len(r)
for i in b:
xb = b[i]["x"][-1]
yb = b[i]["y"][-1]
for k in r:
xr = r[k]["x"][-1]
yr = r[k]["y"][-1]
D = dist.cdist([(xr,yr)],[(xb,yb)])
values[str(k) +"/" + str(i)] = D
indexes[str(k) +"/" + str(i)] = (k,i)
if le > 0:
le -= 1
maxval = max(values,key=values.get)
r_ind = indexes[maxval][0]
b_ind = indexes[maxval][1]
print("Found Appeared", maxval)
appr[b_ind] = b[b_ind]
new_positions[r_ind] = b[b_ind]
else:
minval = min(values,key=values.get)
r_ind = indexes[minval][0]
b_ind = indexes[minval][1]
new_positions[b_ind] = r[r_ind]
del values[minval]
for m,n in enumerate(new_positions):
new_results[m] = new_positions[n]
return(new_results)
这段代码真的有效吗?这些行看起来完全错误:
for i in r:
xr = r[i]["x"][-1]
yr = r[i]["y"][-1]
i
是这里 r
的一个元素。您不会将其用作 r
的索引。当然应该是:
for i in r:
xr = i["x"][-1]
yr = i["y"][-1]
for k in b
循环也是如此。
大部分时间可能都花在了访问字典和格式化字符串上。
这里有一些您可以优化的地方 disappeared()
:
仅访问 b
的值一次:
# at start of function ...
lastB = [ (k,v["x"][-1],v["y"][-1]) for k,v in b.items() ]
...
for k,xb,yb in lastB: # replaces for k in b: and the assignments of xb,yb
...
访问时获取值连同键 r
:
for i,v in r.items():
xr = v["x"][-1]
yr = v["y"][-1]
对 values
使用元组而不是字符串,您根本不需要 indexes
:
# index it with a tuple
values[(k,i)] = D
...
# replace the whole maxval logic.
r_ind,b_ind,_ = max(values.items(),key=lambda kv:kv[1])
...
# replace the whole minval logic.
r_ind,b_ind,_ = min(values.items(),key=lambda kv:kv[1])
...
del values[r_ind,b_ind]
生成新结果而不重新访问每个键:
new_result = dict(enumerate(new_positions.values()))
可以对 appeared()
进行相同的改进,因为它几乎相同。
我有一个 class 组件,用于计算 2 个字典中数组中最后一个元素之间的欧氏距离。一个字典包含 blob 的跟踪轨迹 (r
),另一个字典包含 blob 的更新值 (b
)。 class 的方法根据欧氏距离找到出现或消失的轨迹。最后,他们将 r
字典重新排序为与 b
字典的最佳匹配。
我测试了这个 colab notebook 中的功能,它按预期工作,但是当我在我的代码中实现它时,程序变慢了。
- 有什么方法可以提高这个 class 的速度?
- 有没有更好的方法来解决这个问题?这是什么?
谢谢。
from scipy.spatial import distance as dist
class finder:
def disappeared(self,r,b):
values = {}
indexes = {}
diss = {}
new_results = {}
new_positions = {}
le = len(r) - len(b)
for i in r:
xr = r[i]["x"][-1]
yr = r[i]["y"][-1]
for k in b:
xb = b[k]["x"][-1]
yb = b[k]["y"][-1]
D = dist.cdist([(xb,yb)],[(xr,yr)])
values[str(i) +"/" + str(k)] = D
indexes[str(i) +"/" + str(k)] = (i,k)
if le > 0:
le -= 1
maxval = max(values,key=values.get)
r_ind = indexes[maxval][0]
b_ind = indexes[maxval][1]
print("Found Disappeared", maxval)
diss[r_ind] = r[r_ind]
else:
minval = min(values,key=values.get)
r_ind = indexes[minval][0]
b_ind = indexes[minval][1]
new_positions[b_ind] = r[r_ind]
del values[minval]
for m,n in enumerate(new_positions):
new_results[m] = new_positions[n]
return(new_results,diss)
def appeared(self,r,b):
values = {}
indexes = {}
appr = {}
new_results = {}
new_positions = {}
le = len(b) - len(r)
for i in b:
xb = b[i]["x"][-1]
yb = b[i]["y"][-1]
for k in r:
xr = r[k]["x"][-1]
yr = r[k]["y"][-1]
D = dist.cdist([(xr,yr)],[(xb,yb)])
values[str(k) +"/" + str(i)] = D
indexes[str(k) +"/" + str(i)] = (k,i)
if le > 0:
le -= 1
maxval = max(values,key=values.get)
r_ind = indexes[maxval][0]
b_ind = indexes[maxval][1]
print("Found Appeared", maxval)
appr[b_ind] = b[b_ind]
new_positions[r_ind] = b[b_ind]
else:
minval = min(values,key=values.get)
r_ind = indexes[minval][0]
b_ind = indexes[minval][1]
new_positions[b_ind] = r[r_ind]
del values[minval]
for m,n in enumerate(new_positions):
new_results[m] = new_positions[n]
return(new_results)
这段代码真的有效吗?这些行看起来完全错误:
for i in r:
xr = r[i]["x"][-1]
yr = r[i]["y"][-1]
i
是这里 r
的一个元素。您不会将其用作 r
的索引。当然应该是:
for i in r:
xr = i["x"][-1]
yr = i["y"][-1]
for k in b
循环也是如此。
大部分时间可能都花在了访问字典和格式化字符串上。
这里有一些您可以优化的地方 disappeared()
:
仅访问 b
的值一次:
# at start of function ...
lastB = [ (k,v["x"][-1],v["y"][-1]) for k,v in b.items() ]
...
for k,xb,yb in lastB: # replaces for k in b: and the assignments of xb,yb
...
访问时获取值连同键 r
:
for i,v in r.items():
xr = v["x"][-1]
yr = v["y"][-1]
对 values
使用元组而不是字符串,您根本不需要 indexes
:
# index it with a tuple
values[(k,i)] = D
...
# replace the whole maxval logic.
r_ind,b_ind,_ = max(values.items(),key=lambda kv:kv[1])
...
# replace the whole minval logic.
r_ind,b_ind,_ = min(values.items(),key=lambda kv:kv[1])
...
del values[r_ind,b_ind]
生成新结果而不重新访问每个键:
new_result = dict(enumerate(new_positions.values()))
可以对 appeared()
进行相同的改进,因为它几乎相同。