NumPyにも単位行列を生成する関数が備わっています。

NumPyでは主に2つの関数であるnp.eye()np.identity()が使われており、使われる頻度としては2つの関数間にそこまで差はありません。

identity関数は行数、列数が同じ正方行列しか生成できないのに対し、eye関数は行数と列数各々を指定して単位行列を生成できるところに違いがあります。 他にもeye関数では要素が1となっている対角線の位置を指定することもできます。

特別な指定の必要のない単位行列を生成する場合はnp.identity関数で十分ですが特殊なものを用いたい場合はnp.eye関数を使う必要があるでしょう。

それでは各々の関数について見ていきます。

np.eye()

ここではeye関数について解説していきます。 まずはAPIドキュメントを見てみましょう。

numpy.eye(N, M=None, k=0, dtype=float)

params:

パラメータ名 概要
N int 生成される単位行列の行数を指定します。
M int (省略可能)初期値None
生成される単位行列の列数を指定します。NoneのときはNと同じ値になります。
k int (省略可能)初期値0
1を要素とする対角線が行列のどの位置にするかを指定します。kの値が正であれば上方の位置となり、負の値であれば下方の位置となります。
dtype データ型 (省略可能)初期値float
生成される配列の要素が持つデータ型を指定します。

returns:

N×Mの2次元行列で指定した対角線上の要素が全て1となっており、その他は全て0となっている行列を返します。

引数を見ると、NMで行列のサイズを指定することができ、kで要素が1となっている対角線の位置を指定することができます。また、dtypeで要素のデータ型を指定できます。

サンプルコード

実際に使っていきましょう。簡単な単位行列から作っていきます。

In [1]: import numpy as np

In [2]: np.eye(3) # 3×3の単位行列
Out[2]:
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])

In [3]: np.eye(10)
Out[3]:
array([[ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.]])

行数、列数をNMを使って指定します。

In [4]: np.eye(2, 3) # 2×3
Out[4]:
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.]])

In [5]: np.eye(5, 4) # 5×4
Out[5]:
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.],
       [ 0.,  0.,  0.,  0.]])

次に、要素1が並ぶ対角線の位置を指定します。

In [6]: np.eye(5, k=0) # k=0とするとそのまま。
Out[6]:
array([[ 1.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  1.]])

In [7]: np.eye(5, k=1) # 上方に1つ移動
Out[7]:
array([[ 0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  1.],
       [ 0.,  0.,  0.,  0.,  0.]])

In [8]: np.eye(5, k=-1) # 下方に1つ移動
Out[8]:
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.]])

In [9]: np.eye(5, k=3) # 3つ移動
Out[9]:
array([[ 0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  1.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

最後に、データ型を指定します。

In [10]: np.eye(5, dtype=int)
Out[10]:
array([[1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 0, 1, 0],
       [0, 0, 0, 0, 1]])

In [11]: np.eye(5, dtype=complex) # 複素数型で
Out[11]:
array([[ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j],
       [ 0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j],
       [ 0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j],
       [ 0.+0.j,  0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j],
       [ 0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  1.+0.j]])

np.identity()

ここではidentity関数について解説します。
APIドキュメントは以下の通りです。

numpy.identity(n, dtype=float)

params:

パラメータ名 概要
n int 生成する行列のサイズを指定します。N×Nの正方行列が生成されます。
dtype データ型 (省略可能)初期値float
要素のデータ型を指定します。

returns:

N×Nの単位行列を生成します。

こちらの引数はeye関数に比べるとシンプルになっています。nで配列のサイズを指定し、dtypeで要素のデータ型を指定します。

サンプルコード

実際に使っていきます。

In [12]: np.identity(5) # まずは単純なものから
Out[12]:
array([[ 1.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  1.]])

In [13]: np.identity(2)
Out[13]:
array([[ 1.,  0.],
       [ 0.,  1.]])

dtypeでデータ型を指定します。

In [14]: np.identity(3, dtype=int)
Out[14]:
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]])

In [15]: np.identity(4, dtype="float32")
Out[15]:
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]], dtype=float32)

速さの比較

10000×10000の単位行列を生成する速度を比較してみます。

In [17]: %timeit np.eye(10000)
27.3 ms ± 603 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [18]: %timeit np.identity(10000)
27.1 ms ± 822 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

2つの関数共にほぼ同じ処理速度で実行していますね。

速さの観点からは、どちらを使っても差異はなさそうです。