拟合python中的N维抛物线

时间:2017-07-26 19:40:31

标签: python curve-fitting data-fitting model-fitting function-fitting

我有一组N个样本(N~10000到100000):

(y_i, P_i)

他们采样未知函数:

y = f(P)

就我而言,P是一组n_p参数,n_p通常大约为10。

我的目的是使用样本找到2阶多项式,它近似于我最大的未知函数。典型的结果是最佳拟合多项式的(n_p + 1)+(n_p + 1)* n_p / 2个系数。

但是,我想以下列形式获得解决方案:

f(P) = (P-mu)*(C^-1)*(P-mu)^T + K

具有维数为n_p的矢量,C a(n_p X n_p)对称矩阵,并且K为常数。这些mu,C和K是我想要获得的。

Python生态系统中是否存在标准实现和/或有效的方法?

提前致谢!

修改: 这是一个典型的设置,我创建假样本(P和Y),并且只使用它们,我想恢复原始的mu,C和K:

import numpy as np

n_p = 3
N = 15

# Generate the "mu" we'll try to recover
mu = np.random.rand(n_p)

# Generate the "C" we'll try to recover
tmp = np.random.rand(n_p,n_p)
C = np.dot(tmp, tmp.T)

# Generate the "K" we'll try to recover
K = np.random.rand()

# Generate the samples
P = np.random.rand(n_p,N)
Y = np.array([np.dot(np.dot((P[:,i]-mu),np.linalg.inv(C)),(P[:,i]-mu))+K for i in range(N)])

1 个答案:

答案 0 :(得分:0)

这就是你要找的东西吗?我并非100%确定它对您的用例是准确的(我不知道当您对2阶多项式拟合时可以施加的其他约束),但它应该尝试找到一个U,A(你称之为C),以及最小化最小二乘误差的K.

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

samples = 100
num_params = 20

y = np.random.rand(samples)
p = np.random.rand(samples, num_params)


def my_func(params):
    u = params[0:num_params]
    u = np.expand_dims(u, axis=1)
    a = params[num_params:-1]
    k = params[-1]
    a = a.reshape(num_params, num_params)
    a_inv = np.linalg.inv(a)
    shifted_p = p - np.transpose(u)
    mult_with_a_inv = np.dot(shifted_p, a_inv)
    mat_mult_vec = np.einsum('ij,ji->i', mult_with_a_inv, np.transpose(shifted_p))
    return_val = y - k - mat_mult_vec
    return sum(return_val**2)


guess = np.random.rand(num_params+num_params**2+1)
new_params = optimize.fmin_cg(my_func, guess)
new_u = new_params[0:num_params]
new_a = new_params[num_params:-1]
new_a = new_a.reshape(num_params, num_params)
new_k = new_params[-1]

original_y, = plt.plot(np.arange(samples), y)
new_y, = plt.plot(np.arange(samples), np.einsum('ij,ji->i', np.dot(p-np.transpose(new_u),
                                                                   np.linalg.inv(new_a)),
                                                            np.transpose(p-np.transpose(new_u))
                                 ) + new_k)
plt.legend([original_y, new_y], ['Original Y', 'Newly Fitted Y'])
plt.show()

这可能是一种更加数学上合理的方法,但希望这至少有帮助。

编辑:刚刚注意到我弄乱了k的标志。我还需要提高参数数量。这似乎工作得非常好。我几乎完全恢复了原来的噪音。

同时添加样本输出。

Sample Output