Scipy's curve_fit / наименьший квадрат становится медленнее, когда задан якобиан?

Поэтому я прочитал документацию о curve_fit здесь . Он содержит следующий пример:

import numpy as np
import scipy.optimize as so

def func(x, a,b,c ):
    return a * np.exp(-b * x) + c

a,b,c = 2.5, 1.3, 0.5
nx = 500
noiseAlpha = 0.5
#
xdata = np.linspace(0, 4, nx)
y = func(xdata, a,b,c)
ydata = y + noiseAlpha * np.random.normal(size=len(xdata))

Если я сейчас вызову curve_fit, он аппроксимирует производные, поскольку я ничего не предоставлял. Рассчитаем время:

%%timeit
popt, pcov = so.curve_fit(func, xdata, ydata )
1000 loops, best of 3: 787 µs per loop

Фактически curve_fit вызывает leastsq (doc здесь), который принимает аргумент Dfun для вычисления якобиана. Итак, я сделал это:

def myDfun( abc, xdata, ydata, f ) :
    a,b,c = abc
    ebx = np.exp(-b * xdata)
    res = np.vstack( ( ebx, a * -xdata * ebx, np.ones(len(xdata)) ) ).T
    return res

И я снова засекал:

%%timeit
popt, pcov = so.curve_fit(func, xdata, ydata, Dfun=myDfun )
1000 loops, best of 3: 858 µs per loop

Эм-м-м? Использование якобиана медленнее, чем его приближение? Я сделал что-то неправильно?


person usual me    schedule 24.06.2014    source источник


Ответы (1)


На самом деле это не ответ, но я чувствую, что это зависит от размера проблемы. Для небольшого размера (n = 500) дополнительное время, потраченное на оценку якобиана (с поставляемым jac), вероятно, в конце концов не окупится.

n=500, с джебом:

100 loops, best of 3: 1.50 ms per loop

Без:

100 loops, best of 3: 1.57 ms per loop

n=5000, с джебом:

100 loops, best of 3: 5.07 ms per loop

Без:

100 loops, best of 3: 6.46 ms per loop

n=50000, с джебом:

100 loops, best of 3: 49.1 ms per loop

Без:

100 loops, best of 3: 59.2 ms per loop

Также вы можете подумать о том, чтобы переписать функцию jacobian, например, избавление от дорогого .T() может привести к ускорению примерно на 15%:

def myDfun2( abc, xdata, ydata, f ) :
    a,b,c = abc
    ebx = np.exp(-b * xdata)
    res = np.hstack( ( ebx.reshape(-1,1), (a * -xdata * ebx).reshape(-1,1), np.ones((len(xdata),1)) ) )
    return res
person CT Zhu    schedule 24.06.2014