我为它绕太阳运行的行星的(x,y,z)坐标生成了一堆数据 . 现在我想通过这些数据拟合椭圆 .
我试图做的:
我基于五个参数创建了一个虚拟椭圆:半长轴和偏心,定义了大小和形状以及三个旋转椭圆的欧拉角 . 由于我的数据并不总是以原点为中心,因此我还需要翻译需要额外三个变量(dx,dy,dz)的椭圆 . 一旦我用这八个变量初始化这个函数,我就得到了这个椭圆上的N个点 . (N =我正在绘制椭圆的数据点的数量)我计算这些虚拟点与实际数据的偏差,然后使用一些最小化方法最小化该偏差,以找到这八个变量的最佳拟合值 .
我的问题在于最后一部分:最小化偏差并找到变量的值 .
为了最大限度地减少偏差,我使用scipy.optimize.minimize来尝试近似最佳拟合变量,但它只是做得不够好:
Here is an image我的最佳配合是什么样的,并且具有非常慷慨准确的初始猜测 . (蓝色=数据,红色=适合)
Here is the entire code.(无需数据,它会生成自己的假数据)
In short ,我使用这个scipy函数:
initial_guess = [0.3,0.2,0.1,0.7,3,0.0,-0.1,0.0]
bnds = ((0.2, 0.5), (0.1, 0.3), (0, 2*np.pi), (0, 2*np.pi), (0, 2*np.pi), (-0.5,0.5), (-0.5,0.5), (-0.3,0.3)) #reasonable bounds for the variables
result = optimize.minimize(deviation, initial_guess, args=(data,), method='L-BFGS-B', bounds=bnds, tol=1e-8) #perform minimalisation
semi_major,eccentricity,inclination,periapsis,longitude,dx,dy,dz = result["x"]
要最小化此错误(或偏差)功能:
def deviation(variables, data):
"""
This function calculates the cumulative seperation between the ellipse fit points and data points and returns it
"""
num_pts = len(data[:,0])
semi_major,eccentricity,inclination,periapsis,longitude,dx,dy,dz = variables
dummy_ellipse = generate_ellipse(num_pts,semi_major,eccentricity,inclination,periapsis,longitude,dz,dy,dz)
deviations = np.zeros(len(data[:,0]))
pair_deviations = np.zeros(len(data[:,0]))
# Calculate separation between each pair of points
for j in range(len(data[:,0])):
for i in range(len(data[:,0])):
pair_deviations[i] = np.sqrt((data[j,0]-dummy_ellipse[i,0])**2 + (data[j,1]-dummy_ellipse[i,1])**2 + (data[j,2]-dummy_ellipse[i,2])**2)
deviations[j] = min(pair_deviations) # only pick the closest point to the data point j.
total_deviation = sum(deviations)
return total_deviation
(我的代码可能有点凌乱和低效,我是新手)
我可能在编码中犯了一些逻辑错误,但我认为它归结为scipy.minimize.optimize函数 . 我不知道它是如何工作的以及对它的期望 . 我还建议在处理这么多变量时尝试马尔可夫链蒙特卡罗 . 我确实看了一下主持人,但现在它有点高于我的头脑 .
1 回答
首先,你的目标函数中有一个拼写错误,它会阻止其中一个变量的优化:
应该
另外,取出
sqrt
并最小化欧氏距离的平方和使得优化器在数值上更容易一些 .由于BFGS求解器假设的min(),你的目标函数也无处可辨,因此它的性能不是最理想的 .
此外,从分析几何角度来解决问题可能有所帮助:3d中的椭圆被定义为两个方程的解
其中
p
是椭圆的参数 . 现在,为了使参数适合数据集,您可以尝试最小化总和超过数据点 .
更好的是,在这个问题公式中你可以使用
optimize.leastsq
,这在最小二乘问题中可能更有效 .