2-градусная многогранная кривая - PullRequest
0 голосов
/ 18 ноября 2018

Я работаю над своим проектом в аспирантуре, где у меня есть уравнение что-то вроде этого:

fos=f(x,y)= a1+a2*x+a3*x^2+a4*y+a5*y^2

У меня есть значения fos[] и array[[x],[y]].
Мне нужно знатьметод, чтобы получить те значения коэффициента, используя NumPy или Scipy / Scikit.Я попытался использовать PolynomialFeature в scikit, но не смог найти правильный метод для подачи моего уравнения и вычисления значений на основе этих данных.

Ответы [ 2 ]

0 голосов
/ 18 ноября 2018

Вот ответ на ваш вопрос. По сути, подобрать такую ​​функцию довольно просто с помощью numpy. Я прокомментировал код ниже сильно. Вы можете видеть, что в первых 4 строках кода (исключая комментарий и пустые строки) я просто делаю набор данных, который хочу подогнать, подгоняю Z, используя X и Y. Здесь Z = fos = f (x, y).

Первая важная строка для того, чтобы вы соответствовали вашему набору данных после загрузки, будет XY = ... После этого есть только еще одна строка, чтобы найти ваши коэффициенты, а остальное - просто распечатать их.

import numpy as np

# in these 4 lines I just create a some data
# You have your own so you can ignore them
# we have x and y and the z. z is f(x,y)

X, Y = np.meshgrid(np.linspace(0, 1, 20), np.linspace(0, 1, 20), copy=False)
X = X.flatten()
Y = Y.flatten()
Z = (X**2 + Y**2 + np.random.rand(*X.shape)*0.01).flatten()

# we want to make the function something like a1+a2*x+a3*x^2+a4*y+a5*y^2
# we will first make an array of our known variables
# we want a array of 1, x, x**2, y, y**2
# after we have this we can fit it linearly to get the coefficients a_n

XY = np.array([np.ones(X.shape), X, Y, X**2, Y, Y**2]).T

# here is where we actually fit the coefficients
coeff,_,_,_ = np.linalg.lstsq(XY, Z)

for i in range(len(coeff)):
    print('a{} = {}'.format(i, coeff[i]))
0 голосов
/ 18 ноября 2018

Внимательно следуя этому коду Я получил следующее:

from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np

def f(x, a1, a2, a3, a4, a5):
    return a1+a2*x[0]+a3*x[0]**2+a4*x[1]+a5*x[1]**2

limits = [-10, 10, -10, 10]  # [x1_min, x1_max, x2_min, x2_max]
side_x = np.linspace(limits[0], limits[1], 100)
side_y = np.linspace(limits[2], limits[3], 100)
X1, X2 = np.meshgrid(side_x, side_y)
size = X1.shape
X1_1d = X1.reshape((1, np.prod(size)))
X2_1d = X2.reshape((1, np.prod(size)))


xdata = np.vstack((X1_1d, X2_1d))

#Here I create some sample data
original = (1,2,3,4,5)
z = f(xdata, *original)
Z = z.reshape(size)
z_noise = z + .2*np.random.randn(len(z))
Z_noise = z_noise.reshape(size)

#For z_noise you have to plug in your data here
popt, pcov = curve_fit(f, xdata, z_noise)
print("fitted: {}".format(popt))
z_fit = f(xdata, *popt)
Z_fit = z_fit.reshape(size)

#Plotting
plt.subplot(1, 2, 1)
plt.title("Sample data")
plt.pcolormesh(X1, X2, Z_noise)
plt.axis(limits)
plt.colorbar()
plt.subplot(1, 2, 2)
plt.title("Fitted Function")
plt.pcolormesh(X1, X2, Z_fit)
plt.axis(limits)
plt.colorbar()

plt.show()

Сначала я определяю функцию в том виде, в каком вы ее опубликовали (предполагая, что под ^ вы подразумевали **). Затем я устанавливаю ограничения для осей X и Y (вам придется заменить их на свои собственные ограничения).

Теперь, чтобы сделать подгонку, мы должны поместить ваши данные x / y в один вектор, что и делается в блоке кода до первого комментария. После комментария я создаю образцы данных, которые вам не нужны, поскольку у вас есть свои собственные. Образцы данных называются z_noise (small z!), Которые вам нужно будет преобразовать в одномерный вектор. После всего этого я могу просто позвонить curve_fit, чтобы получить параметры, которые лучше всего соответствуют z_noise.

Я позволил части с созданием примера данных войти, чтобы это было легко проверить и повторить: большая часть этого кода взята с здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...