質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

5496閲覧

行列の掛け算をライブラリを使わず自力で実装する

eggpol

総合スコア60

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

1クリップ

投稿2019/06/20 10:17

編集2019/06/20 12:11

事情があってライブラリを使わず最初からPythonに入っているもので行列の掛け算を実装しなければいけません。

一応できたのはできたのですが、コードの正当性の証明などどうやればいいかわからないです。
行列の掛け算をやってくれるサイトがあるのでそれの答えと照らし合わせていますが正しいか不安です。
そもそもあっているのかわからないです。
よろしくお願いします。
参考
計算の仕方

#行列UとVを掛け算する def matrix_multiplication(U,V): answer=[] u_colmun_length=len(U[0]) v_row_lengthh=len(V) v_column_length=len(V[0]) #Uの列数とVの行数が同じじゃないなら計算できない if u_colmun_length != v_row_lengthh: print("Could not compute") return else: #Uの行列から1行を取り出す for u in U: temp=[] colmun_index=0 #Vの行列から一列を取り出す for _ in range(v_column_length): a = [x[colmun_index] for x in V] el_index=0 temp_multiple=0 #Uの行とVの列を掛け算し足し合わせる for _ in range(u_colmun_length): temp_multiple+=u[el_index]*a[el_index] el_index+=1 #行列の行を作成 temp.append(temp_multiple) colmun_index+=1 #行を追加 answer.append(temp) print(answer) matrix_multiplication([[2,3],[3,5]],[[2,1]]) matrix_multiplication([[2,3]],[[2],[3]]) matrix_multiplication([[2,3],[2,10]],[[3,5],[3,3]]) matrix_multiplication([[2,3,3],[2,10,3]],[[3,5,2],[3,3,1],[2,4,5]]) """ Result Could not compute [[13]] [[15, 19], [36, 40]] [[21, 31, 22], [42, 52, 29]] """
DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

コードの正当性の証明などどうやればいいかわからないです

普通は、テストケースを作り、テストに全て(すべてでない場合もある)合格すれば良しとします。
このような計算の場合、事前に答えがわかっている値を何組か用意して、確認します。

というので回答になりますか?他の何かを求めていますか?

投稿2019/06/20 13:45

Q71

総合スコア995

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

10000 回ランダムに生成した行列で試しましたが、すべて numpy の答えと一致しましたので、実装は合っていると思います。

python

1# 行列UとVを掛け算する 2def matrix_multiplication(U, V): 3 answer = [] 4 u_colmun_length = len(U[0]) 5 v_row_lengthh = len(V) 6 v_column_length = len(V[0]) 7 # Uの列数とVの行数が同じじゃないなら計算できない 8 if u_colmun_length != v_row_lengthh: 9 print("Could not compute") 10 return None 11 else: 12 # Uの行列から1行を取り出す 13 for u in U: 14 temp = [] 15 colmun_index = 0 16 # Vの行列から一列を取り出す 17 for _ in range(v_column_length): 18 a = [x[colmun_index] for x in V] 19 el_index = 0 20 temp_multiple = 0 21 # Uの行とVの列を掛け算し足し合わせる 22 for _ in range(u_colmun_length): 23 temp_multiple += u[el_index] * a[el_index] 24 el_index += 1 25 # 行列の行を作成 26 temp.append(temp_multiple) 27 colmun_index += 1 28 # 行を追加 29 answer.append(temp) 30 return answer 31######################################################## 32# ここまで質問者さんのコード 33######################################################## 34 35from pprint import pprint 36import numpy as np 37 38# 計算できるパターンで答えがあっているかどうか 39np.random.seed(42) 40num_tests = 10000 41num_ok = 0 42 43for i in range(num_tests): 44 # 行列 A, B の列数、行数をランダムに生成する。 45 N, M, L = np.random.randint(1, 10, 3) 46 # 行列 A, B の値をランダムに生成する。 47 A = np.random.randint(1, 10, size=(N, M)) 48 B = np.random.randint(1, 10, size=(M, L)) 49 50 # numpy の計算結果 51 ret1 = A @ B 52 53 # 自作した関数の計算結果 54 ret2 = matrix_multiplication(A, B) 55 56 if not np.array_equal(ret1, ret2): 57 print("=== incorrect case found ===") 58 print(f"A {A.shape}\n{A}") 59 print(f"B {B.shape}\n{B}") 60 print(f"numpy {ret1.shape}:\n{ret1}") 61 print(f"matrix_multiplication:\n{ret2}") 62 else: 63 num_ok += 1 64 65print(f"{num_ok} / {num_tests}") # 10000 / 10000

