繁体   English   中英

在3D中拟合一条线

[英]Fitting a line in 3D

是否有任何算法可以从一组3D数据点返回直线方程? 我可以找到很多来源,这些来源将给出2D数据集中的线的等式,但没有3D。

谢谢。

如果你试图从其他两个值中预测一个值,那么你应该使用带有a参数的lstsq作为你的自变量(加上一个1来估计一个截距的列)和b作为你的因变量。

另一方面,如果您只想获得数据的最佳拟合线,即如果您将数据投影到数据线上的线将最小化实际点与其投影之间的平方距离,那么您想要的是什么是第一个主要组成部分。

定义它的一种方法是线,其方向向量是对应于最大特征值的协方差矩阵的特征向量,它通过数据的均值。 也就是说, eig(cov(data))是一种非常糟糕的计算方法,因为它会进行大量不必要的计算和复制,并且可能不如使用svd准确。 见下文:

import numpy as np

# Generate some data that lies along a line

x = np.mgrid[-2:5:120j]
y = np.mgrid[1:9:120j]
z = np.mgrid[-5:3:120j]

data = np.concatenate((x[:, np.newaxis], 
                       y[:, np.newaxis], 
                       z[:, np.newaxis]), 
                      axis=1)

# Perturb with some Gaussian noise
data += np.random.normal(size=data.shape) * 0.4

# Calculate the mean of the points, i.e. the 'center' of the cloud
datamean = data.mean(axis=0)

# Do an SVD on the mean-centered data.
uu, dd, vv = np.linalg.svd(data - datamean)

# Now vv[0] contains the first principal component, i.e. the direction
# vector of the 'best fit' line in the least squares sense.

# Now generate some points along this best fit line, for plotting.

# I use -7, 7 since the spread of the data is roughly 14
# and we want it to have mean 0 (like the points we did
# the svd on). Also, it's a straight line, so we only need 2 points.
linepts = vv[0] * np.mgrid[-7:7:2j][:, np.newaxis]

# shift by the mean to get the line in the right place
linepts += datamean

# Verify that everything looks right.

import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d as m3d

ax = m3d.Axes3D(plt.figure())
ax.scatter3D(*data.T)
ax.plot3D(*linepts.T)
plt.show()

这是它的样子: 拟合线的3d图

如果您的数据表现相当不错,那么找到组件距离的最小二乘和就足够了。 然后你可以找到z独立于x的线性回归,然后再次独立于y。

按照文档示例:

import numpy as np

pts = np.add.accumulate(np.random.random((10,3)))
x,y,z = pts.T

# this will find the slope and x-intercept of a plane
# parallel to the y-axis that best fits the data
A_xz = np.vstack((x, np.ones(len(x)))).T
m_xz, c_xz = np.linalg.lstsq(A_xz, z)[0]

# again for a plane parallel to the x-axis
A_yz = np.vstack((y, np.ones(len(y)))).T
m_yz, c_yz = np.linalg.lstsq(A_yz, z)[0]

# the intersection of those two planes and
# the function for the line would be:
# z = m_yz * y + c_yz
# z = m_xz * x + c_xz
# or:
def lin(z):
    x = (z - c_xz)/m_xz
    y = (z - c_yz)/m_yz
    return x,y

#verifying:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

fig = plt.figure()
ax = Axes3D(fig)
zz = np.linspace(0,5)
xx,yy = lin(zz)
ax.scatter(x, y, z)
ax.plot(xx,yy,zz)
plt.savefig('test.png')
plt.show()

如果你想最小化从线(正交到线)到3空间中的点的实际正交距离(我不确定甚至称为线性回归)。 然后我将构建一个计算RSS的函数,并使用scipy.optimize最小化函数来解决它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM