python - 简单的线性依赖
问题描述
试图找出两个向量是线性相关的还是独立的。我不断遇到错误“数组的最后两个维度必须是正方形?有人可以解释一下吗?
def Indy2Vec(v1, v2):
A = np.array([v1])
B = np.array([v2])
print(A)
#A =np.linalg.matrix_rank(A)
A=np.linalg.solve(A,B)
return A
v1 = np.array([0, 5, 0])
v2 = np.array([0, -10, 0])
v3 = np.array([1, 2, 3])
v4 = np.array([-2, -4, -6])
Indy2Vec(v1,v2)
解决方案
错误的问题陈述
看来您没有解决正确的问题。正如您所说,它不能作为您使用的方法工作:
计算完全确定的(即满秩)线性矩阵方程 ax = b 的“精确”解 x。
如文档中所定义。
将您的问题写为Ax = b
. 但是你需要一个 3x3 矩阵来测试一个向量b=[0,0,0]T
并找到一个非平凡的解决方案x
来声称所有三个向量都不是线性独立的。但这意味着矩阵没有满秩。
在您的代码中,以下表达式无法满足函数签名:
np.linalg.solve(np.array([v1]), v2)
并引发以下错误:
LinAlgError: Last 2 dimensions of the array must be square
numpy.linalg.solve
对矩阵形状的有效调用是:
np.linalg.solve(np.array([v1, v2, v3]).T, np.zeros(v1.size))
但以两种方式失败:
LinAlgError: Singular matrix
首先,因为矩阵不是满秩的,因此不可逆。其次,这并不能解决两个向量的问题。
一般解决方案
import numpy as np
from scipy import linalg
相反,您想解决一个关于线性独立性的更一般的问题,这可以通过评估 的等级来解决[v1, v2]T
:
在线性代数中,矩阵 A 的秩是由其列生成(或跨越)的向量空间的维度。这对应于 A 的最大线性独立列数。
使用 numpy,您可以使用numpy.linalg.matrix_rank这样做:
np.linalg.matrix_rank(np.array([v1, v2]).T) # Missing dimension: 1
np.linalg.matrix_rank(np.array([v1, v3]).T) # Full rank: 2
此方法计算执行SVD 分解计算的空奇异值,此算法的实现由scipy.linalg.svd提供:
U, s, V = linalg.svd(np.array([v1, v2]).T) # s = [11.18033989, 0.]
U, s, V = linalg.svd(np.array([v1, v3]).T) # s = [5.55992016, 2.84381571]
或者执行它的高斯消除(假设使用LU 分解)并检查结果。包 scipy 提供scipy.linalg.lu:
p, l, u = linalg.lu(np.array([v1, v2]).T) # Null pivot: u = [[5., -10.], [0., 0.]]
p, l, u = linalg.lu(np.array([v1, v3]).T) # Full rank: u = [[5., 2.], [0., 3.]]
所有这些方法都会评估从矩阵的列跨越的向量空间的维数。如果矩阵是满秩的,那么你的向量是线性独立的。如果不是,则它们至少有两个因向量。
那么解决问题的简单方法是:
def indep1(*args):
A = np.array(args).T
return np.linalg.matrix_rank(A) == len(args)
indep1(v1, v2) # False
indep1(v1, v3) # True
indep1(v1, v2, v3) # False
indep1(v1, np.zeros(v1.size)) # False
特例
如果您停留在 3D 向量空间并且只需要检查两个向量,您还可以利用numpy.cross提供的叉积:
np.cross(v1, v2) # Colinear: [0, 0, 0]
np.cross(v1, v3) # Not colinear: [15, 0, -5]
更具体的替代方案是:
def indep2(a, b):
return not np.allclose(np.cross(a, b), 0.)
indep2(v1, v2) # False
indep2(v1, v3) # True
# indep2(v1, v2, v3) # TypeError
indep2(v1, np.zeros(v1.size)) # False
恒定比率
正如建议的那样@MadPhycist
,我们还可以评估共线向量共享标量比例因子的事实a = k*b
,那么测试它的非防弹方法是检查坐标的比率是否为常数:
def indep3(a, b):
r = a/b # Ratio of coordinates
q = np.isfinite(r) # Filter bad ratio (zero division)
return not np.allclose(r[q], r[q][0]) # Assess all ratio are equal
indep3(v1, v2) # False
indep3(v1, v3) # True
# indep3(v3, np.zeros(v1.size)) # IndexError
如果它比以前的解决方案需要更少的计算并且不依赖于高级线性代数,它需要处理特定情况并且建议的实现很臭(不要使用它)。
格拉姆方法
公开的方法@dmuir
可以安全地为两个向量实现,如下所示:
def indep4(a, b):
return not np.isclose(np.dot(a,b)*np.dot(b,a), np.dot(a,a)*np.dot(b,b))
indep4(v1, v2) # False
indep4(v1, v3) # True
indep4(v3, v4) # False
indep4(v3, np.zeros(v1.size)) # False
推荐阅读
- css - 按钮的背景颜色没有在 React 中立即更新,其他 css 属性工作正常
- python - 如何在 pandas 的多个 If 语句中减少 for 循环和 df.loc 的运行时间?
- android - 频繁调用fusedLocationProviderClient lastKnownLocation的Android电池消耗?
- java - 对经常超时的 API 进行休息调用的微服务设计模式
- r - (R) Markdown:如何在不插入空行的情况下定义新段落?
- php - 从 SHOUTcast 脚本 print_r ($vc_shoutcast->LISTENERS) 中删除重复项;
- python - 使用 Notebook 中的名称酸洗列表并在 Notebook2 中取消酸洗它们
- python - ModuleNotFoundError:即使安装后也没有名为“selenium”的模块
- java - Java 服务器的语言支持在过去 3 分钟内崩溃了 5 次。服务器不会重启
- xcode - 我在哪里可以删除我在 macOS Big Sur 中使用 Xcode 安装的 App 小部件?