AがNxN行列であり、逆行列がある場合に気づきました。ただし、inv()関数とpinv()関数の出力は異なります。 -私の環境はWin7x64SP1、Matlab R2012a、Cygwin Octave 3.6.4、FreeMat4.2です。
Octaveの例をご覧ください。
_A = Rand(3,3)
A =
0.185987 0.192125 0.046346
0.140710 0.351007 0.236889
0.155899 0.107302 0.300623
pinv(A) == inv(A)
ans =
0 0 0
0 0 0
0 0 0
_
ans
の結果になります。inv(A)*A
またはA*inv(A)
を計算すると、結果はOctaveとMatlabの両方で同一性の3x3行列になります。A*pinv(A)
とpinv(A)*A
の結果は、MatlabとFreeMatの同一性3x3行列です。A*pinv(A)
の結果は、Octaveのアイデンティティ3x3行列です。pinv(A)*A
の結果はnot Octaveのアイデンティティ3x3行列です。inv(A) != pinv(A)
の理由はわかりませんが、行列内の要素の詳細を検討しました。この問題の原因は、浮動精度の問題のようです。
ドットポイントの後の10桁以上は、次のように異なる場合があります。
inv(A)(1,1)
の_6.65858991579923298331777914427220821380615200000000
_要素に対して
pinv(A)(1,1)
の_6.65858991579923209513935944414697587490081800000000
_要素
この質問はかなり古いですが、いくつかのグーグル検索でほぼ一番上に表示されるので、とにかく答えます。
私の例では、N行N列の魔方陣を返すmagic(N)関数を使用します。
3x3の魔方陣M3を作成し、疑似逆行列PI_M3を取得して、それらを乗算します。
Prompt_ $ M3 = magic(3)、PI_M3 = pinv(M3)、M3 * PI_M3
M3 = 8 1 6 3 5 7 4 9 2 PI_M3 = 0.147222 -0.144444 0.063889 -0.061111 0.022222 0.105556 -0.019444 0.188889 -0.102778 ans = 1.0000e + 00 -1.2212e-14 6.3283e-15 5.5511e-17 1.0000e + 00 -2.2204e-16 -5.9952e-15 1.2268e-14 1.0000e +00
ご覧のとおり、答えは、丸め誤差を除いた単位行列です。 4x4の魔方陣で操作を繰り返します。
Prompt_ $ M4 = magic(4)、PI_M4 = pinv(M4)、M4 * PI_M4
M4 = 16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1 PI_M4 = 0.1011029 -0.0738971 -0.0613971 0.0636029 -0.0363971 0.0386029 0.0261029 0.0011029 0.0136029 -0.0113971 -0.0238 。]-0.0488971 0.0761029 0.0886029 -0.0863971 ans = 0.950000 -0.150000 0.150000 0.050000 -0.150000 0.550000 0.450000 0.150000 [.____。 0.150000 0.450000 0.550000 -0.150000 0.050000 0.150000 -0.150000 0.950000
結果は単位行列ではなく、4x4魔方陣に逆行列がないことを意味します。これは、ムーアペンローズ疑似逆の規則の1つを試すことで確認できます。
Prompt_ $ M4 * PI_M4 * M4
ans = 16.00000 2.00000 3.00000 13.00000 5.00000 11.00000 10.00000 8.00000 9.00000 7.00000 6.00000 12.00000 4.00000 14.00000 15.00000 1.00000
ルールA * B * A = Aが満たされます。これは、pinvが利用可能な場合は逆行列を返し、逆行列が利用できない場合は疑似逆行列を返すことを示しています。これが、状況によっては小さな差が発生し、丸め誤差が発生する場合もあれば、大きな差が発生する場合もある理由です。それを示すために、両方のマジッククアドラントの逆行列を取得し、それらを疑似逆行列から減算します。
Prompt_ $ I_M3 = inv(M3)、I_M4 = inv(M4)、DIFF_M3 = PI_M3-I_M3、DIFF_M4 = PI_M4-I_M4
I_M3 = 0.147222 -0.144444 0.063889 -0.061111 0.022222 0.105556 -0.019444 0.188889 -0.102778 警告:逆行列:行列はマシンの精度に対して特異、rcond = 1.30614e-17 I_M4 = 9.3825e + 13 2.8147e + 14 -2.8147e + 14 -9.3825e + 13 2.8147e + 14 8.4442e + 14 -8.4442e + 14 -2.8147e + 14 -2.8147e + 14 -8.4442e + 14 8.4442e + 14 2.8147e + 14 -9.3825e + 13 -2.8147e + 14 2.8147e + 14 9.3825e + 13 DIFF_M3 = 4.7184e-16 -1.0270e- 15 5.5511e-16 -9.9226e-16 2.0470e-15 -1.0825e-15 5.2042e-16 -1.0270e-15 4.9960e-16 DIFF_M4 = -9.3825e + 13 -2.8147e + 14 2.8147e + 14 9.3825e + 13 -2.8147e + 14 -8.4442e + 14 8.4442e + 14 2.8147e + 14 2.8147e + 14 8.4442e + 14 -8.4442e + 14 -2.8147e + 14 9.3825e + 13 2.8147e + 14 -2.8147e + 14 -9.3825e + 13
あなたがここの一番下であなた自身の質問に答えたように私には思えます。その理由は浮動小数点演算です。 inv()
とpinv()
のアルゴリズムは完全に同じではありません。これは、pinv()
が非正方行列を処理できる必要があるためです。したがって、答えは完全に同じではありません。
pinv(A)*A
の値を見ると、単位行列に非常に近いことがわかります。
私は得る:
_ans =
1.0000e+00 6.1062e-16 -3.0809e-15
-5.8877e-15 1.0000e+00 6.3942e-15
2.4425e-15 -3.0184e-16 1.0000e+00
_
行列を_==
_と比較する代わりに、_< tolerance_limit
_を使用します
_c = A*pinv(A);
d = pinv(A)*A;
(c-d) < 1e-10
_
補足:
_x = A^-1*b
_は解決すべきではありませんx = inv(A)*b;
ではなく、_x = A \ b;
_説明については Shaiが投稿したリンク を参照してください。
浮動小数点演算には一定の精度があり、平等に頼ることはできません。このようなエラーを回避するには、matlabのシンボリックツールボックスを使用してみてください。
問題を示すためのオクターブ単位の非常に単純なコード行:
>>> (1/48)*48==(1/49)*49
ans = 0
>>> (1/48)*48-(1/49)*49
ans = 1.1102e-16
>>>