web-dev-qa-db-ja.com

行列が特異かどうかを調べる方法は?

4x4行列が特異かどうかを知るにはどうすればいいですか?

特定の行列に単位行列を追加してから行操作を行わなくても、これを知ることができますか?

27
Madu

それでは、マトリックスが本当に特異であるかどうかをどのように識別しますか? (MATLABでは、紙と鉛筆またはシンボリック計算、または手書きの行操作を使用しませんか?)教科書では、行列式を使用するように生徒に指示することがありますので、ここから始めます。

理論的には、行列の行列式がゼロかどうかを簡単にテストできます。かくして

M = magic(4)
M =
    16     2     3    13
     5    11    10     8
     9     7     6    12
     4    14    15     1

det(M)
ans =
  -1.4495e-12

判明したように、この行列は確かに特異であるため、Mの行を他の行の線形結合として書き込む方法があります(列についても同様です)。しかし、detから正確にゼロではない値を取得しました。それは本当にゼロですか、MATLABはちょうど混乱しましたか?何故ですか?シンボリック行列式は本当にゼロです。

det(sym(M))
ans =
0

結局のところ、行列式の計算は、より大きな配列にとっては非常に非効率的なものです。したがって、ニースの代替案は、正方配列の特定の行列因子分解の対角要素の積を使用することです。実際、これは、MATLABが非記号入力に対して内部で行うことです。

[L,U,P] = lu(M)
L =
            1            0            0            0
         0.25            1            0            0
       0.3125      0.76852            1            0
       0.5625      0.43519            1            1
U =
           16            2            3           13
            0         13.5        14.25        -2.25
            0            0      -1.8889       5.6667
            0            0            0   3.5527e-15
P =
     1     0     0     0
     0     0     0     1
     0     1     0     0
     0     0     1     0

Lの対角要素は1ですが、Uには非ゼロの対角要素があります。また、行列の積の行列式、および上三角行列または下三角行列の行列式についてのニースの特性があります。

prod(diag(U))
ans =
  -1.4495e-12

同じ答えを得たことを確認してください。 LU因数分解は大きな配列に対してもかなり速いので、行列式を計算するのに良い方法です。問題は、浮動小数点演算を使用することです。浮動小数点数。製品を取得すると、正確にゼロではない結果が得られます。

Detには他にも問題があります。たとえば、行列eye(100)が非常によく条件付けられていることがわかります。結局、それは単位行列です。

det(eye(100))
ans =
     1

さて、行列に定数を掛けると、行列の状態は特異なものとして変わりません。しかし、行列式はどうなりますか?

det(.1*eye(100))
ans =
   1e-100

この行列は特異ですか?結局、det(magic(4))が1e-12を与える場合、1e-100は特異行列に対応しなければなりません!しかし、そうではありません。さらに悪いことに、

det(.0001*eye(100))
ans =
     0

実際、行列式は0.0001 ^ 100でスケーリングされ、matlabでは1e-400になります。少なくともmatlabがdoubleを使用してそれほど小さい数を表すことができれば、それは真実です。そうすることはできません。その数はアンダーフローします。または、簡単にオーバーフローさせることができます。

det(10000*eye(100))
ans =
   Inf

明らかに、これらのスケーリングされた単位行列はすべて等しく非特異ですが、私たちが見たい答えを私たちに与えることができます!したがって、行列式を計算することは、行列に対して行うべき恐ろしいことであると結論付けなければなりません。あなたの教科書がずっと前に言ったことや、上司や先生が言ったことは気にしません。コンピュータを使用して、この目的のために行列式を計算するように誰かに言われた場合、それはひどいアドバイスでした。期間。決定要因には単純に問題が多すぎます。

特異性をテストするために他のことを行うことができます。最良のツールはランクを使用することです。したがって、NxM行列のランクがmin(N、M)より小さい場合、その行列は特異です。以下にいくつかのテストを示します。

rank(M)
ans =
     3

rank(.0001*eye(100))
ans =
   100

したがって、ランクは4x4の魔方陣が特異であることを教えてくれますが、スケーリングされた単位行列は特異ではありません。 (良いことは、ランクが非正方行列の特異性をテストできることです。)

Condを使用して、数値の特異性をテストすることもできます。可能な最小の条件番号は1.0で、これは非常に適切に動作するマトリックスに対応します。条件数が大きいと悪いです。倍精度では、これは、条件数が約1e15より大きい場合、マトリックスに非常に問題があることを意味します。

cond(M)
ans =
    8.148e+16

cond(.0001*eye(100))
ans =
     1

実際、condは、スケーリングされた単位行列が条件付きであると認識しています。条件数が大きいと悪いです。倍精度の行列の場合、1e15程度に近い条件番号は、おそらく数値的に特異な行列を示します。したがって、Mは明らかに特異であることがわかります。繰り返しますが、condは非正方行列でも機能します。

または、条件数の逆数を推定するツールであるrcondを使用できます。これは、本当に大きな配列に適したツールです。 rcondがepsに近い任意の数を与えるとき、注意してください!

rcond(M)
ans =
   1.3061e-17

rcond(.0001*eye(100))
ans =
     1

最後に、(私のような)数学的ギアヘッドについては、svdを引き出すかもしれません。結局のところ、svdはcondとrankが基づいているツールです。行列の1つ以上の特異値が最大の特異値と比較して小さい場合、再び特異性があります。

svd(M)
ans =
           34
       17.889
       4.4721
   4.1728e-16

ここで、行列の最大の特異値と比較して特異値が小さい場合を見てみましょう。良いことは、svdがマトリックスが特異点にどれだけ近いか、そして複数の小さな特異値がある場合、マトリックスのランクに関する情報を提供するかどうかを教えてくれることです。

嬉しいことに、これまでに示したツールのいずれも、ユーザーが基本的な行操作などを行う必要はありません。

ただし、DETは使用しないでください!はい、教科書に載っています。はい、おそらくあなたのインストラクターまたはあなたの上司がそれを使用するようにあなたに言ったでしょう。このようなツールは、浮動小数点演算を使用するコンピューターに適用すると失敗するため、それらは単に間違っていました。また、シンボリックな行列式を計算したくないだけで、ひどく非効率的です。

これが長い間読まれていたらごめんなさい。私は今、ソープボックスを降ります。

104
user85109

ランクを計算し、ディメンションと比較します。ランクが次元より低い場合、マトリックスは特異です。

9

最も信頼できるアプローチは、行列の特異値分解を実行することです。最大の特異値と最小の特異値の比率は、ある程度の許容範囲内でなければなりません。この比率は、マトリックスの条件番号です。倍精度の値では、条件数が100万以上を超えると、倍精度の値で非常に簡潔になりますが、これはかなり高い制限です。 SVDを取得したら、条件番号を計算するだけでなく、他の多くのことに役立ちます。

特異値分解は、数値解析のスイス軍のチェーンソーです。行列が特異/悪条件ではないことがわかっている場合、ツールの扱いが少し重くなる可能性があります。しかし、わからない場合は、知っておくと良いツールです。 Matlabは組み込みツールなので、特にそうです。

4
David Hammen

condを使用します。これにより、行列が特異にどれだけ近いかを数値的に推定できます(Infは特異行列です)。

例えば:

m = randn(4);
cond(m)   %Well conditioned, usually in the 10's

m = diag([1e-6 1 2 1e6]);
cond(m)   %Less well conditioned, 1e12

m = diag([0 1 2 3]);
cond(m)   %Singular:  Inf
3
Pursuit