こんにちは、インストラクターのフクロウです!
この記事では行列を扱うクラス、np.matrixについて紹介します!
NumPyではnp.ndarrayクラスで配列を管理していました。
これに対して、np.ndarrayの二次元配列に当たる構造には特別にnp.matrixクラスが用意されています。
np.matrixはほとんどnp.ndarrayの二次元配列限定版といっても良いのですが、実は少し違う機能を持っています。
この記事でnp.matrixについて詳しく解説するので、是非読んでくださいね!
np.matrixとは
このクラスのコンストラクタ(初期化する関数)は、np.matrix/np.matという2つの関数があります。
どちらを使っても同じものができます。
import numpy as np X = np.matrix( [ [1,2,3], [4,5,6] ] ) X2 = np.mat( [ [1,2,3], [4,5,6] ] ) X3 = np.array( [ [1,2,3], [4,5,6] ] ) print(type(X)) print(type(X2)) print(type(X3))
[出力結果]
<class 'numpy.matrixlib.defmatrix.matrix'> <class 'numpy.matrixlib.defmatrix.matrix'> <class 'numpy.ndarray'>
このクラスは行列を表現するものなので、二次元以外の配列から作ろうとするとValueErrorになります。注意しましょう。
X = np.matrix( [[[1,2,3],[4,5,6]]] )
[エラーメッセージ]
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-19-bf08575410de> in <module>() 1 X = np.matrix( ----> 2 [[[1,2,3],[4,5,6]]] 3 ) ~/anaconda3/lib/python3.7/site-packages/numpy/matrixlib/defmatrix.py in __new__(subtype, data, dtype, copy) 144 shape = arr.shape 145 if (ndim > 2): --> 146 raise ValueError("matrix must be 2-dimensional") 147 elif ndim == 0: 148 shape = (1, 1) ValueError: matrix must be 2-dimensional
np.matrixとnp.arrayの動作の違い
np.matrixとnp.ndarrayはほとんど同じ動作をする、これは先程書きましたね。
実はこれらが違う動きをする場合がいくつかあります。
それらの中でも特に主要なものを紹介します。
内積
配列同士の内積を取る計算に、np.dotがありました。
この関数はもちろん、np.ndarrayでもnp.matrixでも使えます。
ですが、np.ndarrayでは*演算子では内積計算はできないのに対して、np.matrixでは*演算子で内積が計算できます。
np.matrixの内積計算
X*X.transpose() # 計算結果 matrix([[14, 32], [32, 77]])
np.dot(X,X.transpose()) # 計算結果 matrix([[14, 32], [32, 77]])
np.arrayの内積計算
np.dot(X3,X3.transpose()) # 計算結果 array([[14, 32], [32, 77]])
X3*X3.transpose()
[エラーメッセージ]
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-32-0720f2ef1dc3> in <module>() ----> 1 X3*X3.transpose() ValueError: operands could not be broadcast together with shapes (2,3) (3,2)
アダマール積(要素ごとの積)
配列の要素ごとの積を計算するには、np.arrayでは*演算子で可能ですが、np.matrixではできません。
np.matrixではnp.multiply関数を使います。(np.araryでもnp.multiplyは使えますよ)
np.matrixのアダマール積
np.matrix同士を*演算子で計算しようとするとエラーがでます。
X*X
[エラーメッセージ]
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-34-0794a8b26aec> in <module>() ----> 1 X*X ~/anaconda3/lib/python3.7/site-packages/numpy/matrixlib/defmatrix.py in __mul__(self, other) 213 if isinstance(other, (N.ndarray, list, tuple)) : 214 # This promotes 1-D vectors to row vectors --> 215 return N.dot(self, asmatrix(other)) 216 if isscalar(other) or not hasattr(other, '__rmul__') : 217 return N.dot(self, other) ValueError: shapes (2,3) and (2,3) not aligned: 3 (dim 1) != 2 (dim 0)
アダマール積を計算するならnp.ndarray.multiply関数を使えばOKです。
np.multiply(X,X) # 計算結果 matrix([[ 1, 4, 9], [16, 25, 36]])
np.arrayのアダマール積
np.ndarray同士ならば*演算子でもアダマール積が計算できます。
X3*X3 # 計算結果 array([[ 1, 4, 9], [16, 25, 36]])
また、np.ndarray.multiply関数ならば、np.ndarrayでもnp.matrixでも同様にアダマール積が計算できます。
np.multiply(X3,X3) # 計算結果 array([[ 1, 4, 9], [16, 25, 36]])
まとめ
この記事では、NumPyで行列を扱うクラスnp.matrixの紹介と、np.ndarrayとの動作の違いについて解説しました。
np.matrixを使えば明示的に行列を扱うことができます。
行列計算はどんな機械学習モデルの実装でもよく使われるものです。
np.matrixの使い方を覚えて、是非とも効率的にプログラミングを行いましょう!