放送

放送

1. 学習内容



2. ある開発者の実話

(1) 問題点

ボブは、4×3の行列の各行に1×3の行ベクトルを足し込みたいと考えています。そこで、4行のforループを書きましたが、このコードは見栄えが悪く、処理も遅く、インデックスを間違えやすいものです。

(2) 解決策

アリスは彼にこう説明した。「ループは必要ないわ。NumPyは自動的にブロードキャストを行うの。行ベクトルは加算される前に4×3に『ブロードキャスト』されるのよ。」ボブはマーメイドの図を見て、次元がどのように「仮想的に拡張」されるかを即座に理解した。

(3) 成果

ループを削除すると、コードは6行から1行に短縮され、実行速度は50倍以上向上します。ブロードキャストは、NumPyのベクトル化演算の基盤となっています。



3. 放送規則の詳細

(1) 3つのルール

ブロードキャスト機能により、異なる形状の配列でも、次元が自動的に「整列」されるため、算術演算で連携して処理することができ、手動でのデータコピーは不要です。

ルール 説明
ルール 1: 揃え 最も右側の次元から始め、左揃えにし、左側の不足している次元には 1 を埋める (3,) + (2,3)(1,3) + (2,3) に埋める
ルール 2:サイズ 1 の場合は拡張 次元のサイズが 1 の場合、その次元に沿ってコピーし、もう一方の配列と一致させる (1,3) + (2,3)(2,3) + (2,3)
ルール 3: 他の値は一致しなければならない サイズ 1 以外の次元は完全に一致しなければならず、一致しない場合はエラーが発生する (2,3) + (4,3) → ❌ 2≠4

クイックリファレンス

シナリオ 形状 A 形状 B 結果の形状 互換性あり?
スカラー + 配列 () (3,4) (3,4)
1D + 2D (3,) (4,3) (4,3)
列 + 行 (4,1) (1,3) (4,3)
2D 2つ (3,1) (1,5) (3,5)
不一致 (2,3) (4,3)
展開するサイズ-1なし (3,) (4,)

(2) 放送の手順の可視化

(4,3) 行列と (3,) 行ベクトルの加算:

100%
graph TB
    A["Matrix A<br/>shape=(4,3)"] --> D{"Rule 1:<br/>Align dimensions"}
    B["Vector B<br/>shape=(3,)"] --> D
    D --> E["Pad left dim<br/>B: (3,) → (1,3)"]
    E --> F{"Rule 2:<br/>Expand dim=1"}
    F --> G["Expand B along axis 0<br/>(1,3) → (4,3)"]
    G --> H["A + B_expanded<br/>shape=(4,3)"]

    style A fill:#4CAF50,color:#fff
    style B fill:#2196F3,color:#fff
    style D fill:#FF9800,color:#fff
    style F fill:#FF9800,color:#fff
    style G fill:#9C27B0,color:#fff
    style H fill:#E91E63,color:#fff

(3) 放送の実践

PYTHON
import numpy as np

# Scalar + array
a = np.array([1, 2, 3])
print(a + 10)  # [11 12 13]

# 1D + 2D
matrix = np.arange(12).reshape(4, 3)
row = np.array([10, 20, 30])
print(matrix + row)
# [[10 22 34]
#  [13 25 37]
#  [16 28 40]
#  [19 31 43]]

# Column + row (outer operation)
col = np.array([[1], [2], [3], [4]])  # shape (4, 1)
print(col + row)
# [[11 21 31]
#  [12 22 32]
#  [13 23 33]
#  [14 24 34]]
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。



4. よくある落とし穴

(1) 形状の不一致

PYTHON
a = np.ones((3, 2))
b = np.ones((2, 3))
# a + b  # ValueError: shapes (3,2) and (2,3) not aligned

(2) 予期せぬ放送

PYTHON
a = np.ones((3, 1))
b = np.ones((3,))
# a + b broadcasts to (3, 3) — may not be what you expect!

(3) 期待される結果

PYTHON
# To avoid broadcasting, use explicit shapes
a = np.ones((3, 1))
b = np.ones((3, 1))  # or b[:, np.newaxis]
print((a + b).shape)  # (3, 1) — no broadcasting
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

(1) ▶ サンプル

TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

: スカラーから2Dへのブロードキャスト (難易度 ⭐)

PYTHON
import numpy as np

# Scalar broadcasting
arr = np.array([[1, 2, 3],
                [4, 5, 6]])
print("arr + 10:\n", arr + 10)
print("arr * 2:\n", arr * 2)
print("arr  2:\n", arr  2)
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(2) ▶ サンプル

TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

: 列 + 行 = 外側演算 (難易度 ⭐⭐)

PYTHON
import numpy as np

