この記事のまとめ
- MATLAB/OctaveとPythonのNumPyのコード比較
- NumPyのarray型とmatrix型のサンプルコード
背景
最近の私がよく使うプログラミング言語はPythonとMATLABなのですが、基本的にPythonで算術計算をあまりすることはなく、行列計算などを必要とするプログラムについては、MATLABでしかやったことがありませんでした。
機械学習を学んでいると、Pythonで行列計算などの算術計算をする必要がありそうなので、MATLABと対比しながら、Pythonでどのように行列計算を行っていくかをまとめたいと思います。
今回はその2回目です。
前回は全般的な違いを説明致しました。今回はソースコードを実際に叩きながら違いを見ていきます。
MATLABユーザーがよく使う行列表記とNumPy表記の比較
前回、array
型とmatrix
型の話をしましたが、array
型を使うべし、と記載しましたので下記の比較はarray
型のみを対象にしております。
もし、matrix
型を使いたいという方は、NumPyの中にmatlib
モジュールがあり、これにはMATLABユーザーにとってより使い慣れた関数表現が可能です。ただし、matlib
モジュールの関数はmatrix
型の返り値を取りますので、array
型を使う方には適していませんのでご注意ください。
MATLAB |
NumPy |
備考 |
[1 2 3; 4j 5j 6j] |
numpy.array([[1.,2.,3.],[4.j,5.j,6.j]]) |
2x3の複素行列表記 |
[a b; c d] |
vstack([hstack([a,b]), hstack([c,d])]) |
配列の結合 |
A(end) |
A[-1] |
最後の要素(ただしPythonの場合は1次元目の最後の要素) |
A(1,3) |
A[0,2] |
1行目3列目の要素 |
A(1,:) |
A[0,:] |
1行目のすべての要素 |
A(1:2,2:3) |
A[0:2][1:3] |
1-2行目の2-3列目の要素 |
A.' |
A.T |
転置 |
A' |
A.conj().T |
エルミート転置(複素共役転置、随伴行列) |
A*B |
A.dot(B) |
行列積 |
A.*B |
A*B |
要素ごとの積 |
A.^3 |
A**3 |
要素ごとのべき乗 |
numel(A) |
numpy.size(A) or A.size |
配列の要素数 |
size(A) |
numpy.shape(A) or A.shape |
配列のサイズ |
size(A,n) |
A.shape[n-1] |
配列のn次元目のサイズ |
find(A>0.5) |
nonzero(A>0.5) |
0.5以上の要素のインデックス |
C=A |
C=A.copy() |
値渡しによる代入(C=Aとすると参照渡しになります。部分参照の場合でも同様) |
D=A(:) |
D=A.flatten() |
行列のベクトル化 |
1:10 |
arange(1.,11.) or
r_[1.:11.] |
1から10までの連続数の配列(MATLABは行ベクトル、列ベクトルが配列として扱われる) |
1:10 |
arange(1.,11.).reshape(1,10) |
1から10までの連続数の行ベクトル |
[1:10]' |
arange(1.:11.).reshape(10,1) or c_[1.:11.] |
1から10までの連続数の列ベクトル |
zeros(3,4) |
zeros((3,4)) |
64-bit浮動小数点の0で満たされた3x4の行列 |
ones(3,4) |
ones((3,4)) |
64-bit浮動小数点の1で満たされた3x4の行列 |
eye(3) |
eye(3) |
3x3の単位行列 |
diag(a) |
diag(a) |
配列aの要素を対角要素に持つ対角行列 |
rand(3,4) |
random.rand(3,4) |
ランダムな要素の3x4の行列 |
repmat(A,2,3) |
tile(A,(2,3)) |
行列Aを行方向に2個、列方向に3個コピーした行列 |
max(max(A)) |
A.max() |
行列Aのすべての要素の最大値 |
max(A) |
A.max(0) |
1次元目の配列の要素の最大値 |
inv(A) |
linalg.inv(A) |
逆行列 |
pinv(A) |
linalg.pinv(A) |
疑似逆行列 |
A\B |
linalg.solve(A,B) if A is squared linalg.lstsq(A,B) otherwise |
を解く |
とりあえず最低限必要なものはこの程度でしょうか。
必要に応じて適宜追加していきたいと思います。
もし、実際のコードを打ちながら試したいという方は本記事の最後にarray
型とmatrix
型でのコードを示しておきますのでお試しください。
今回は以上です。
最後まで読んでいただき、ありがとうございます。
サンプルコード
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Make all numpy available via shorter 'np' prefix
import numpy as np
# Make all matlib functions accessible at the top level via npm.func()
import numpy.matlib as npm
# 3x3 の複素行列表記
## array型
A = np.array([[1., 2., 3.], [4.j, 5.j, 6.j], [7., 8., 9.]])
print('A: \n{0}'.format(A))
## matrix型
M = np.matrix('[1. 2. 3.; 4.j 5.j 6.j; 7. 8. 9.]')
print('M: \n{0}'.format(M))
# 配列の結合
## array型
a = np.array([1, 1])
b = np.array([2, 2])
c = np.array([3, 3])
d = np.array([4, 4])
e = np.array([5, 5])
f = np.array([6, 6])
B = np.vstack( [np.hstack([a, b]), np.hstack([c, d]), np.hstack([e, f])] )
print('vstack([hstack([a,b]),hstack([c,d]),hstack([e,f])]): \n{0}'.format(B))
## matrix型
m = np.matrix('[1 1]')
n = np.matrix('[2 2]')
o = np.matrix('[3 3]')
p = np.matrix('[4 4]')
q = np.matrix('[5 5]')
r = np.matrix('[6 6]')
N = np.bmat('m n; o p; q r')
print("bmat('m n; o p; q r'): \n{0}".format(N))
# 最後の要素
## array型、matrix型共通
print('A[-1]: \n{0}'.format(A[-1]))
# 3行目1列目の要素
## array型、matrix型共通
print('A[2,0]: \n{0}'.format(A[2,0]))
# 1行目のすべての要素
## array型、matrix型共通
print('A[0,:]: \n{0}'.format(A[0,:]))
# 2-3行目の1-2列目の要素
## array型、matrix型共通
print('A[1:3,0:2]: \n{0}'.format(A[1:3,0:2]))
# 転置
## array型、matrix型共通
print('A.T: \n{0}'.format(A.T))
# エルミート転置(複素共役転置、随伴行列)
## array型
print('A.conj().T: \n{0}'.format(A.conj().T))
## matrix型
print('M.H: \n{0}'.format(M.H))
# 行列積
## array型
print('A.dot(B): \n{0}'.format(A.dot(B)))
## matrix型
print('M*N: \n{0}'.format(M*N))
# 要素ごとの積
## array型
print('A*A: \n{0}'.format(A*A))
## matrix型
print('multiply(M,M): \n{0}'.format(np.multiply(M,M)))
# 要素ごとのべき乗
## array型
print('A**3 \n{0}'.format(A**3))
## matrix型
print('power(M,M): \n{0}'.format(np.power(M,3)))
# 行列の要素数
## array型、matrix型共通
print('np.size(A): {0}'.format(np.size(A)))
print('A.size: {0}'.format(A.size))
# 行列のサイズ
## array型、matrix型共通
print('np.shape(A): {0}'.format(np.shape(A)))
print('A.shape: {0}'.format(A.shape))
# 1次元目の要素数
## array型、matrix型共通
print('A.shape[0]: {0}'.format(A.shape[0]))
# 0.5以上の要素のインデックス
## array型、matrix型共通
print('nonzero(A>0.5): {0}'.format(np.nonzero(A>0.5)))
# 値渡しによる代入
## array型、matrix型共通
C=A.copy()
C[0,0] = 99.
print('A: \n{0}'.format(A))
print('C: \n{0}'.format(C))
# 行列のベクトル化
D=A.flatten()
print('D: \n{0}'.format(D))
# 1から10までの連続数の配列
## array型のみ(matrix型は1次元配列の定義ができない)
print('arange(1.,11.): \n{0}'.format(np.arange(1.,11.)))
print('r_[1.:11.]: \n{0}'.format(np.r_[1.:11.]))
# 1から10までの連続数の行ベクトル
## array型
print('arange(1.,11.).reshape(1,10): \n{0}'.format(np.arange(1.,11.).reshape(1,10)))
## matrix型
print('matrix(arange(1.,11.)): \n{0}'.format(np.matrix(np.arange(1.,11.))))
# 1から10までの連続数の列ベクトル
## array型
print('arange(1.,11.).reshape(10,10): \n{0}'.format(np.arange(1.,11.).reshape(10,1)))
print('c_[1.:11.]: \n{0}'.format(np.c_[1.:11.]))
## matrix型
print('matrix(arange(1.,11.)).T: \n{0}'.format(np.matrix(np.arange(1.,11.)).T))
# 0で満たされた3x4の行列
## array型
print('numpy.zeros((3,4)): \n{0}'.format(np.zeros((3,4))))
## matrix型
print('numpy.matlib.zeros((3,4)): \n{0}'.format(npm.zeros((3,4))))
# 1で満たされた3x4の行列
## array型
print('numpy.ones((3,4)): \n{0}'.format(np.ones((3,4))))
## matrix型
print('numpy.matlib.ones((3,4)): \n{0}'.format(npm.ones((3,4))))
# 3x3の単位行列
## array型
print('numpy.eye(3): \n{0}'.format(np.eye(3)))
## matrix型
print('numpy.matlib.eye(3): \n{0}'.format(npm.eye(3)))
# 配列aの要素を対角要素に持つ対角行列
## array型
print('numpy.diag(a): \n{0}'.format(np.diag(a)))
## matrix型
print('numpy.matlib.diag(a): \n{0}'.format(npm.diag(a)))
# 乱数を要素に持つ3x4の行列
## array型
print('numpy.random.rand(3,4): \n{0}'.format(np.random.rand(3,4)))
## matrix型
print('numpy.matlib.random.rand(3,4): \n{0}'.format(npm.random.rand(3,4)))
# 行列のすべての要素の最大値
## array型、matrix型共通
print('A.max(): {0}'.format(A.max()))
# 1次元目(行)の要素について2次元目(列)以降ごとの最大値
## array型、matrix型共通
print('A.max(0): {0}'.format(A.max(0)))
# 行列のコピー
## array型
print('tile(A,(2,3)): \n{0}'.format(np.tile(A,(2,3))))
## matrix型
print('repmat(): \n{0}'.format(npm.repmat(M,2,3)))
# 逆行列
## array型、matrix型共通
print('numpy.linalg.inv(A): \n{0}'.format(np.linalg.inv(A)))
# 疑似逆行列
## array型、matrix型共通
print('numpy.linalg.pinv(A): \n{0}'.format(np.linalg.pinv(A)))
# A^-1*Bを解く
## array型、matrix型共通
print('numpy.linalg.solve(A,B): \n{0}'.format(np.linalg.solve(A,B)))
コメント
コメントを投稿