行列の乗算は、線形代数の基本的な操作です。
通常、画像処理、機械学習など、さまざまなアプリケーションで使用されています。 NumPy は、科学計算用の注目すべき Python パッケージです。
ただし、この投稿では、NumPy を使用せずに Python で行列乗算を行うためのさまざまな方法を見ていきます。
活用させていただきます ネストされたループ、組み込みの map() 関数、およびリスト内包表記。
さらに、各戦略の利点と欠点、およびそれぞれをいつ適用するかについても見ていきます。 線形代数が初めてで、行列の乗算について詳しく知りたい場合。 読み続けてください。
行列乗算はどこで使用しますか?
行列乗算は コンピューターグラフィックス 2D および 3D ビジュアルを変更します。 たとえば、画面上のオブジェクトを回転、スケーリング、および移動できます。 マトリックスは、画像処理で画像をピクセルの配列として表すために使用されます。 さらに、マトリックスを使用して、画像フィルタリングなどの操作を実行することもできます。
また、マトリックスを利用します 機械学習. これらは、データとモデルのパラメーターを表すのに役立ちます。 ドット積や行列ベクトル積の計算など、さまざまな操作を実行できます。
確かに、この作戦は科学作戦においても非常に有利です。 物理学と工学で物理量を記述するために使用できます。 したがって、ベクトルとテンソルを操作できます。
NumPy の使用を選択できない理由
NumPy は Pythonライブラリ、行列乗算の理想的なオプションであるとは限りません。 サイズや依存関係、学習、レガシー システムなどの理由で、NumPy の使用を選択しない場合があります。
場合によっては、Python の組み込み関数を使用するか、カスタム コードを開発する方が効率的です。 ただし、NumPy は強力なライブラリであることに注意してください。 また、行列の乗算にも使用できます。
それでは、NumPy を使用せずに行列乗算を実現する方法を見てみましょう。
入れ子ループ方式
ネストされたループ手法は、ネストされたループを使用して Python で行列乗算を実行します。 関数は各行列要素を反復処理します。 そして、一連のネストされたループを使用してそれらを乗算します。 この関数は結果を返し、それは新しい行列に格納されます。
このアプローチは簡単に理解できます。 ただし、特に大きな行列の場合、他の方法ほど効率的ではない場合があります。 それでも、線形代数を初めて使用する場合は、素晴らしい選択です。
def matrix_multiplication(A, B):
# Determine the matrices' dimensions.
rows_A = len(A)
cols_A = len(A[0])
rows_B = len(B)
cols_B = len(B[0])
# 結果の行列をゼロに設定します。
result = [[0 for row in range(cols_B)] for col in
range(rows_A)]
# Iterate through rows of A
for s in range(rows_A):
# Iterate through columns of B
for j in range(cols_B):
# Iterate through rows of B
for k in range(cols_A):
result[s][j] += A[s][k] * B[k][j]
return result
これを行う方法の例を見てみましょう。 以下のコード行を追加するだけで、この例をテストできます。
# Sample matrices
A = [[1, 4, 3], [4, 9, 6]]
B = [[7, 8], [9, 10], [11, 12]]
# Perform matrix multiplication
result = matrix_multiplication(A, B)
# Print the result
print(result)
# Output: [[76, 84], [175, 194]]
利点:
- わかりやすい。
- 初心者または行列乗算のより深い理解を求めている人に最適です。
短所:
- 特に大きなマトリックスの場合、代替手法ほど効果的ではありません。
- 代替アプローチほど読みにくいです。
map() 関数メソッド
map() 関数メソッドは、Python で行列乗算を行うための代替アプローチを提供します。 このアプローチでは、組み込みの map() 関数を使用します。 したがって、提供された関数を反復可能な各要素 (リスト、タプルなど) に適用する関数型プログラミング ツールを使用します。 また、map() 関数は、関数とイテラブルの XNUMX つのパラメーターを受け入れます。 そして、反復可能な各要素に関数を適用する反復子を返します。
このアプローチでは、行列の各メンバーを調べ、ネストされた map() 関数を使用して乗算を行います。
zip() 関数は、行列の各要素を並列に反復するために使用されます。
最後に、sum() 関数を使用して結果を合計します。
def matrix_multiplication(A, B):
# To get the dimensions of the matrices
rows_A = len(A)
cols_A = len(A[0])
rows_B = len(B)
cols_B = len(B[0])
# We use map() function for multiplication.
result = [[sum(a * b for a, b in zip(row_a, col_b)) for
col_b in zip(*B)] for row_a in A]
return result
ここで、例を使用してコードをテストできます。
# Example matrices
A = [[3, 2, 3], [4, 5, 6]]
B = [[7, 8], [9, 10], [11, 12]]
# Use map() function to perform matrix multiplication
result = list(map(lambda x: list(map(lambda y: sum(i*j
for i,j in zip(x,y)), zip(*B))), A))
# Print the result
print(result)
# Output: [[72, 80], [139, 154]]
Advantages
- スタック ループ アプローチより効果的
- 関数型プログラミングを使用してコードを単純化します。
デメリット
- 関数型プログラミングに慣れていない一部の人々は、読みにくいと感じるかもしれません。
- ネストされたループ手法よりも理解しにくいです。
リストの理解方法
リスト内包表記を使用すると、XNUMX 行のコードで新しいリストを生成できます。 したがって、これは既存のリストの各メンバーに式を適用することによるものです。
このアプローチでは、乗算は、各行列メンバーを繰り返し反復することによって実行されます。 階層化されたリスト内包表記を使用しています。
# Sample matrices
A = [[1, 12, 3], [14, 5, 6]]
B = [[7, 8], [9, 10], [12, 12]]
# Matrix multiplication using list comprehension
result = [[sum(A[i][k] * B[k][j] for k in range(len(A[0])))
for j in range(len(B[0]))] for i in range(len(A))]
# Print the result
print(result)
[[151, 164], [215, 234]]
福利厚生
- map() 関数メソッドと比較して、短くて読みやすい。
デメリット
- 特に大規模な行列の場合、 map() 関数を使用するよりも効果的ではない場合があります。
- ネストされたループのアプローチよりも困難です。
まとめ
この投稿では、Python で行列を乗算するときに NumPy を使用する代わりの方法を調べました。 ネストされたループ、組み込みの map() 関数、およびリスト内包表記で行列の乗算を実行しました。
最良の戦略は、プロジェクトの特定のニーズに依存します。
それぞれの戦略には、それぞれ長所と短所があります。 関数が適切に動作していることを確認するには、さまざまな行列の次元と値を使用していくつかのテスト ケースを追加することをお勧めします。
また、これらのメソッドがどの程度うまく実行されるかを比較するために、いくつかのパフォーマンス テストを含める必要があります。
コメントを残す