Подгонка точек трехмерных данных к полиномиальной поверхности и восстановление уравнения поверхности - PullRequest
1 голос
/ 05 августа 2020

Я плохо знаком с Python 3D-подгонкой и соответствующими методами оптимизации. Я пытался разобраться в подобных темах и найти ответ на основе методов наименьших квадратов, но мой успех был довольно ограниченным.

Проблема: у меня есть количество (около 400) трехмерных точек, хранящихся в массиве np .

data = np.array([[x1, y1, z1], [x2, y2, z2], [x3, y3, z3], [x4, y4, z4], ... ])

Я хотел бы подогнать полиномиальную поверхность (порядка 2 или 3) к этим точкам, а затем получить параметры уравнения поверхности, чтобы я мог вычислить z для любой заданной пары (x , y) значения. Например:

z = (A * x ** 2) + (B * y ** 2) + (C * x * y) + (D * x) + (E * y) + F

Мне нужно получить вывод, содержащий параметры A, B, C, D, E и F. Есть ли хороший способ сделать это с помощью Pythoni c?

Ответы [ 2 ]

2 голосов
/ 05 августа 2020

Если вы разрешаете зависимость от sklearn, вы можете использовать sklearn.preprocessing.PolynomialFeatures вместе с sklearn.linear_model.LinearRegression :

import numpy as np
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

np.random.seed(0)

# Generate fake data 
n,m = 400, 3
data = np.random.randn(n,m)

# Generate polynomial features of desired degree
d = 3
poly = PolynomialFeatures(degree=d, include_bias=False)
X = poly.fit_transform(data[:, :-1]) # X.shape = (400, 9)
y = data[:,-1] # y.shape = (400,)

# Define and fit linear regression 
clf = LinearRegression()
clf.fit(X, y)

# Check results
print(clf.coef_)
[-0.01437971  0.09894586  0.01936384  0.17245758  0.05518938
  0.0239589  -0.09930492 -0.04593238 -0.01588326]

print(clf.intercept_)
-0.12456419670821159
2 голосов
/ 05 августа 2020

curve_fit принимает многомерный массив для независимой переменной, но ваша функция должна принимать то же самое:

import numpy as np
from scipy.optimize import curve_fit

data = np.array(
    [[0, 0, 1],
     [1, 1, 2],
     [2, 1, 3],
     [3, 0, 5],
     [4, 0, 2],
     [5, 1, 3],
     [6, 0, 7]]
)

def func(X, A, B, C, D, E, F):
    # unpacking the multi-dim. array column-wise, that's why the transpose
    x, y, z = X.T

    return (A * x ** 2) + (B * y ** 2) + (C * x * y) + (D * x) + (E * y) + F

popt, _ = curve_fit(func, data, data[:,2])
from string import ascii_uppercase
for i, j in zip(popt, ascii_uppercase):
    print(f"{j} = {i:.3f}")

# A = 0.060
# B = 2004.446
# C = -0.700
# D = 0.521
# E = -2003.046
# F = 1.148

Обратите внимание, что в целом вы должны предоставить начальное предположение для параметров, чтобы добиться хорошего соответствия результаты.

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