【问题标题】:Python: Improve the speed of Euclidean distance calculation in a classPython:提高类中欧几里得距离计算的速度
【发布时间】:2021-05-28 13:34:55
【问题描述】:

我有一个类组件,它计算 2 个字典中数组中最后一个元素之间的欧几里得距离。一个字典包含 blob 的跟踪轨迹(r),另一个字典包含 blob 的更新值(b)。该类的方法根据欧几里得距离寻找出现或消失的轨迹。最后,他们根据与b 字典的最佳匹配对r 字典重新排序。

我测试了colab notebook 中的功能,它按预期工作,但是当我在我的代码上实现它时,程序变慢了。

  1. 有什么方法可以提高这门课的速度吗?
  2. 有没有更好的方法来解决这个问题?它是什么?

谢谢。

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)

【问题讨论】:

  • 我不止一次在我的程序的慢速部分出错。尝试用(错误的)快速和肮脏的方法替换它,并检查它确实是慢的部分。
  • 好的,我下载了你的代码并试了一下。唯一需要时间的是加载 scipy 模块,这是巨大的。一旦scipy 在内存中,程序的其余部分就会立即执行。第一次运行需要几秒钟。成功运行不需要时间。
  • @TimRoberts 谢谢,所以问题可能出在我执行的时候。我会检查的。
  • @user3184950 我会试试的。谢谢。

标签: python performance dictionary for-loop euclidean-distance


【解决方案1】:

大部分时间可能都花在了访问字典和格式化字符串上。

您可以采取以下措施来优化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() 进行相同的改进,因为它几乎相同。

【讨论】:

    【解决方案2】:

    这段代码真的有效吗?这些行看起来完全错误:

           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 循环也是如此。

    【讨论】:

    • 请检查 colab notebook,代码有效。 i 返回列表字典的索引。
    • dic = {1:{"x":[1,2,3]},2:{"x":[4,5,6]}} for i in dic: print(i)#1, 2
    • 你是对的,当然。当 r 是 dict 时,for i in r 返回键。
    猜你喜欢
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 2020-11-29
    • 2018-02-14
    • 1970-01-01
    • 2013-04-07
    • 2021-01-31
    • 2015-09-23
    相关资源
    最近更新 更多