行列から線形独立行を識別する方法は?例えば、
4行目は独立しています。
まず、3行目は1tと2行目で線形従属です。ただし、1列目と4列目は線形従属です。
使用できる2つの方法:
固有値
行列の1つの固有値がゼロの場合、対応する固有ベクトルは線形従属です。ドキュメント eig は、固有値が必ずしも順序付けられていないことを示しています。結果の配列の固有値が単に並べ替えられているのか、ランダムな順序であるのかは、本当にわかりません。ただし、固有値が行ベクトルに対応しているとすると、メソッドは次のようになります。
import numpy as np
matrix = np.array(
[
[0, 1 ,0 ,0],
[0, 0, 1, 0],
[0, 1, 1, 0],
[1, 0, 0, 1]
])
lambdas, V = np.linalg.eig(matrix.T)
# The linearly dependent row vectors
print matrix[lambdas == 0,:]
コーシー・シュワルツの不等式
ベクトルの線形依存性をテストし、どの依存関係かを調べるには、 Cauchy-Schwarz不等式 を使用できます。基本的に、ベクトルの内積がベクトルのノルムの積に等しい場合、ベクトルは線形従属です。以下は列の例です。
import numpy as np
matrix = np.array(
[
[0, 1 ,0 ,0],
[0, 0, 1, 0],
[0, 1, 1, 0],
[1, 0, 0, 1]
])
print np.linalg.det(matrix)
for i in range(matrix.shape[0]):
for j in range(matrix.shape[0]):
if i != j:
inner_product = np.inner(
matrix[:,i],
matrix[:,j]
)
norm_i = np.linalg.norm(matrix[:,i])
norm_j = np.linalg.norm(matrix[:,j])
print 'I: ', matrix[:,i]
print 'J: ', matrix[:,j]
print 'Prod: ', inner_product
print 'Norm i: ', norm_i
print 'Norm j: ', norm_j
if np.abs(inner_product - norm_j * norm_i) < 1E-5:
print 'Dependent'
else:
print 'Independent'
行をテストすることも同様のアプローチです。
次に、これを拡張してベクトルのすべての組み合わせをテストすることもできますが、このソリューションはサイズに応じてうまく拡張できないと思います。
sympy を使用すると、次を使用して線形独立行を見つけることができます。 sympy.Matrix.rref
:
>>> import sympy
>>> import numpy as np
>>> mat = np.array([[0,1,0,0],[0,0,1,0],[0,1,1,0],[1,0,0,1]]) # your matrix
>>> _, inds = sympy.Matrix(mat).T.rref() # to check the rows you need to transpose!
>>> inds
[0, 1, 3]
これは基本的に、行0、1、3が線形独立であることを示しますが、行2はそうではありません(行0と1の線形結合です)。
次に、これらの行をスライスして削除できます。
>>> mat[inds]
array([[0, 1, 0, 0],
[0, 0, 1, 0],
[1, 0, 0, 1]])
これは、(2次行列だけでなく)長方形行列にも有効です。
コーシーシュワルツの不等式のコードを編集しました。これは、次元に合わせてスケーリングします。入力は行列とその次元であり、出力は、行に沿って開始行列の線形独立列を含む新しい長方形行列です。これは、最初の列がnullになることはないという前提で機能しますが、この場合も実装するために簡単に一般化できます。私が観察したもう1つのことは、一部の特定の病理学的ベクトルがその場合線形依存であることが判明したため、1e-5は「だらしない」しきい値のように見えることです。1e-4では同じ問題が発生しません。私はこれがいくつかの助けになることを願っています:私がliベクトルを抽出するための本当に機能するルーチンを見つけるのはかなり困難でしたので、私は喜んで私と共有します。バグを発見したら、報告してください!!
from numpy import dot, zeros
from numpy.linalg import matrix_rank, norm
def find_li_vectors(dim, R):
r = matrix_rank(R)
index = zeros( r ) #this will save the positions of the li columns in the matrix
counter = 0
index[0] = 0 #without loss of generality we pick the first column as linearly independent
j = 0 #therefore the second index is simply 0
for i in range(R.shape[0]): #loop over the columns
if i != j: #if the two columns are not the same
inner_product = dot( R[:,i], R[:,j] ) #compute the scalar product
norm_i = norm(R[:,i]) #compute norms
norm_j = norm(R[:,j])
#inner product and the product of the norms are equal only if the two vectors are parallel
#therefore we are looking for the ones which exhibit a difference which is bigger than a threshold
if absolute(inner_product - norm_j * norm_i) > 1e-4:
counter += 1 #counter is incremented
index[counter] = i #index is saved
j = i #j is refreshed
#do not forget to refresh j: otherwise you would compute only the vectors li with the first column!!
R_independent = zeros((r, dim))
i = 0
#now save everything in a new matrix
while( i < r ):
R_independent[i,:] = R[index[i],:]
i += 1
return R_independent
私はこれが少し前に尋ねられたことを知っていますが、これは非常に簡単な解決策です。配列が与えられた場合、次の例では、ベクトルを徐々に追加し、ランクが増加したかどうかをテストすることにより、線形独立のベクトルのセットを見つけます。
from numpy.linalg import matrix_rank
def LI_vecs(dim,M):
LI=[M[0]]
for i in range(dim):
tmp=[]
for r in LI:
tmp.append(r)
tmp.append(M[i]) #set tmp=LI+[M[i]]
if matrix_rank(tmp)>len(LI): #test if M[i] is linearly independent from all (row) vectors in LI
LI.append(M[i]) #note that matrix_rank does not need to take in a square matrix
return LI #return set of linearly independent (row) vectors
#Example
mat=[[1,2,3,4],[4,5,6,7],[5,7,9,11],[2,4,6,8]]
LI_vecs(4,mat)
この問題を、他の行から線形的に独立している行を見つけると解釈します。これは、他の行に線形に依存する行を見つけることと同じです。
ガウス消去法を使用して、しきい値よりも小さい数値をゼロとして処理できるようにします。これは、行列の固有値を見つけ、コーシーシュワルツの不等式、または特異値分解を使用して行のすべての組み合わせをテストするよりも高速です。
浮動小数点数の問題:
http://numpy-discussion.10968.n7.nabble.com/Reduced-row-echelon-form-td16486.html