補足

A: (N, M) の行列, B: (M, L) の行列としたとき、
行列積 C は (N, L) の行列でその (i, j) 成分は

C_{ij} = \sum_k^M A_{ik} B_{kj}

なので、定義に従い書くと以下のようになる。

python

1def matrix_multiplication(A, B): 2 A_rows, A_cols = len(A), len(A[0]) # A の行数及び列数 3 B_rows, B_cols = len(B), len(B[0]) # B の行数及び列数 4 5 if A_cols != B_rows: 6 print("Could not compute") 7 return None 8 9 # (A_rows, B_cols) の0で初期化した行列を作成する。 10 ret = [[0 for j in range(B_cols)] for i in range(A_rows)] 11 12 for i in range(A_rows): 13 for j in range(B_cols): 14 for k in range(A_cols): 15 ret[i][j] += A[i][k] * B[k][j] 16 17 return ret

追記

↓これは[[0]]と出るのですが二次元配列ですか。
ret = [[0 for j in range(B_cols)] for i in range(A_rows)]
ここにインデックスをあらかじめ指定して代入するということですかね?
[[0]]と表示されているのにIndex out of rangeみたいなエラーが出ないので不思議でした

例えば、(2, 2) と (2, 3) の行列積であれば、結果は (2, 3) の行列となるので、(2, 3) の値がすべて0の行列を Python の内包記法で作成しています。

pythonの内包表記を少し詳しく - Qiita

python

1ret = [[0 for j in range(3)] for i in range(2)] 2print(ret) 3# [[0, 0, 0], 4# [0, 0, 0]]

具体的な例で各出力がどうなるかをコメントに記載したコード

python

1A = [[1, 2], 2 [3, 4]] 3B = [[5, 6, 7], 4 [8, 9, 10]] 5 6A_rows, A_cols = len(A), len(A[0]) # A の行数及び列数 7print(f"({A_rows}, {A_cols})") # (2, 2) 8B_rows, B_cols = len(B), len(B[0]) # B の行数及び列数 9print(f"({B_rows}, {B_cols})") # (3, 2) 10 11if A_cols != B_rows: 12 print("Could not compute") 13 exit(1) 14 15# 0で初期化した 2x3 行列を作成する。 16ret = [[0 for j in range(B_cols)] for i in range(A_rows)] 17print(ret) 18# [[0, 0, 0], 19# [0, 0, 0]] 20 21for i in range(A_rows): 22 for j in range(B_cols): 23 for k in range(A_cols): 24 ret[i][j] += A[i][k] * B[k][j]

あと↓ですがかけたものを足しているということでいいですか?勉強不足のせいか読み方が分かりません・・・。
C_{ij} = \sum_k^M A_{ik} B_{kj}

行列積の定義です。Tex 記法が teratail だとコンパイルされないので、tex のままになっていますが、以下の行列積の定義を書きました。

イメージ説明

投稿2019/06/21 03:52

編集2019/06/24 07:03
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

eggpol

2019/06/21 14:04

回答ありがとうございます。 やはり確認するにはテストケースを作って確かめるのですね。 コードを拝見いたしましたがこんなにスマートに行列の掛け算ができるのですね。 ↓これは[[0]]と出るのですが二次元配列ですか。 ret = [[0 for j in range(B_cols)] for i in range(A_rows)] ここにインデックスをあらかじめ指定して代入するということですかね? [[0]]と表示されているのにIndex out of rangeみたいなエラーが出ないので不思議でした あと↓ですがかけたものを足しているということでいいですか?勉強不足のせいか読み方が分かりません・・・。 C_{ij} = \sum_k^M A_{ik} B_{kj}
tiitoi

2019/06/24 07:05

回答に追記しました。 まだ不明点がございましたら、コメントしてください。
guest

0

正しいかどうかを確認するときにライブラリを使ったらいいではないですか?

投稿2019/06/20 14:05

mkgrei

総合スコア8560

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問