【问题标题】:How to evaluate execution time when using scipy.optimize?使用 scipy.optimize 时如何评估执行时间?
【发布时间】:2019-11-02 20:33:54
【问题描述】:

我正在编写一个使用scipy.optimize 中的minimize() 函数的python 脚本。该脚本运行良好,但速度相对较慢,我正在尝试弄清楚如何(a)找出时间花费在哪里)以便(b)加快速度。

我当前的“慢”基准我有一个实体数据集,其中每个实体包含约 5000 个样本(即,我需要 minimize() 5000 次/实体。我有大约 2000 个实体。我当前的运行时间在 35每个实体 -45 秒,所以我正在查看 80k 秒(或 22.2 小时)的总运行时间。如果它只是一次性的,这会很好,但这需要测试多个模型等。所以我需要降低运行时间。

脚本的主要部分如下:

###Initializing Export Arrays
Vmin1 = np.array([])
Vmin2 = np.array([])
Vmin3 = np.array([])
Vmin4 = np.array([])
Vmin5 = np.array([])
Vmin6 = np.array([])
Vclay = np.array([])
Vker = np.array([])


###Initial Estimate
x0 = np.array([0.5, 0.1, 0.1, 0.0, 0.01, 0.07, 0.2, 0.02,])
bounds = ((0,1), (0,1), (0,1), (0,1), (0,1), (0,1), (0,1), (0,1)) 

C =np.array([[rhob_Vmin1, rhob_Vmin2, rhob_Vmin3, rhob_Vmin4, rhob_Vmin5, rhob_Vmin6, rhob_Vclay, rhob_Vker],
              [nphi_Vmin1, nphi_Vmin2, nphi_Vmin3, nphi_Vmin4, nphi_Vmin5, nphi_Vmin6, nphi_Vclay, nphi_Vker],
              [pe_Vmin1, pe_Vmin2, pe_Vmin3, pe_Vmin4, pe_Vmin5, pe_Vmin6, pe_Vclay, pe_Vker],
              [dt_Vmin1, dt_Vmin2, dt_Vmin3, dt_Vmin4, dt_Vmin5, dt_Vmin6, dt_Vclay, dt_Vker],
              [0,0,0,0,0,0,1,0],
              [0,0,0,0,0,0,0,1],
              [1,1,1,1,1,1,1,1]])


def mineral_inversion(x, L, C):
    L_pred = np.matmul(C, x)
    if not np.isnan(L[0][0]):
        I1 = (np.subtract(L[0][0], L_pred[0])/unc_rhob)**2
    else:
        I1=0
    if not np.isnan(L[0][1]):
        I2 = (np.subtract(L[0][1], L_pred[1])/unc_nphi)**2
    else:
        I2 = 0
    if not np.isnan(L[0][2]):
        I3 = (np.subtract(L[0][2], L_pred[2])/unc_pe)**2
    else:
        I3 = 0
    if not np.isnan(L[0][3]):
        I4 = (np.subtract(L[0][3], L_pred[3])/unc_dt)**2
    else:
        I4 = 0
    if not np.isnan(L[0][4]):
        I5 = (np.subtract(L[0][4], L_pred[4])/unc_vwcl)**2
    else:
        I5 = 0
    if not np.isnan(L[0][5]):
        I6 = (np.subtract(L[0][5], L_pred[5])/unc_vker)**2    
    else:
        I6 = 0
    I7 = ((1-x.sum())/unc_unity)**2

    incoherence = I1+I2+I3+I4+I5+I6+I7
    return incoherence   

from datetime import datetime
t0 = datetime.now()
vpor_init = np.float(0.1)

for dd in range(len(depth)):

    ###Log values used in mineral inversion + unity value
    L = np.array([[rhob[dd], nphi[dd], pe[dd], dt[dd], vwcl[dd], vkero[dd], 1]])

    res = minimize(fun = mineral_inversion, x0 = x0, args = (L, C), bounds=bounds, method='SLSQP')
    Vmin1 = np.append(Vmin1, res.x[0])
    Vmin2 = np.append(Vmin2, res.x[1])
    Vmin3 = np.append(Vmin3, res.x[2])
    Vmin4 = np.append(Vmin4, res.x[3])
    Vmin5 = np.append(Vmin5, res.x[4])
    Vmin6 = np.append(Vmin6, res.x[5])    
    Vclay = np.append(Vclay, res.x[6])
    Vker = np.append(Vker,   res.x[7])

t1 = datetime.now()
time = t1-t0
print('Run Time: ', time)

目前我正在for 循环级别记录运行时间。然而,这并不能告诉我我的瓶颈可能在哪里。是否在mineral_inversion() 函数的级别,是否在minimize() 函数本身等等。

问题: (1) 我怎样才能巧妙地记录执行时间,以确定是否可以加快速度? (2)如果这实际上是“慢”或者我只是不合理并且有很多样本需要迭代,那么什么是公平的陈述方式? (3) 我是否有任何明显的不良做法/速度陷阱?

【问题讨论】:

  • 您是否尝试过“时间”来记录执行时间? import time since = time.time() # DO YOUR THING time_elapsed = time.time() - since print('\t{:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
  • 是的。如果你看一下代码,我几乎就是在循环级别做的。

标签: python numpy scipy scipy-optimize scipy-optimize-minimize


【解决方案1】:

试图弄清楚如何(a)弄清楚时间花在了哪里

使用标准库中的 pstats 模块进行函数级分析,使用 kernprof 进行行级分析。

在 jupyter notebook 中,它是 %prun 和 %lprun 魔法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 2014-09-14
    • 2017-11-16
    相关资源
    最近更新 更多