Несколько переменных в curve_fit, сигма имеет неправильную форму? - PullRequest
1 голос
/ 05 мая 2019

У меня есть проверенная функция curve_fit для нескольких переменных. Я столкнулся с проблемой "сигма имеет неправильную форму". Я попробовал следующий код. Кто-нибудь может объяснить, почему я получаю эту ошибку? Здесь x и y - мои независимые переменные, а p, q, r - параметры, которые я хочу подогнать

xdata = [214.737191559, -5.64912101538e-36, 36.1372453686, 189.459700978, 233.562136902, 201.230228832, -5.59364882619e-36, -36.3232002416, -188.192199081, -212.837139143, -232.342545403, -200.699429716]
ydata = [-5.88273617837e-37, -211.536123799, -186.67108047, -35.9497006815, 200.282998159, 232.085860035, 213.44274878, 187.945919272, 35.7227474297, -6.00785257974e-37, -199.746844708, -230.856058666]

xdata = np.array(xdata)
ydata = np.array(ydata)

def func1(X,a,b,c):
    x,y = X

    n  = 8
#     % A  = ydata
#     % B  = -xdata
#     % C  = xdata. - ydata
#     % H  = zdata

    g = np.subtract(x,y)
    I_0 = np.subtract(x,y)   # x-y = C
    I_1 = np.multiply(I_0,c) # c(x-y) = cC
    I_2 = np.multiply(b,-x)   #b(-x) = bB
    I_3 = np.multiply(a,y)  # aA


    I3_0 = np.subtract(I_1,I_2) # cC-bB
    I3_1 = np.subtract(I_3,I_1) # aA-cC
    I3_2 = np.subtract(I_2,I_3) # bB-aA

    I3_00 = np.multiply(I3_0,I3_1) # (cC-bB)(aA-cC)
    I3_01 = np.multiply(I3_00,I3_2) # (cC-bB)(aA-cC)(bB-aA)

    I3 = np.divide(I3_01,54) # (cC-bB)(aA-cC)(bB-aA)/54

    I2_0 = np.power((I3_1),2)  # (aA-cC)^2
    I2_1 = np.power((I3_0),2)  # (cC-bB)^2
    I2_2 = np.power((I3_2),2)  # (bB-aA)^2

    I2_00 = np.add(I2_0,I2_1)  # (aA-cC)^2 + (cC-bB)^2
    I2_01 = np.add(I2_00,I2_2) # (aA-cC)^2 + (cC-bB)^2 + (bB-aA)^2

    I2 = np.divide(I2_01,54)  # ((aA-cC)^2 + (cC-bB)^2 + (bB-aA)^2)/54

    th_0 = np.divide(I3,(np.power(I2,(3/2))))  # I3/(I2^(3/2))

    th = np.arccos(np.clip((th_0),-1,1))  # arccos(I3/(I2^(3/2)))

    ans_0 = np.divide(np.add((2*th),(np.pi)),6)   # (2*th + pi)/6
    ans_1 = np.divide(np.add((2*th),(3*np.pi)),6) # (2*th + 3*pi)/6
    ans_2 = np.divide(np.add((2*th),(5*np.pi)),6) # (2*th + 5*pi)/6

    ans_00 = np.multiply(np.cos(ans_0),2)  # 2*cos((2*th + pi)/6)
    ans_11 = np.multiply(np.cos(ans_1),2)  # 2*cos((2*th + 3*pi)/6)
    ans_22 = np.multiply(np.cos(ans_2),2)  # 2*cos((2*th + 5*pi)/6)

    ans_000 = np.power(np.absolute(ans_00),n)  # (abs(2*cos((2*th + pi)/6)))^n
    ans_111 = np.power(np.absolute(ans_11),n)  # (abs(2*cos((2*th + 3*pi)/6)))^n
    ans_222 = np.power(np.absolute(ans_22),n)  # (abs(2*cos((2*th + 5*pi)/6)))^n

    ans_0000 = np.add((np.power(np.absolute(ans_00),n)),(np.power(np.absolute(ans_11),n))) # (abs(2*cos((2*th + pi)/6)))^n + (abs(2*cos((2*th + 3*pi)/6)))^n 
    ans_1111 = np.add((ans_0000),(np.power(np.absolute(ans_22),n)))  # (abs(2*cos((2*th + pi)/6)))^n + (abs(2*cos((2*th + 3*pi)/6)))^n + (abs(2*cos((2*th + 5*pi)/6)))^n

    sna_0 = np.power(np.multiply(3,I2),(n/2))  # (3*I2)^(n/2) !!
    sna_1 = 2*(np.power(190,n)) # 2*(sigma^n) !!

    sna_00 = np.multiply(sna_0,ans_1111)
    sna_11 = np.subtract(sna_00,sna_1)

    return sna_11

