Pythonを用いたデータ分析やAI開発において、行列の計算は避けては通れない非常に重要な要素です。
この記事では、標準ライブラリ以外の環境でも動作するfor文を用いた実装から、現代のスタンダードであるNumPyによる高速な計算手法まで、具体的なコードと共に詳しく解説していきます。
![]() 執筆者:マヒロ |
|
- OS:Windows 11 / macOS Sequoia
- IDE:Visual Studio / VS Code / IntelliJ IDEA
- その他:Chrome DevTools / 各言語最新安定版
※本メディアでは、上記環境にてコードの動作と情報の正確性を検証済みです。
Pythonで行列を作成・入力・表示する基本手法
行列の掛け算を行う前段階として、まずはPythonプログラム上で行列をどのように定義し、操作するのかという基礎を確認しましょう。
Pythonで行列を扱う代表的な方法には、標準の「2次元リスト」と、数値計算に特化した「NumPy配列」の2種類があります。
ここでは、データの作成方法から、プログラム実行中に値を反映させる行列の入力手順、そして中身を確認するための行列の表示手法を見ていきます。
行列の作成と表示のバリエーション
import numpy as np
# NumPyを使用した行列の作成
matrix_a = np.array([
[1, 2],
[3, 4]
])
# 標準リストを使用した行列の作成
matrix_b = [
[5, 6],
[7, 8]
]
print("--- NumPy形式の表示 ---")
print(matrix_a)
print("\n--- リスト形式の表示 ---")
print(matrix_b)
実行結果
--- NumPy形式の表示 ---
[[1 2]
[3 4]]
--- リスト形式の表示 ---
[[5, 6], [7, 8]]
上記のコードでは、まず数値計算ライブラリのNumPyをインポートし、np.array() 関数を使って2×2の行列を定義しています。
NumPyを使用した場合、出力結果が行列の形に整列されるため、データの構造を一目で把握できるのが大きなメリットと言えるでしょう。
一方、標準のリスト形式で作成した場合は、単純なリストの中にリストが格納されている構造であるため、出力も1行に繋がった形式になります。
用途に応じてこれらを使い分けるのが一般的ですが、大規模な計算を行う場合はNumPy形式を選択するのが賢明です。
ユーザーによる行列データの入力
実用的なプログラムでは、あらかじめ決められた値だけでなく、ユーザーがその場で入力したデータを行列に反映させたい場面が多くあります。
# 行数と列数を指定
rows = int(input("行数を入力してください: "))
cols = int(input("列数を入力してください: "))
# 行列の入力処理
matrix = []
print(f"{rows}x{cols}の行列要素を入力してください。")
for i in range(rows):
row_input = list(map(int, input(f"{i+1}行目の要素をスペース区切りで入力: ").split()))
matrix.append(row_input)
print("\n入力された行列の確認:")
for row in matrix:
print(row)
実行結果(例:2×2行列を入力した場合)
行数を入力してください: 2
列数を入力してください: 2
2x2の行列要素を入力してください。
1行目の要素をスペース区切りで入力: 10 20
2行目の要素をスペース区切りで入力: 30 40
入力された行列の確認:
[10, 20]
[30, 40]
このプログラムでは、まず input() 関数を使って行列のサイズ(行と列)を決定しています。
その後、指定された行数分だけループを回し、スペース区切りで入力された文字列を split() で分割、さらに map(int, ...) で数値に一括変換してリスト化しています。
このようにして作成された各行を親リストに追加していくことで、動的に行列を作成することが可能になります。
最終的に for 文を使って1行ずつ出力することで、リスト形式であっても視覚的に分かりやすい表示を実現しています。
NumPyによる高速な行列の掛け算(行列積)
実務でPythonにおける行列の積を扱う際、最も頻繁に利用されるのがNumPyライブラリです。
NumPyは内部がC言語やFortranで最適化されているため、標準のPython機能で計算するよりも圧倒的に高速な処理が期待できます。
ここでは、現在の主流である@演算子の使い方や、複雑な3つ以上の行列を連続して掛け合わせる際の実装方法について、詳細に解説を進めます。
@演算子と専用関数による計算
import numpy as np
# 行列の定義
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# 方法1:@演算子(推奨される書き方)
result_at = A @ B
# 方法2:np.dot()関数
result_dot = np.dot(A, B)
# 方法3:np.matmul()関数
result_matmul = np.matmul(A, B)
print("行列積の結果(@演算子):\n", result_at)
実行結果
行列積の結果(@演算子):
[[19 22]
[43 50]]
現在の環境において、行列の掛け算を行う最も洗練された方法は@演算子を使用することです。
@演算子はPython 3.5以降で導入された専用の演算子で、数式に近い感覚で直感的に記述できるため、コードの可読性が飛躍的に向上するという利点があります。
一方で、古くから使われている np.dot() 関数は、行列だけでなくスカラー(単一の数値)との掛け算にも対応しているという汎用性を持っています。
また、np.matmul() 関数は多次元配列(テンソル)の計算において数学的な定義に忠実な挙動を示すため、ディープラーニングなどの高度な分野で好んで使われます。
基本的には@演算子を選び、特定の用途がある場合に他の関数を検討するのがベストプラティクスです。
3つ以上の行列を連続して掛ける手法
実務の計算では、2つの行列だけでなく、3つ以上の行列を一度に掛け合わせるケースも少なくありません。
C = np.array([[1, 0], [0, 1]])
# 3つの行列の積
result_triple = A @ B @ C
print("3つの行列の積の結果:\n", result_triple)
実行結果
3つの行列の積の結果:
[[19 22]
[43 50]]
数学的に行列の積は結合法則が成り立つため、A × B × C という計算において、どのペアから計算しても結果は一致します。
Pythonのプログラム上では、演算子を左から順番に適用していくことで計算が行われます。
上記のように演算子を繋げて記述するだけで、複雑な多段の行列演算も簡潔に表現できるため、プログラムの保守性が非常に高まるでしょう。
NumPyを使わない行列の掛け算(for文による実装)
ライブラリを自由にインストールできない制限のある環境や、アルゴリズムの基礎を深く学習したい場合には、NumPyに頼らない計算手法が求められます。
ここでは、for文を入れ子にする(ネストする)ことで、行列積の定義をプログラムコードとして再現する方法を詳しく解説します。
for文による行列積のロジック構築
# 2x3の行列A
matrix_a = [
[1, 2, 3],
[4, 5, 6]
]
# 3x2の行列B
matrix_b = [
[7, 8],
[9, 10],
[11, 12]
]
# 結果を格納する2x2の行列を0で初期化
result = [[0 for _ in range(len(matrix_b[0]))] for _ in range(len(matrix_a))]
# 3重のfor文による行列積の計算
for i in range(len(matrix_a)): # 行列Aの行をループ
for j in range(len(matrix_b[0])): # 行列Bの列をループ
for k in range(len(matrix_b)): # 計算の共通次元をループ
result[i][j] += matrix_a[i][k] * matrix_b[k][j]
print("NumPyを使わない計算結果:")
for row in result:
print(row)
実行結果
NumPyを使わない計算結果:
[58, 64]
[139, 154]
このコードは、行列積の定義である「左側の行列の行と、右側の行列の列の要素を順に掛け合わせ、その合計を算出する」というプロセスを忠実に再現したものです。
まず、計算結果を格納するための「空の行列」を準備する必要がありますが、ここではリスト内包表記を使用して、あらかじめ全ての要素が 0 の2次元リストを作成しています。
実際の計算は3重のfor文によって行われています。
一番外側のループが結果行列の「行」を、二番目のループが「列」を決定し、一番内側の三番目のループが各要素の積を計算して合計値(累積和)を求めています。
この手法はNumPyを使わない場合の標準的な実装ですが、データ量が増えると計算時間が指数関数的に増大するため、基本的には学習用や小規模なデータ処理に適した方法と言えるでしょう。
逆行列の計算と特定の要素へのアクセス
行列演算において、掛け算と同様に重要となるのが逆行列の扱いです。
また、計算結果から特定の数値だけを取り出したり、値を変更したりする要素操作のスキルも、データの前処理において欠かせません。
ここでは、NumPyを用いた高度な行列操作と、個別の行列の要素に対するアクセス方法について解説します。
NumPyによる逆行列の算出
import numpy as np
# 正方行列を定義
A = np.array([
[1, 2],
[3, 4]
])
# 逆行列の計算
try:
inv_A = np.linalg.inv(A)
print("逆行列:\n", inv_A)
# 元の行列との積が単位行列になるか確認
check = A @ inv_A
print("\nAと逆行列の積(単位行列):\n", np.round(check))
except np.linalg.LinAlgError:
print("この行列には逆行列が存在しません。")
実行結果
逆行列:
[[-2. 1. ]
[ 1.5 -0.5]]
Aと逆行列の積(単位行列):
[[1. 0.]
[0. 1.]]
逆行列を求めるには、NumPyの線形代数モジュールである linalg.inv() 関数を使用するのが最も効率的です。
行列 A に対して、A × A⁻¹ = I(I は単位行列)となるような A⁻¹ を自動で算出します。
ただし、全ての行列に逆行列が存在するわけではなく、行列式が 0 の場合はエラーが発生するため、上記のコードのように try-except 構文を用いてエラーを回避するのが実務的な実装です。
計算結果を確認するために元の行列と掛け合わせると、浮動小数点の微小な誤差を np.round() で整えることで、きれいな単位行列が再現されていることが分かります。
行列の特定要素へのアクセスと更新
行列内の特定のデータのみを操作したい場合は、インデックスを指定してアクセスします。
# 行列Aの [0行目, 1列目] の要素を取得
# インデックスは0から始まる点に注意
val = A[0, 1]
print(f"現在の要素[0, 1]の値: {val}")
# 特定の要素の値を書き換える
A[0, 1] = 100
print("更新後の行列A:\n", A)
実行結果
現在の要素[0, 1]の値: 2
更新後の行列A:
[[ 1 100]
[ 3 4]]
NumPyでは [行番号, 列番号] という直感的な形式で行列の要素にアクセスすることができます。
標準のPythonリストとは異なり、コンマで区切って一度に指定できるため、記述が非常にスマートになります。
この手法を使えば、特定のデータだけをサンプリングしたり、異常値を修正したりといった操作が自由自在に行えるようになります。
Pythonのスキルを活かして年収を上げる方法
以上、Pythonで行列の掛け算を効率化する方法について解説してきました。
Pythonエンジニアの需要は非常に高いため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。
なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。
| 年収アップにこだわりたい方 (平均アップ額138万円の実績) | テックゴー |
| 未経験・経験者問わず幅広く探したい方 | ユニゾンキャリア |
| 業界に精通した担当者に相談したい方 | キッカケエージェント |
| ゲーム業界への転職を志望する方 | ファミキャリ |
| エンジニア未経験からキャリアを築く方 | イーチキャリア |



