简体   繁体   English

Python:提高 class 中欧几里得距离计算的速度

[英]Python: Improve the speed of Euclidean distance calculation in a class

I have a class component that calculates the Euclidean distance between the last elements in arrays within 2 dictionaries.我有一个 class 组件,用于计算 2 个字典中 arrays 中最后一个元素之间的欧几里得距离。 One dictionary contents the tracking trajectory of blobs ( r ), and the other have the updated values of the blobs( b ).一个字典包含 blob 的跟踪轨迹( r ),另一个字典包含 blob 的更新值( b )。 The methods of the class find the appeared or disappeared trajectories based on Euclidean distance. class的方法基于欧几里得距离寻找出现或消失的轨迹。 Finally, they reorder the r dictionary on their best match with the b dictionary.最后,他们将r字典重新排序为与b字典的最佳匹配。

I tested the functionality in this colab notebook and it works as expected, but when I implement it on my code the program gets slow.我测试了这个colab 笔记本中的功能,它按预期工作,但是当我在我的代码上实现它时,程序变慢了。

  1. Is there I way I can improve the speed of this class?有没有办法可以提高这个 class 的速度?
  2. Is there a better approach to solve this problem?有没有更好的方法来解决这个问题? What is it?它是什么?

Thank you.谢谢你。

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)

Most of the time is probably spent accessing dictionaries and formatting strings.大部分时间可能都花在访问字典和格式化字符串上。

Here are a few things you could do to optimize disappeared() :这里有一些你可以做的事情来优化disappeared()

Access values of b only once:只访问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
     
     ...

Obtain values along with keys when accessing r :访问r时获取值和键:

 for i,v in r.items():
     xr = v["x"][-1]
     yr = v["y"][-1]

Use tuples instead of strings for values and you won't need indexes at all:使用元组而不是字符串作为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]     

Generate new result without re-accessing each key:无需重新访问每个键即可生成新结果:

 new_result = dict(enumerate(new_positions.values()))

The same improvements can be made to appeared() , as it is almost identical.可以对appeared()进行相同的改进,因为它几乎是相同的。

Does this code actually work?这段代码真的有效吗? These lines look totally wrong:这些行看起来完全错误:

       for i in r:
            xr = r[i]["x"][-1]
            yr = r[i]["y"][-1]

i is an element of r here. ir的元素。 You wouldn't use that as an index into r .您不会将其用作r的索引。 Surely it's supposed to be:当然应该是:

       for i in r:
            xr = i["x"][-1]
            yr = i["y"][-1]

and the same for the for k in b loop.对于for k in b循环也是如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM