我有想要与多项式拟合的数据。我有200,000个数据点,所以我想要一个有效的算法。我想使用numpy.polynomial
包,以便我可以尝试不同的族和多项式次数。有没有什么方法可以将其表示为Ax = b等方程组?有没有比使用scipy.minimize更好的解决方法?
import numpy as np
from scipy.optimize import minimize as mini
x1 = np.random.random(2000)
x2 = np.random.random(2000)
y = 20 * np.sin(x1) + x2 - np.sin (30 * x1 - x2 / 10)
def fitness(x, degree=5):
poly1 = np.polynomial.polynomial.polyval(x1, x[:degree])
poly2 = np.polynomial.polynomial.polyval(x2, x[degree:])
return np.sum((y - (poly1 + poly2)) ** 2 )
# It seems like I should be able to solve this as a system of equations
# x = np.linalg.solve(np.concatenate([x1, x2]), y)
# minimize the sum of the squared residuals to find the optimal polynomial coefficients
x = mini(fitness, np.ones(10))
print fitness(x.x)
答案 0 :(得分:1)
你的直觉是正确的。您可以将此解析为 Ax = b 形式的方程组。
然而:
系统过度定义,您希望获得最小二乘解决方案,因此您需要使用np.linalg.lstsq
代替np.linalg.solve
。
您不能使用 polyval
,因为您需要分离自变量的系数和幂。
这是如何构建方程组并解决它:
A = np.stack([x1**0, x1**1, x1**2, x1**3, x1**4, x2**0, x2**1, x2**2, x2**3, x2**4]).T
xx = np.linalg.lstsq(A, y)[0]
print(fitness(xx)) # test the result with original fitness function
当然,你可以概括一下学位:
A = np.stack([x1**p for p in range(degree)] + [x2**p for p in range(degree)]).T
使用示例数据,最小二乘解决方案的运行速度比minimize
解决方案快得多(800μs比我的笔记本电脑上的35ms)。但是,A
可能变得非常大,因此如果内存有问题minimize
可能仍然是一个选项。
<强>更新强>
在没有任何关于多项式函数内部的知识的情况下,事情变得棘手,但 可能将术语和系数分开。这是从像A
这样的函数构造系统矩阵polyval
的一种有点丑陋的方法:
def construct_A(valfunc, degree):
columns1 = []
columns2 = []
for p in range(degree):
c = np.zeros(degree)
c[p] = 1
columns1.append(valfunc(x1, c))
columns2.append(valfunc(x2, c))
return np.stack(columns1 + columns2).T
A = construct_A(np.polynomial.polynomial.polyval, 5)
xx = np.linalg.lstsq(A, y)[0]
print(fitness(xx)) # test the result with original fitness function