1. ブロードキャストとは
これまでに arr * 2 や arr + 10 のように、配列とスカラーの演算をしてきました。
これは内部的に「arr と同じ形のスカラー配列を作って各要素同士で演算」する処理になっており、
この自動拡張が ブロードキャスト(broadcasting) の最も単純な形です。
ブロードキャストは 形状の違う配列同士の演算にも適用されます。 ある規則を満たせば、NumPyが 足りない次元を自動的に補って 演算してくれます。 実際にコピーは作られないため、メモリ効率も非常に良い仕組みです。
2. ブロードキャストの規則
ブロードキャストが成立するか判定する手順は次の通りです。
- shape を末尾から比較する(右側=末尾の軸から)
- 各次元について次のどちらかを満たせばOK:
- サイズが 等しい
- どちらかのサイズが 1(その軸を「引き伸ばす」)
- 次元数が違う場合、足りない次元は左側に「サイズ1」を補う
| A の shape | B の shape | 判定 | 結果 shape |
|---|---|---|---|
| (4, 3) | (3,) | ✅ Bが左に1補完 → (1, 3) と比較 → 末尾3=3、軸0で1↔4 → OK | (4, 3) |
| (4, 3) | (4, 1) | ✅ 末尾で1↔3、軸0で4=4 → OK | (4, 3) |
| (4, 1) | (1, 3) | ✅ 末尾で1↔3、軸0で4↔1 → OK(外積的) | (4, 3) |
| (4, 3) | (4,) | ❌ Bが左に1補完 → (1, 4) と比較 → 末尾3≠4 でエラー | エラー |
| (4, 3) | (2, 3) | ❌ 軸0で4≠2、どちらも1でない → エラー | エラー |
💡 規則を一言でまとめると:
「末尾から各次元を比べて、サイズが等しいか、どちらかが1なら OK」。
慣れるまではエラーが出やすい箇所ですが、print(a.shape, b.shape) で両者の shape を確認する癖をつければすぐにコツが掴めます。
3. 正規化への応用(AI学習の基本)
ブロードキャストの真価を体感できる代表例が データの正規化(標準化)です。 「各列の値から、その列の平均を引いて、その列の標準偏差で割る」処理を たった1行で書けます。
ここで前のレッスンで学んだ keepdims=True が活きます。
集計後も shape を保つことで、元の (N, M) 配列と自然にブロードキャストできます。
🤖 AI用語メモ — 「データの正規化(標準化)」とは?
AI学習では、入力データの各特徴量を 「平均0・標準偏差1」 に揃える前処理が定番です。
これにより各特徴量のスケールが揃い、学習が安定して進みます。
上の (data - mean) / std の1行が「Zスコア正規化(Standardization)」と呼ばれ、機械学習・ディープラーニングの必須テクニックです。
scikit-learn の StandardScaler の中身はまさにこれです。
🩺 医療AI文脈: 患者×検査項目のデータでAIモデルを学習するとき、SBP(100台)・BMI(20台)・年齢(20〜90)のようにスケールがバラバラなままだと学習が偏ります。 正規化することで、すべての特徴量を 「平均からどれだけ離れているか(標準偏差を1単位として)」という共通の尺度に揃えられ、モデルがフェアに各特徴を扱えるようになります。
4. 練習問題
各行に同じベクトルを足そう
(3, 4) のゼロ配列に offset = np.array([1, 2, 3, 4]) を足して、
全行が [1, 2, 3, 4] になる ことを確認してください(ブロードキャスト)。
ヒントを見る(答え+解説)
import numpy as np
zeros = np.zeros((3, 4))
offset = np.array([1, 2, 3, 4])
# ブロードキャストで足してください
result = zeros + offset
print("結果:")
print(result)
# [[1. 2. 3. 4.]
# [1. 2. 3. 4.]
# [1. 2. 3. 4.]]
print("shape:", result.shape) # (3, 4)
(3, 4) + (4,) は、(4,) が左に1補完されて (1, 4) として扱われ、末尾の4が一致するためブロードキャストが成立します。各行に同じベクトルが足される結果になります。
各列に異なるスカラーを足そう
(4, 3) のゼロ配列に row_offset(shape (4, 1))を足して、
各行に異なる値が一様に足されることを確認してください。
ヒントを見る(答え+解説)
import numpy as np
zeros = np.zeros((4, 3))
# row_offset を (4, 1) の形で作ってください
row_offset = np.array([[10], [20], [30], [40]])
# 代替: row_offset = np.array([10, 20, 30, 40])[:, np.newaxis]
# 代替: row_offset = np.array([10, 20, 30, 40]).reshape(4, 1)
# ブロードキャストで足してください
result = zeros + row_offset
print(result)
# [[10. 10. 10.]
# [20. 20. 20.]
# [30. 30. 30.]
# [40. 40. 40.]]
print("row_offset shape:", row_offset.shape) # (4, 1)
print("結果 shape:", result.shape) # (4, 3)
(4, 3) + (4, 1) は末尾の軸でサイズ1↔3、軸0で4=4 となりブロードキャストが成立。row_offset の各行のスカラーが、その行全体に足されます。1次元配列 [10,20,30,40](shape (4,))のままでは末尾の比較で3≠4 となりエラーになる点に注意してください。
データを Zスコア正規化しよう
以下の (4, 2) 配列(4人 × 2項目)を 各列の平均0・標準偏差1 に正規化してください。
keepdims=True とブロードキャストの組み合わせで1行で書けます。
ヒントを見る(答え+解説)
import numpy as np
data = np.array([
[120, 65.0],
[140, 80.0],
[130, 70.0],
[150, 85.0]
])
# 列ごとの平均・標準偏差(keepdims=True で形を保つ)
mean = data.mean(axis=0, keepdims=True)
std = data.std(axis=0, keepdims=True)
# 正規化(1行で書く)
normalized = (data - mean) / std
print("正規化後:")
print(normalized.round(3))
print("\n確認 — 各列の平均(≈0): ", normalized.mean(axis=0).round(6))
print("確認 — 各列の標準偏差(≈1):", normalized.std(axis=0).round(6))
mean・std の shape は (1, 2) になります。data の (4, 2) と末尾比較で 2=2、軸0 で 4↔1 となりブロードキャストが成立し、各列が「自分の列の平均」「自分の列の標準偏差」で正規化されます。これは機械学習・ディープラーニングで毎回使う必須中の必須テクニックです。
5. まとめ
このレッスンのポイント
- ブロードキャストは 「形状の違う配列同士でも自動で形を合わせる」 仕組み
- 規則:末尾から比較 → サイズが等しい OR どちらかが1 ならOK / 不足分は左に1補完
- 典型パターン(いずれも結果は
(N, M)):(N, M) + (M,)→ 各行に同じベクトルを足す(N, M) + (N, 1)→ 各行に同じスカラーを足す(N, 1) + (1, M)→ 外積のように展開
keepdims=Trueと組み合わせると、列ごと・行ごとの集計結果を元の配列と自然に演算できる- 正規化
(data - mean) / stdがたった1行で書けるのがNumPyの真価
自由に試してみましょう:
完了するとコース一覧に進捗が記録されます