メインコンテンツへスキップ
  1. 授業・研究ノート/
  2. Python/
  3. NumPy/

配列演算

目次
NumPy - この記事は連載の一部です
パート 4: この記事

要素ごとの演算
#

NumPyの四則演算(\( +, -, *, / \))は基本的には要素ごとの演算を行う.

加算なら

x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
x + y    # jupyterで出力用

出力

array([5, 7, 9])

乗算なら

x * y    # jupyterで出力用

出力

array([4, 10, 18])

ブロードキャスト
#

NumPy では,形状が異なる配列同士でも,条件を満たせば自動的に形状をそろえて演算できる.この仕組みをブロードキャストという.

普通の四則演算や np.sin()np.power() などもブロードキャストが適用される.

NumPy は配列の shape を後ろの軸から比較する.次元数が異なる場合は,次元数が少ない配列の先頭にサイズ 1 の軸を補う.その後,各軸のサイズが等しいか,どちらかが 1 であれば演算可能であり,サイズ 1 の軸は自動的に拡張されて揃えられる.

(例)

  • A.shape: (2, 3)
  • x.shape: (3,)

まず,次元が少ない方の \(x\) の shape は

$$ (3,) → (1, 3) $$

のように先頭にサイズ 1 の軸が補われる.次に

$$ (1, 3) → (2, 3) $$

のように \(A\) の shapeに揃えられて,その後に要素ごとに演算される.

スカラーと配列
#

x = np.array([1, 2, 3])
x + 2    # jupyterで出力用

出力

array([3, 4, 5])
  • スカラーの 2 は配列 \( x \) の形状に合わせてブロードキャストされ,各要素に加算される.
  • 概念的には array([2, 2, 2])が足されているものと思って良い(実際にそのような配列を内部で作っているわけではない)

異なる形状の配列同士
#

x = np.array([[1, 2, 3],
              [4, 5, 6]])
y = np.array([10, 20, 30])
x + y    # jupyterで出力用

出力

array([[11, 22, 33],
       [14, 25, 36]])
  • \(x\) の形状は \((2, 3)\),\(y\) の形状は \((3,)\)
  • \(y\) は \(x\) の形状に合わせてブロードキャストされる
  • 概念的には次のような配列が足されていると考えてよい
array([[10, 20, 30],
       [10, 20, 30]])

ベクトルや行列の積
#

NumPy では @ 演算子または np.matmul() によって線形代数における積を計算できる. np.dot()も積の計算に使用できるが3次元以上の配列では@と挙動が異なるので注意.現在は@の利用が推奨されている.

これらの演算は四則演算等のブロードキャストとは別物なので注意.

ベクトルの内積
#

x = np.array([0, 1, 2])
y = np.array([3, 4, 5])
x @ y    # 0*3 + 1*4 + 2*5

出力

14

行列とベクトルの積
#

$$ A = \begin{pmatrix} 0 & 1 \\ 2 & 3 \\ \end{pmatrix}, \quad \mathbf{x} = \begin{pmatrix} 0 \\ 1 \\ \end{pmatrix} $$$$ A \mathbf{x} = \begin{pmatrix} 0 & 1 \\ 2 & 3 \\ \end{pmatrix} \begin{pmatrix} 0 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 1 \\ 3 \\ \end{pmatrix} $$
x = np.array([0, 1])    # ベクトル
A = np.array([[0, 1], [2, 3]])    # 行列
A @ x

出力

array([1, 3])

ここで x @ A のように順番を変えると上記とは異なる計算になるので注意. @ はブロードキャストとは違なり特別な演算になる. 下記の例ではベクトルは横ベクトルと解釈される.

$$ \begin{pmatrix} 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 & 1 \\ 2 & 3 \\ \end{pmatrix} = \begin{pmatrix} 2 & 3 \\ \end{pmatrix} $$
x @ A

出力

array([2, 3])

ただし,最終的に得られるのは1次元配列なので,横ベクトルではなくなる.1次元配列は縦横の区別はない.

行列同士の積
#

$$ \begin{pmatrix} 0 & 1 \\ 2 & 3 \\ \end{pmatrix} \begin{pmatrix} 3 & 2 \\ 1 & 0 \\ \end{pmatrix} = \begin{pmatrix} 1 & 0 \\ 9 & 4 \\ \end{pmatrix} $$
A = np.array([[0, 1],[2, 3]])
B = np.array([[3, 2], [1, 0]])
A @ B

出力

array([[1, 0],
       [9, 4]])
NumPy - この記事は連載の一部です
パート 4: この記事