NumPyのブロードキャストは、異なる形状(shape)の配列同士の演算を可能にする便利な機能です。
この記事ではブロードキャストがどのように適用されるか、そのルールを具体例とともにご紹介します。
ぜひ参考にしてみてください!
ブロードキャストのルール
次元数(ndim)を揃える
2つの配列の次元数が異なる場合、次元数の少ない方の前に「1」の次元を追加して形を揃えます。
各次元のサイズを比較する
2つの配列の対応する次元について、以下のいずれかを満たせば、その次元は互換性があります:
- 両方の配列で次元のサイズが同じ
- どちらかの次元のサイズが
1
(この場合、サイズが1
の配列はその次元で拡張される)
ブロードキャストが可能ならば、拡張された形状で演算が行われる
互換性のある次元は、自動的に繰り返されて(仮想的に拡張されて)演算が実行されます。
具体例
同じ形状の場合
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3)
B = np.array([[10, 20, 30], [40, 50, 60]]) # (2, 3)
print(A + B)
# 実行結果
#[[11 22 33]
# [44 55 66]]
A
と B
は同じ形 (2,3)
なので、通常の要素ごとの演算が行われます。
片方の配列に次元 1
がある場合
A = np.array([[1, 2, 3]]) # (1, 3)
B = np.array([[10], [20], [30]]) # (3, 1)
print(A + B)
# 実行結果
# A: [[1, 2, 3]]
# B: [[10],
# [20],
# [30]]
# 結果: [[11, 12, 13],
# [21, 22, 23],
# [31, 32, 33]]
A.shape = (1, 3)
, B.shape = (3, 1)
のため、以下のようにブロードキャストされます:
A: [[1, 2, 3]]
B: [[10],
[20],
[30]]
結果: [[11, 12, 13],
[21, 22, 23],
[31, 32, 33]]
配列B
が配列A
と同じshapeに伸長されて処理が行われます。
1次元配列と2次元配列の演算
A = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3)
B = np.array([10, 20, 30]) # (3,)
print(A + B)
# 実行結果
#[[11, 22, 33],
# [14, 25, 36]]
B.shape
は (3,)
なので、(1,3)
に拡張されて (2,3)
と互換性が取れます。
ブロードキャストが適用されないケース
ブロードキャストが適用されるためには、すべての次元が
- 同じサイズ または
- どちらかが
1
のいずれかでなければなりません。
例えば、次のケースではエラーになります:
A = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3)
B = np.array([10, 20]) # (2,)
print(A + B) # ブロードキャストできないためエラー
(2,3)
と (2,)
は互換性がなく、ブロードキャストできません。
ブロードキャストのメリット
コードの簡潔化
ブロードキャストを活用すると、明示的なループを書かずに簡潔なコードで記述できます。
例えば、次のような処理をforループなしで実現できます。
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3)
B = np.array([10, 20, 30]) # (3,)
# ブロードキャストを利用した計算
C = A + B
print(C)
通常のループを使うとこうなります:
C = []
for row in A:
C.append([row[i] + B[i] for i in range(len(B))])
print(C)
ブロードキャストを使うことで、ループなしでシンプルな書き方が可能になります。
メモリ効率の向上
ブロードキャストは、メモリを無駄に消費せずに計算を行うことができます。
例えば、(1, 3)
の形状の配列 B
を (2, 3)
にコピーすることなく、仮想的に拡張して計算を行います。
これにより、不要なメモリの消費を抑えることができます。
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3)
B = np.array([10, 20, 30]) # (3,)
# メモリ効率を考えた演算
C = A + B
print(C)
追加のメモリを確保せずに計算ができるため、大規模データ処理にも有効です。
まとめ
ブロードキャストの基本ルール
- 形状をそろえるために、必要ならば次元数を増やす(
1
を前に追加) - 各次元ごとに、サイズが一致するか、一方が
1
なら拡張可能 - ブロードキャストが成立すれば、要素ごとの演算が可能になる
以上がNumPyの配列のブロードキャストのルールです。ブロードキャストをうまく活用すると、for ループを使わずに効率的に計算を行えます!
大規模な数値計算をする方などは、ぜひ身に着けておきたいですね!
Python初心者におすすめの学習サービス
オンラインPython学習サービス「PyQ™(パイキュー)」:プログラミング初心者に優しいオンラインPython学習サービス。プログラミングを始めたけど、何かを作れるレベルには至っていない人におすすめ。実用的なPythonコードを実装することができる。