Как получить оптимизированные параметры, используя curve_fit для двух независимых переменных? - PullRequest
0 голосов
/ 07 мая 2019

Я хочу выполнить подгонку кривой для двух независимых параметров x и y. И я хочу оптимизировать свои параметры a, b и c. Я попытался оптимизировать мои параметры с помощью Curve_fit в Scipy. Но мои параметры не оптимизируются. Я использовал следующий код

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

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

    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(c,I_0) # 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))

#     print(th_0)

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

#     print(th)

    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 = 1., 1., 1.
z = func1((xdata,ydata), a, b, c) * 1 + np.random.random(12) / 100

# initial guesses for a,b,c:
p0 = 8., 2., 7.
cfit = (curve_fit(func1, (xdata,ydata), z, p0))
cfit

И я получаю следующий результат


(array([1., 1., 1.]),
 array([[ 2.00165749e-32, -1.12390196e-32, -3.15983591e-33],
        [-1.12390196e-32,  1.91794261e-32, -3.96062853e-33],
        [-3.15983591e-33, -3.96062853e-33,  1.44218612e-32]]))

Я не получил оптимизированные a, b и c.

Ответы [ 2 ]

0 голосов
/ 09 мая 2019
def func1(coeff,x,y):
 a = coeff[0]
 b = coeff[1]
 c = coeff[2] 
...
 return
x0 = np.array([1.0, 1.0, 1.0])
res_lsq = least_squares(func1, x0,loss='cauchy',f_scale=0.001,args=(xdata, ydata))
res_lsq.x


0 голосов
/ 07 мая 2019

Вот пример кода, который может помочь вам начать работу.При этом используется curve_fit для подгонки к поверхности "z = f (x, y)" и рисуется трехмерная диаграмма рассеяния, трехмерная диаграмма поверхности и контурная диаграмма.Обратите внимание, что вы можете удерживать клавишу мыши на 3D-графиках и вращать их для проверки.

import numpy, scipy, scipy.optimize
import matplotlib
from mpl_toolkits.mplot3d import  Axes3D
from matplotlib import cm # to colormap 3D surfaces from blue to red
import matplotlib.pyplot as plt

graphWidth = 800 # units are pixels
graphHeight = 600 # units are pixels

# 3D contour plot lines
numberOfContourLines = 16


def SurfacePlot(func, data, fittedParameters):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)

    matplotlib.pyplot.grid(True)
    axes = Axes3D(f)

    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    xModel = numpy.linspace(min(x_data), max(x_data), 20)
    yModel = numpy.linspace(min(y_data), max(y_data), 20)
    X, Y = numpy.meshgrid(xModel, yModel)

    Z = func(numpy.array([X, Y]), *fittedParameters)

    axes.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=1, antialiased=True)

    axes.scatter(x_data, y_data, z_data) # show data along with plotted surface

    axes.set_title('Surface Plot (click-drag with mouse)') # add a title for surface plot
    axes.set_xlabel('X Data') # X axis data label
    axes.set_ylabel('Y Data') # Y axis data label
    axes.set_zlabel('Z Data') # Z axis data label

    plt.show()
    plt.close('all') # clean up after using pyplot or else thaere can be memory and process problems


def ContourPlot(func, data, fittedParameters):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)
    axes = f.add_subplot(111)

    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    xModel = numpy.linspace(min(x_data), max(x_data), 20)
    yModel = numpy.linspace(min(y_data), max(y_data), 20)
    X, Y = numpy.meshgrid(xModel, yModel)

    Z = func(numpy.array([X, Y]), *fittedParameters)

    axes.plot(x_data, y_data, 'o')

    axes.set_title('Contour Plot') # add a title for contour plot
    axes.set_xlabel('X Data') # X axis data label
    axes.set_ylabel('Y Data') # Y axis data label

    CS = matplotlib.pyplot.contour(X, Y, Z, numberOfContourLines, colors='k')
    matplotlib.pyplot.clabel(CS, inline=1, fontsize=10) # labels for contours

    plt.show()
    plt.close('all') # clean up after using pyplot or else thaere can be memory and process problems


def ScatterPlot(data):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)

    matplotlib.pyplot.grid(True)
    axes = Axes3D(f)
    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    axes.scatter(x_data, y_data, z_data)

    axes.set_title('Scatter Plot (click-drag with mouse)')
    axes.set_xlabel('X Data')
    axes.set_ylabel('Y Data')
    axes.set_zlabel('Z Data')

    plt.show()
    plt.close('all') # clean up after using pyplot or else thaere can be memory and process problems


def func(data, a, alpha, beta):
    t = data[0]
    p_p = data[1]
    return a * (t**alpha) * (p_p**beta)


if __name__ == "__main__":
    xData = numpy.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
    yData = numpy.array([11.0, 12.1, 13.0, 14.1, 15.0, 16.1, 17.0, 18.1, 90.0])
    zData = numpy.array([1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.0, 9.9])

    data = [xData, yData, zData]

    initialParameters = [1.0, 1.0, 1.0] # these are the same as scipy default values in this example

    # here a non-linear surface fit is made with scipy's curve_fit()
    fittedParameters, pcov = scipy.optimize.curve_fit(func, [xData, yData], zData, p0 = initialParameters)

    ScatterPlot(data)
    SurfacePlot(func, data, fittedParameters)
    ContourPlot(func, data, fittedParameters)

    print('fitted prameters', fittedParameters)

    modelPredictions = func(data, *fittedParameters) 

    absError = modelPredictions - zData

    SE = numpy.square(absError) # squared errors
    MSE = numpy.mean(SE) # mean squared errors
    RMSE = numpy.sqrt(MSE) # Root Mean Squared Error, RMSE
    Rsquared = 1.0 - (numpy.var(absError) / numpy.var(zData))
    print('RMSE:', RMSE)
    print('R-squared:', Rsquared)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...