線形代数
1. 学習内容
- ❶ 行列の乗算:
@、np.dot、np.matmul - ❷ 逆数と行列式:
np.linalg.inv、np.linalg.det - ❸ 固有値と固有ベクトル:
np.linalg.eig - ❹ 連立一次方程式の解法:
np.linalg.solve - ❺ 行列の分解:QR分解、SVD、コレスキー分解
2. ストーリー
ボブは1000個の線形方程式の連立方程式を解く必要があります。彼はガウス消去法のループを記述しましたが、処理時間は30秒で、実装にはバグがありました。一方、アリスはnp.linalg.solve(A, b)を使用し、処理時間は0.01秒で、正確な結果を得ました。 「NumPyでの線形代数は単に高速なだけでなく、MATLABやRでも使用されているのと同じライブラリであるBLAS/LAPACKを呼び出します。これらは数十年にわたり実戦でその実力が証明されています。」
3. 主要な概念
(1) 行列の乗算
PYTHON
import numpy as np
A = np.array([[1, 2],
[3, 4]])
B = np.array([[5, 6],
[7, 8]])
# Three equivalent ways:
print(A @ B) # [[19 22]
# [43 50]]
print(np.dot(A, B)) # same
print(np.matmul(A, B)) # same
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(2) 逆行列と行列式
PYTHON
import numpy as np
A = np.array([[1, 2],
[3, 4]])
det = np.linalg.det(A) # -2.000
inv = np.linalg.inv(A) # [[-2. 1. ]
# [ 1.5 -0.5]]
print(A @ inv) # [[1. 0.]
# [0. 1.]] (identity)
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(3) 連立一次方程式の解法
PYTHON
# Solve Ax = b
A = np.array([[3, 1],
[1, 2]])
b = np.array([9, 8])
x = np.linalg.solve(A, b)
print(x) # [2. 3.]
print(A @ x) # [9. 8.] — verify
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(1) ▶ サンプル:行列の乗算(難易度 ⭐)
PYTHON
import numpy as np
A = np.array([[1, 2, 3],
[4, 5, 6]])
B = np.array([[7, 8],
[9, 10],
[11, 12]])
# Matrix multiply: (2x3) @ (3x2) = (2x2)
C = A @ B
print("A @ B:\n", C)
# Dot product of vectors
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
print("dot(x, y):", np.dot(x, y))
出力:
TEXTA @ B: [[ 58 64] [139 154]] dot(x, y): 32
(2) ▶ サンプル:連立一次方程式の解法(難易度 ⭐⭐)
PYTHON
import numpy as np
# Solve: 3x + y = 9, x + 2y = 8
A = np.array([[3, 1],
[1, 2]])
b = np.array([9, 8])
x = np.linalg.solve(A, b)
print("Solution:", x)
# Verify
print("A @ x =", A @ x)
print("b =", b)
出力:
TEXT解答:[2. 3.] A @ x = [9. 8.] b = [9. 8.]
(3) ▶ サンプル:固有値と固有ベクトル(難易度 ⭐⭐)
PYTHON
import numpy as np
A = np.array([[4, -2],
[1, 1]])
eigenvalues, eigenvectors = np.linalg.eig(A)
print("Eigenvalues:", eigenvalues)
# Verify: A @ v = λ * v
v = eigenvectors[:, 0]
lam = eigenvalues[0]
lhs = A @ v
rhs = lam * v
print("A @ v:", lhs)
print("λ * v:", rhs)
print("Match:", np.allclose(lhs, rhs))
出力:
TEXT固有値:[3, 2] A @ v: [0.89442719 0.4472136 ] λ * v: [0.89442719 0.4472136 ] 一致:True
Q
@、np.dot、np.matmul の違いは何ですか?A 2次元配列の場合、これらは同一です。 高次元の場合、
@とnp.matmulはブロードキャスティング(積層行列乗算)を使用するのに対し、np.dotは各要素の最終軸に対して和積を使用します。Q
solve と inv は、それぞれどのような場合に使用すべきですか?A 常に
solve を使用してください。処理速度が速く、数値的な安定性も高いからです。 inv(A) @ bの計算は、solve(A, b)に比べて処理速度が遅く、精度も劣ります。Q A が単体行列の場合はどうなりますか?
A
np.linalg.solve は LinAlgError: Singular matrix を呼び出します。過決定・欠決定系の最小二乗解を求めるには、np.linalg.lstsq を使用してください。❓ よくある質問
Q 最も重要なポイントは何か?
A NumPyの演算はベクトル化されているため、パフォーマンスを向上させるにはPythonのループは避けるべきだ。
Q さらに詳しく知りたい場合はどうすればよいですか?
A 詳細なリファレンスや高度なトピックについては、numpy.org の NumPy 公式ドキュメントをご覧ください。
Q これはNumPy 2.xでも動作しますか?
A はい。すべての例はNumPy 2.xと互換性があります。一部の古いAPI(np.random.seedなど)は引き続きサポートされていますが、最新の代替APIの使用をお勧めします。
📖 まとめ
@/np.matmul/np.dot: 行列の乗算np.linalg.inv: 行列の逆行列;np.linalg.det: 行列式np.linalg.eig: 固有値と固有ベクトルnp.linalg.solve: 連立一次方程式の解法np.linalg.qr、np.linalg.svd、np.linalg.cholesky:分解- 速度と安定性を高めるため、
inv @ bの代わりにsolveを使用してください
📝 練習問題
-
初心者向け(難易度 ⭐):ランダムな整数からなる 3×3 の行列を 2 つ作成する。それらの積、行列式、および逆行列を計算する。A @ inv(A) ≈ 単位行列であることを確認する。
-
中級(難易度 ⭐⭐):
np.linalg.solveを使って、連立方程式 3x + y = 9, x + 2y = 8 を解きなさい。答えが正しいか確認しなさい。 -
上級(難易度 ⭐⭐⭐):5×5のランダムな行列を生成し、その固有値と固有ベクトルを計算する。各固有値・固有ベクトルの組について、A @ v = λ * v となることを確認する。