a, b, c = 10., 4., 6.
z = func1((xdata,ydata), a, b, c) * 1 + np.random.random(12) / 100

# initial guesses for a,b,c:
a, b, c = 1, 1, 1
p0      = np.array([a, b, c])
# p0 = 8., 2., 7.
popt,pcov  = (curve_fit(func1, (xdata,ydata),z, p0))
popt

Когда я запускаю это, я иду следующую ошибку

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-484bc542850b> in <module>()
      6 p0      = np.array([a, b, c])
      7 # p0 = 8., 2., 7.
----> 8 popt,pcov  = (curve_fit(func1, (xdata,ydata), p0))
      9 popt

~/.conda/envs/ML/lib/python3.6/site-packages/scipy/optimize/minpack.py in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, **kwargs)
    749         # Remove full_output from kwargs, otherwise we're passing it in twice.
    750         return_full = kwargs.pop('full_output', False)
--> 751         res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
    752         popt, pcov, infodict, errmsg, ier = res
    753         cost = np.sum(infodict['fvec'] ** 2)

~/.conda/envs/ML/lib/python3.6/site-packages/scipy/optimize/minpack.py in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    381     if not isinstance(args, tuple):
    382         args = (args,)
--> 383     shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
    384     m = shape[0]
    385     if n > m:

~/.conda/envs/ML/lib/python3.6/site-packages/scipy/optimize/minpack.py in _check_func(checker, argname, thefunc, x0, args, numinputs, output_shape)
     25 def _check_func(checker, argname, thefunc, x0, args, numinputs,
     26                 output_shape=None):
---> 27     res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
     28     if (output_shape is not None) and (shape(res) != output_shape):
     29         if (output_shape[0] != 1):

~/.conda/envs/ML/lib/python3.6/site-packages/scipy/optimize/minpack.py in func_wrapped(params)
    461     if transform is None:
    462         def func_wrapped(params):
--> 463             return func(xdata, *params) - ydata
    464     elif transform.ndim == 1:
    465         def func_wrapped(params):

ValueError: operands could not be broadcast together with shapes (12,) (3,) 


1 Ответ

1 голос
/ 05 мая 2019

Ошибка, которую вы получаете ValueError: ``sigma`` has incorrect shape., связана с неправильным вызовом curve_fit и разницей между тем, что ожидает функция, и тем, что вы ее кормите.Вот пример правильного вызова:

p, q, r = 1, 1, 1
p0      = np.array([p, q, r])
cfit    = curve_fit(func, xdata, ydata, p0)
print(cfit)

К сожалению, это не единственная вещь, вызывающая беспокойство в вашем коде.Ваш func1 потребует от вас некоторого редактирования.Вы можете сослаться на этот пост о том, как использовать curve_fit .

Обновление:

Я сократил ваш код и оптимизировал некоторые строки плюс - как уже упоминалосьв комментариях вам нужна выходная переменная, поэтому я сгенерировал пользовательский zdata, который вы позже сможете заменить своими данными.

import numpy as np
from scipy.optimize import curve_fit

xdata = [214.737, -5.649e-36, 36.137, 189.459, 233.562, 201.230, -5.593e-36, -36.323, -188.192, -212.837, -232.342, -200.699]
ydata = [-5.882e-37, -211.536, -186.671, -35.949, 200.282, 232.085, 213.442, 187.945, 35.722, -6.007, -199.746, -230.856]


def func(X, p, q, r):

    x = np.array(X[0])
    y = np.array(X[1])
    n = 8

    a1 = (p * y) - (r * (x-y))
    b1 = (q * -1 * x) - (p * y)
    c1 = (r * (x - y)) - (q * -1 * x)

    I3 = (a1 * b1 * c1) / 54 
    I2 = (a1**2 + b1**2 +  c1**2) / 54  
    th = np.arccos( I3 / (I2**(3/2)) )

    an1 = (np.abs(2 * np.cos((2 * th + 1 * np.pi) /6)))**n
    an2 = (np.abs(2 * np.cos((2 * th + 3 * np.pi) /6)))**n
    an3 = (np.abs(2 * np.cos((2 * th + 5 * np.pi) /6)))**n

    res = ( (3 * I2)**(n/2) ) * (an1 + an2 + an3) - (2 * (189.32)**8)
    return res

# init
p, q, r = 1, 1, 1
p0      = np.array([p, q, r])

# artificial zdata  
zdata = func((xdata, ydata), p, q, r) + np.random.random(np.array(xdata).shape)
cfit  = curve_fit(func, (xdata, ydata), zdata, p0)

# print output
print(cfit)

Я до сих пор точно не понимаю, что у вас внутри func, что вызывает RuntimeWarning: из-за invalid value encountered in arccos, и именно поэтому я отредактировал также и предоставленные вами данные.

...