バックナンバーはこちら。
https://www.simulationroom999.com/blog/stock-predict-matlabpython-backnumber/
はじめに
前回は、MATLABの列ベクトル、行ベクトルの直積を利用した行列生成について説明。
ベクトル、行列同士の演算は基本は内積ではあるが、
演算順序によっては直積になる。
ここで問題になったのが、Python(Numpy)でも同様のことができるか?
というところ。
よって、今回はその点を確認していく。
登場人物
博識フクロウのフクさん
イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1
エンジニア歴8年の太郎くん
イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1
Python(Numpy)で直積は可能か?
で、前回の話の流れだとPython(Numpy)で直積が可能かを確認すると思ったのだけど、
問題無く出来そう?
結論としては「できる」
にはなるな。
その言い回しだと、やはり罠があったパターンか・・・。
Python(Numpy)の罠
まぁある程度予測はできてはいたが、
やはり、Pythonのベクトルの種類が以下に分かれていることが厄介なところだな。
- ベクトル(数列)
- 列ベクトル
- 行ベクトル
今回の場合だと、列ベクトルか行ベクトルにしないとダメっぽいイメージはあるかな。
その通り。
np.array、np.arange、np.linspaceを使って生成しただけだったらベクトル(数列)になる。
この状態だと転置が効かない。
ちょっとコードを出してみよう。
>>> A=np.arange(1,10)
>>> A
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> A.T
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> A=np.array([1,2,3,4,5,6,7,8,9])
>>> A
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> A.T
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> A=np.linspace(1,9,9)
>>> A
array([1., 2., 3., 4., 5., 6., 7., 8., 9.])
>>> A.T
array([1., 2., 3., 4., 5., 6., 7., 8., 9.])
あー、確かに転置が効いてないね。
Python(Numpy)で列ベクトル、行ベクトル生成
よって、以下の方法で列ベクトル、行ベクトルにする必要がある。
最初からmatrixとして生成する方法と、
ベクトル(数列)として生成したあとにreshapeでmatrixにする方法になる。
>>> A=np.mat([np.arange(1,10)])
>>> A
matrix([[1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> A.T
matrix([[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
>>> A=np.arange(1,10)
>>> A
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> A=np.reshape(A,(1,9))
>>> A
array([[1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> A.T
array([[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
お!
今度はちゃんと転置されてる!
matrixは気難しい?
ということは、最初からnp.matで生成しておけば良いんじゃない?
matrixで生成したものは結構気難しいんだよね。
というと?
こういうことになる。
>>> A=np.mat([np.arange(1,10)])
>>> A
matrix([[1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> A.T
matrix([[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
>>> A[0]
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> A[0,0]
1
>>> A[0,1]
2
>>> A[0,8]
9
これは・・・。
行ベクトルなのに、添え字を複数設定する必要が出てくるのか・・・。
まぁ真面目に添え字を設定していけば良いだけなんだけど、
これに合わせると結構MATLABコードと乖離していっちゃうんだよね。
というわけで、直積が必要な時だけnp.reshapeをする方法が妥当な気はしている。
なるほど。
それはなんかわかる。
一応、直積ができることも証明しておこう。
>>> A=np.arange(1,10)
>>> A
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> A=np.reshape(A,(1,9))
>>> B=A.copy().T
>>> B
array([[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
>>> A@B
array([[285]])
>>> B@A
array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9],
[ 2, 4, 6, 8, 10, 12, 14, 16, 18],
[ 3, 6, 9, 12, 15, 18, 21, 24, 27],
[ 4, 8, 12, 16, 20, 24, 28, 32, 36],
[ 5, 10, 15, 20, 25, 30, 35, 40, 45],
[ 6, 12, 18, 24, 30, 36, 42, 48, 54],
[ 7, 14, 21, 28, 35, 42, 49, 56, 63],
[ 8, 16, 24, 32, 40, 48, 56, 64, 72],
[ 9, 18, 27, 36, 45, 54, 63, 72, 81]])
>>> A*B
array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9],
[ 2, 4, 6, 8, 10, 12, 14, 16, 18],
[ 3, 6, 9, 12, 15, 18, 21, 24, 27],
[ 4, 8, 12, 16, 20, 24, 28, 32, 36],
[ 5, 10, 15, 20, 25, 30, 35, 40, 45],
[ 6, 12, 18, 24, 30, 36, 42, 48, 54],
[ 7, 14, 21, 28, 35, 42, 49, 56, 63],
[ 8, 16, 24, 32, 40, 48, 56, 64, 72],
[ 9, 18, 27, 36, 45, 54, 63, 72, 81]])
>>> B*A
array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9],
[ 2, 4, 6, 8, 10, 12, 14, 16, 18],
[ 3, 6, 9, 12, 15, 18, 21, 24, 27],
[ 4, 8, 12, 16, 20, 24, 28, 32, 36],
[ 5, 10, 15, 20, 25, 30, 35, 40, 45],
[ 6, 12, 18, 24, 30, 36, 42, 48, 54],
[ 7, 14, 21, 28, 35, 42, 49, 56, 63],
[ 8, 16, 24, 32, 40, 48, 56, 64, 72],
[ 9, 18, 27, 36, 45, 54, 63, 72, 81]])
>>>
あ、ちゃんと内積と直積が出来てる。
あれ?
A*B、B*AってNumpyの場合、アダマール積になるような気が・・・。
結果は直積になってるようだけど・・・。
同じ行列要素数同士の場合はアダマール積になるようだが、
異なる場合、今回だとそもそも行と列が異なっている場合は、直積になるようだな。
うーん、結構MATLABの性質と違いが出るなー。
確かにこれは気難しいと言われるのもわかるなー。
どっちにしても直積ができるのはわかったので、
次回までにfor文無しフーリエ変換、逆フーリエ変換のPython(Numpy)版を作ってくる。
よろしくー。
まとめ
まとめだよ。
- Python(Numpy)で直積は可能か確認。
- 結果としては可能。
- 明示的に行ベクトル、列ベクトルにしないと直積は不可。
- ベクトル(数列)から行ベクトル、列ベクトルにするにはnp.mat、np.reshapeを使用する。
- 行と列が異なる場合の積は直積になるっぽい。(よくわからん)
バックナンバーはこちら。
コメント