【NumPy】ブロードキャスト(broadcast)の基本
の基本.jpg)
NumPy の特徴的な機能であるブロードキャスト(broadcast)の基本的な考え方を紹介します。
目次
ブロードキャスト(broadcast)の基本
NumPy の特徴的な機能としてブロードキャスト(broadcast)という機能があります。ブロードキャストは、NumPy が高速にベクトル演算するユニバーサル関数(ufunc)の土台となる機能です。
ユニバーサル関数は、例えば、np.add や np.multiply というような関数のことです。NumPy 配列(ndarray)の + や * 演算子は、内部でそれらの ufunc を呼び出す糖衣構文となっています。
この記事では、ブロードキャスト(broadcast)の基本について説明します。
ブロードキャスト(broadcast)の基本的な考え方
ブロードキャストの基本的な考え方について、簡単な例を使って見ていきましょう。
ユニバーサル関数のベクトル計算
ユニバーサル関数(ufunc)のベクトル計算のイメージを説明します。以下は同じサイズの NumPy の配列(ndarray)を足し算するプログラムです。
import numpy as np
x1 = np.arange(1, 6)
print(f'x1 = {x1}')
x2 = np.arange(6, 11)
print(f'x2 = {x2}')
print(f'x1 + x2 = {x1 + x2}')【実行結果】 x1 = [1 2 3 4 5] x2 = [ 6 7 8 9 10] x1 + x2 = [ 7 9 11 13 15]
ユニバーサル関数では、ベクトル演算をするため、各要素ごとに演算が行われます。イメージ図にしてみると以下のようになります。今回は足し算(+)の例ですが、他の演算でも同様です。

ブロードキャスト例(1 次元)
上記で説明した例は、配列の形状が一致している場合でした。配列の形状(shape)が異なる場合について見てみましょう。以下は配列と数値の足しているプログラムです。このような場合に、ブロードキャストの機能が動作します。
import numpy as np
x1 = np.arange(1, 6)
print(f'x1 = {x1}')
print(f'x1 + 5 = {x1 + 5}')【実行結果】 x1 = [1 2 3 4 5] x1 + 5 = [ 6 7 8 9 10]
結果を見ると、x1 の各要素にそれぞれ 5 が足し算されていることが分かります。この時、NumPy は 5 という数字を拡張して、x1 と同じ形状の配列にしてからベクトル計算をします。イメージにすると以下のようになります。
このように NumPy が内部的に形状を拡張して対応することを「ブロードキャスト」と言います。

ブロードキャスト例(2 次元:行方向)
2 次元配列の場合も見てみましょう。以下の例は、np.eye で 5 × 5 の単位行列を作成しています。足し算するのは、1 次元の 1 ~ 5 までの数字が入った配列です。
import numpy as np
x1 = np.eye(5)
print(f'x1 = \n{x1}')
x2 = np.arange(1, 6)
print(f'x2 = {x2}')
print(f'x1 + x2 = \n{x1 + x2}')【実行結果】 x1 = [[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.]] x2 = [1 2 3 4 5] x1 + x2 = [[2. 2. 3. 4. 5.] [1. 3. 3. 4. 5.] [1. 2. 4. 4. 5.] [1. 2. 3. 5. 5.] [1. 2. 3. 4. 6.]]
例では、行方向のサイズが異なっているため、x2 の配列を行方向に拡張し、x1 と同じ形状にして計算がされます。イメージは、以下のようになります。

ブロードキャスト例(2 次元:列方向)
列方向に拡張される例も見てみましょう。
import numpy as np
x1 = np.eye(5)
print(f'x1 = \n{x1}')
x2 = np.arange(1, 6)[:, np.newaxis]
print(f'x2 = {x2}')
print(f'x1 + x2 = \n{x1 + x2}')【実行結果】 x1 = [[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.]] x2 = [[1] [2] [3] [4] [5]] x1 + x2 = [[2. 1. 1. 1. 1.] [2. 3. 2. 2. 2.] [3. 3. 4. 3. 3.] [4. 4. 4. 5. 4.] [5. 5. 5. 5. 6.]]
例では、列方向のサイズが異なっているため、x2 の配列を列方向に拡張して、x1 と同じ形状にして計算がされます。イメージは、以下のようになります。

ブロードキャスト(broadcast)のルール
これまで見てきた例は非常にシンプルな例となっていますが、NumPy の高速な演算を支えるブロードキャストという仕組みの概要です。より詳細にはブロードキャストの具体的なルールがありますが、この記事はブロードキャストのイメージを持ってもらうことに留めようかと思います。
より詳細なブロードキャストのルールに興味がある方は、公式ドキュメントのこちらを参考にしてください。
まとめ
NumPy の特徴的な機能であるブロードキャスト(broadcast)の基本的な考え方を紹介しました。
ブロードキャストは、NumPy の np.add や np.multiply といったユニバーサル関数(ufunc)が、内部的に形状を拡張して演算に対応することを言います。
ブロードキャストはNumPyの高速演算を支える重要な考え方の 1 つです。NumPy のユニバーサル関数(ufunc)ではブロードキャストという機能で内部的に形状を拡張して対応していることを意識してみてください。


のスライス」と「Python組み込みのlistのスライス」の違い-1.jpg)
の形状を変更する方法-_-reshape-_.jpg)
を用いた配列(ndarray)の計算.jpg)

をソートする方法-_-sort-argsort-_-1.jpg)
の基本.jpg)