假设我想找到2条任意高维线的“交点”。两条线实际上不会相交,但是我仍然想找到最相交的点(即,尽可能靠近所有线的点)。
假设这些线具有方向矢量A
,B
和初始点C
,D
,
我可以通过简单地建立一个线性最小二乘问题来找到最大的相交点:转换线相交方程
Ax + C = By + D
最小二乘形式
[A, -B] @ [[x, y]] = D - C
其中@
是矩阵时间向量的标准,然后我可以使用例如np.linalg.lstsq
来解决。
但是如何找到3条或更多条任意线的“最大相交点”?如果我遵循同样的规则,我现在有
Ax + D = By + E = Cz + F
我唯一想到的方法是将其分解为三个方程式:
Ax + D = By + E
Ax + D = Cz + F
By + E = Cz + F
并将其转换为最小二乘形式
[A, -B, 0] [E - D]
[A, 0, -C] @ [[x, y, z]] = [F - D]
[0, B, -C] [F - E]
问题是最小二乘问题的大小大约增加了行数。我想知道有没有更有效的方法来解决n向等式最小二乘线性问题?
我在思考上面By + E = Cz + F
提供其他两个术语的必要性。但是,由于此问题没有确切的解决方案(即它们实际上没有相交),因此我相信这样做会在某些变量上产生更多的“权重”吗?
谢谢您的帮助!
编辑
我刚刚使用以下代码测试了在n向平等中将第一个术语与所有其他术语配对(没有其他对)
def lineIntersect(k, b):
"k, b: N-by-D matrices describing N D-dimensional lines: k[i] * x + b[i]"
# Convert the problem to least-square form `Ax = B`
# A is temporarily defined 3-dimensional for convenience
A = np.zeros((len(k)-1, k.shape[1], len(k)), k.dtype)
A[:,:,0] = k[0]
A[range(len(k)-1),:,range(1,len(k))] = -k[1:]
# Convert to 2-dimensional matrix by flattening first two dimensions
A = A.reshape(-1, len(k))
# B should be 1-dimensional vector
B = (b[1:] - b[0]).ravel()
x = np.linalg.lstsq(A, B, None)[0]
return (x[:,None] * k + b).mean(0)
下面的结果表明这样做是不正确的,因为n-way-equality中的第一项是“权重不同”。
第一项输出是常规结果与不同输入顺序(行顺序无关紧要)的结果之间的差异,其中第一项没有变化。
第二个输出与第一个字词确实发生了变化相同。
k = np.random.rand(10, 100)
b = np.random.rand(10, 100)
print(np.linalg.norm(lineIntersect(k, b) - lineIntersect(np.r_[k[:1],k[:0:-1]], np.r_[b[:1],b[:0:-1]])))
print(np.linalg.norm(lineIntersect(k, b) - lineIntersect(k[::-1], b[::-1])))
产生
7.889616961715915e-16
0.10702479853076755
答案 0 :(得分:2)
此问题可能更适合数学stackexchange。另外,有人在这里格式化数学的好方法吗?抱歉,这很难看,我尽了最大努力。
编辑:我误解了Ax+C
行@ZisIsNotZis的含义,因此忽略了下一段。
我不认为您的方法陈述正确。您介意发布您的代码和输出的一个小示例(也许在2d中包含3或4行,以便我们对其进行绘制)?当您尝试查找两条线的交点时,是否不应该
Ax+C = Bx+D
?如果您进行Ax+C=By+D
,则可以在第一行中选择一些x
,在第二行中选择一些y
,并完全满足两个方程式。因为此处x
和y
的大小应与A
和B
相同,这是空间的尺寸,而不是标量。
有很多方法可以理解找到尽可能靠近所有直线的点的问题。我认为最自然的是,到每一行的欧几里得距离的平方和被最小化。
假设我们在R^n
中有一行:c^Tz + d = 0
(其中c
是单位长度)和另一点x
。那么从x
到直线的最短向量是:(I-cc^T)(x-d)
,所以从x
到直线的距离的平方是║(I-cc^T)(x-d)║^2
。我们可以通过最小化该距离来找到最接近直线的点。请注意,这是min_x ║b-Ax║_2
形式的标准最小二乘问题。
现在,假设我们有c_iz+d_i
代表i=1,...,m
的行。从点d_i^2
到第x
行的距离i
的平方是d_i^2 = ║(I-cc^T)(x-d)║_2^2
。现在,我们要解决min_x \sum_{i=1}^{m} d_i^2
的问题。
以矩阵形式有:
║ ⎡ (I-c_1 c_1^T)(x-d_1) ⎤ ║
║ | (I-c_2 c_2^T)(x-d_2) | ║
min_x ║ | ... | ║
║ ⎣ (I-c_n c_n^T)(x-d_n) ⎦ ║_2
这也是min_x ║b - Ax║_2
的形式,因此有很好的求解器。
每个块的大小为n(空间尺寸),有m个块(行数)。因此系统是mn
的{{1}}。特别是,它的线数是线性的,空间的尺寸是平方的。
它还有一个优势,如果添加一条线,您只需向最小二乘法添加另一个块。这还提供了在添加行时迭代更新解决方案的可能性。
我不确定这种最小二乘系统是否有特殊的求解器。请注意,每个块都是恒等式减去一个秩矩阵,因此可能会提供一些其他结构,这些结构可用于加快处理速度。就是说,我认为使用现有的求解器几乎总是比编写自己的求解器更好,除非您在数值分析方面有相当多的背景或要解决的系统非常专业。
答案 1 :(得分:2)
“相交点”的另一个标准是点x,以使x到直线的距离的平方和尽可能小。像您的标准一样,如果线实际上相交,则几乎相交的点将是实际相交的点。但是,我认为距离平方标准的总和使计算有问题的点变得很简单:
假设我们用一个点表示一条直线,并沿着该直线表示一个单位向量。因此,如果一条直线由p,t表示,那么直线上的点的形式为
p + l*t for scalar l
点x与线p,t的距离平方是
(x-p)'*(x-p) - square( t'*(x-p))
如果我们有N条线p [i],t [i],则距点x的距离的总和为
Sum { (x-p[i])'*(x-p[i]) - square( t[i]'*(x[i]-p[i]))}
对此进行扩展,我得到的就是
x'*S*x - 2*x'*V + K
其中
S = N*I - Sum{ t[i]*t[i]'}
V = Sum{ p[i] - (t[i]'*p[i])*t[i] }
并且K不依赖于x
除非所有线都是平行的,否则S将(严格地)是正定的,因此是可逆的,在这种情况下,我们的距离平方和为
(x-inv(S)*V)'*S*(x-inv(S)*V) + K - V'*inv(S)*V
因此,将x最小化
inv(S)*V
因此,练习是:标准化“方向向量”(并使用与缩放方向相同的因子缩放每个点),如上所述形成S和V,求解
S*x = V for x
答案 2 :(得分:1)
一些想法不是解决方案:
如果nD空间中的线具有参数方程式(单位为Dir
向量)
L(t) = Base + Dir * t
然后从点P
到这条线的平方距离是
W = P - Base
Dist^2 = (W - (W.dot.Dir) * Dir)^2
如果可以用适合LSQ方法的形式编写Min(Sum(Dist[i]^2))
(通过每个点坐标进行偏导数),则可以用(x1..xn)
坐标向量求解所得系统。
(情况类似于通常的LSQ的许多点和单行的反转)
答案 3 :(得分:0)
您说您有两条“高维”线。这意味着指示行的矩阵的列多于行。
如果是这种情况,并且您可以有效地找到低阶分解,例如 A =LRᵀ,那么您可以重写最小二乘问题的解 min || Ax- y ||²为 x =(RᵀRLᵀL)⁻¹Lᵀy 。
如果 m 是线的数量,而 n 是线的尺寸,则这将从 O(mn²+nʷ )到 O(nr²+mr²),其中 r = min(m,n)。
然后的问题是找到这种分解。