在Python中矢量化多维函数

时间:2014-08-11 23:31:37

标签: python arrays optimization numpy vectorization

我经常在Stack Overflow上潜伏一段时间,每当我遇到编码问题时,我都会从这里找到非常有用和清晰的信息。但是,我现在似乎无法找到解决我今天特定问题的线索。

今天早些时候,我了解了Python中的矢量化函数,以加快计算时间。我目前正在尝试优化一个月前编写的python程序。我的程序采用包含以下格式数据的文本文件:

<magnitude> <dmagnitude> <exposure_number>

然后我将每列分配到列表magdmagexpnum

我想要做的是创建共享相同mag的{​​{1}}和dmag值的二维数组(具有相同的曝光数量意味着expnum并且mag指向同一数据点)。

我为所有曝光数字执行此操作,最后,我采用dmagmag的中位数,以及每个曝光的dmag的标准偏差基于数字的数组并将它们组合成一个我可以绘制的数组。

目前,我有以下代码:

mag

然后我准备好from numpy import loadtxt,array,asarray,append,std,median,empty,take data = loadtxt(infile,usecols=(0,1,2)) mag = data1[:,2].tolist() dmag = data1[:,3].tolist() expnum = data1[:,4].tolist() #initialize variables indexing = list() master_mag = list() master_dmag = list() sub_mag = list() sub_dmag = list() mag_std = array([]) mag_stdmed = array([]) mag_med = array([]) while len(mag) > 0: num=expnum[0] for i in range(0,len(expnum)): if expnum[i] == num: sub_mag.append(mag[i]) sub_dmag.append(dmag[i]) indexing.append(i) #add the sub lists to their master lists master_mag.append(sub_mag) master_dmag.append(sub_dmag) sub_mag=list() sub_dmag=list() #remove from mag, dmag, and expnum the index referred to by indexing while len(indexing) > 0: mag.pop(indexing[-1]) dmag.pop(indexing[-1]) expnum.pop(indexing[-1]) indexing.pop() #make the master mag and dmag lists into numpy arrays master_mag=asarray(master_mag) master_dmag=asarray(master_dmag) #generate the mag and dmag median and mag std arrays for i in range(0,len(master_mag)): mag_std=append(mag_std,std(master_mag[i])) mag_med=append(mag_med,median(master_mag[i])) mag_stdmed=append(mag_stdmed,median(master_dmag[i])) #create empty numpy arrays to be used for mag med vs. mag std #and mag med vs. dmag med med_std=empty([0,2]) med_dmed=empty([0,2]) #fill in those arrays for i in range(0,len(mag_std)): med_std=append(med_std,[[mag_med[i],mag_std[i]]],axis=0) med_dmed=append(med_dmed,[[mag_med[i],mag_stdmed[i]]],axis=0) #sort the median mag and dmag standard deviation arrays by median mag order_med_std=med_std[:,0].argsort() order_med_dmed=med_dmed[:,0].argsort() sorted_med_std=take(med_std,order_med_std,0) sorted_med_dmed=take(med_dmed,order_med_dmed,0) sorted_med_dmed[:,0]sorted_med_dmed[:,1]sorted_med_std[:,0]

的关系

这段代码有效,只是我觉得它太慢了(特别是当我获得超过10,000个数据点时)。我想尝试对这段代码进行矢量化以使其更快,但我不知道从哪里开始。

我想帮助弄清楚如何对匹配的曝光数字组件进行矢量化。我想在开始时创建一个多维数组,其格式为:sorted_med_std[:,1],长度等于不同曝光数的数量。有没有办法在线生成和更新这样的数组,而不必使用大量的循环?

如果您需要进一步明确此代码的用途,请与我们联系。

感谢您的时间。

1 个答案:

答案 0 :(得分:2)

像这样的任何问题的第一步应始终是分析。我建议尝试line_profiler,因为这样可以直观地查找热点。 (您也可以尝试Python的内置探查器,但我发现它的输出更难解析。)

这应该可以让您了解哪些部分最能减慢代码速度。如果不自己尝试,我可以提供一些建议:

  • 当numpy数组足够时,尽量避免使用Python列表。如果你做了很多append,列表很快,但对于大多数其他操作来说速度很慢,而且它们不支持向量化。
  • 相关地,如果可以的话,尽量避免调用numpy.append。每次调用都涉及分配更多内存和复制,这在循环中可能非常慢。
  • 使用词典按键分组数据。我发现stdlib collections.defaultdict对于这样的分组非常有用:

    groups = defaultdict(list)
    for a,b,key in data:
      groups[key].append((a,b))
    
  • 使用numpy的自动向量化函数调用,而不是在循环中调用函数。例如,此代码:

    #generate the mag and dmag median and mag std arrays 
    for i in range(0,len(master_mag)): 
      mag_std=append(mag_std,std(master_mag[i])) 
      mag_med=append(mag_med,median(master_mag[i])) 
      mag_stdmed=append(mag_stdmed,median(master_dmag[i]))
    
    写作时,

    会快得多:

    mag_std = numpy.std(master_mag, axis=0)
    mag_meg = numpy.median(master_mag, axis=0)
    mag_stdmed = numpy.median(master_dmag, axis=0)