# Standardize data: subtract mean, divide by std
data = np.random.randn(5, 3)  # 5 samples, 3 features

mean = data.mean(axis=0)  # shape (3,)
std = data.std(axis=0)    # shape (3,)

standardized = (data - mean) / std  # broadcasting!
print("Standardized shape:", standardized.shape)  # (5, 3)
print("Mean of standardized:", standardized.mean(axis=0).round(6))
# [ 0.  0.  0.]  (within floating point)
TEXT
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。



5. 比較表

(1) ブロードキャストとループ

次元 Pythonのforループ NumPyのブロードキャスティング
実行レイヤー Pythonインタプリタ Cレベルのufunc
速度 低速 (10~100倍) 高速
コード for i in range(n): ... a + b
メモリ 追加の割り当てなし 仮想 (データのコピーなし)
読みやすさ

(2) 放送との互換性

形状 A 形状 B 互換性あり? 結果
(3,) (3,) (3,)
(3,) (1,) (3,)
(4,3) (3,) (4,3)
(4,3) (4,1) (4,3)
(4,1) (1,3) (4,3)
(2,3) (4,3) エラー
(3,) (4,) エラー


6. 原理図

100%
graph TB
    A[Input arrays] --> B[Align dimensions from right]
    B --> C{Size matches?}
    C -->|Yes| D[Direct operation]
    C -->|One is 1| E[Expand size-1 dimension]
    E --> D
    C -->|Neither is 1| F[ValueError: incompatible]
    D --> G[Result array]
    
    style A fill:#e1f5fe
    style C fill:#fff9c4
    style D fill:#c8e6c9
    style F fill:#ffccbc
    style G fill:#c8e6c9

(1) ▶ サンプル:newaxis を使った 3D 放送(難易度 ⭐⭐)

PYTHON
import numpy as np

# 3D array + 1D vector
arr_3d = np.arange(24).reshape(2, 3, 4)
vec = np.array([10, 20, 30, 40])

result = arr_3d + vec
print("Shape:", result.shape)
print("First layer:\n", result[0])

# Broadcasting with newaxis
col = np.array([0, 10, 20])[:, np.newaxis]
row = np.array([1, 2, 3, 4])
print("col + row:\n", col + row)

出力:

TEXT
形状:(2, 3, 4)
最初の層:
 [[10 21 32 43]
 [14 25 36 47]
 [18 29 40 51]]
列 + 行:
 [[ 1  2  3  4]
 [11 12 13 14]
 [21 22 23 24]]


❓ よくある質問

Q ブロードキャスト処理では実際にデータがコピーされるのですか?
A いいえ。ブロードキャストは「仮想的な」操作です。NumPyはストライドの仕組みを利用して、新しいメモリを割り当てることなく、あたかもデータが展開されたかのように見せかけます。実際の展開は、計算中にC言語レベルで行われます。
Q 2つのシェイプがブロードキャスト互換かどうかを確認するにはどうすればよいですか?
A 右側から揃えて比較します。各次元のペアについて、値が等しいか、いずれかが1であれば互換性があります。いずれかのペアで条件を満たさず、かつどちらも1でない場合、互換性はありません。
Q ブロードキャストを行うとパフォーマンスの問題が発生しますか?
A いいえ。ブロードキャストは常にPythonのループよりも高速です。ただし、非常に大きな配列をブロードキャストして巨大な一時変数を埋める場合は、より多くのメモリを消費する可能性があります。 明示的な制御を行うには、np.einsum または np.matmul を使用してください。
Q ブロードキャスティングとタイル/リピートの違いは何ですか?
A np.tilenp.repeat は、メモリ内でデータを物理的に展開します。一方、ブロードキャスティングは仮想的に展開を行います。ブロードキャスティングの方が処理が速く、メモリ使用量も少なくて済みます。 タイル/リピートは、展開された配列を他の演算に使用する必要がある場合にのみ使用してください。

📖 まとめ



📝 練習問題

  1. 初心者(難易度 ⭐):4×3の行列と1×3の行ベクトルを作成し、それらを足し合わせます。次に、4×1の列ベクトルを作成し、それを行列に足し合わせます。その結果の形状を確認してください。

  2. 中級(難易度 ⭐⭐):形状が (5, 4, 3) の3次元配列と、形状が (3,) の1次元配列を作成してください。 これらを足し合わせてください。どの次元がブロードキャストされるかを説明してください。次に、(4, 3)の配列を3次元配列に足し合わせてみてください。うまくいきますか?

  3. 上級(難易度 ⭐⭐⭐):各データポイントに5つの特徴量を持つデータポイントを1000個生成します。ブロードキャスティングを使用してデータを正規化(平均値を引いて、標準偏差で割る)します。次に、Pythonのforループを使用して同じ処理を実装します。実行時間を比較してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%