📘 このレッスンについて:
NumPy は AI・機械学習で最も重要なライブラリのひとつです。このレッスンでは
AI学習を進めるうえで最低限必要な概念(配列・shape・ブロードキャスト・スライス・行列積)を
体験することを目的としています。
NumPy の詳細(統計計算・線形代数・フーリエ変換・画像処理など)は、
今後公開予定の 「NumPy完全入門コース」 で改めて解説します。
まずは「こういうものがある」と感覚をつかんでください。
1. NumPy配列の作成と基本情報
NumPy(import numpy as np)はPythonの数値計算の基盤ライブラリです。
Pythonの標準リストは汎用的ですが、10万件の数値の平均を求めるような大量計算では低速です。
NumPy の ndarray(多次元配列)は同じ型のデータをメモリ上に連続して格納するため、
ループ不要で高速な一括演算が可能になります。
配列を作ったら、まず3つの属性で構造を確認する習慣をつけましょう。
.shape は「各次元の要素数」(例: (4, 3) = 4行×3列)、
.dtype は「データ型」(例: int64、float64)、
.ndim は「次元数」(1次元=ベクトル、2次元=行列、3次元=テンソル)です。
PyTorchの Tensor も全く同じ属性を持ちます。
💡 PyTorch との対応: torch.Tensor も .shape, .dtype, .ndim を持ちます。NumPy の操作を覚えるとそのまま Tensor に応用できます。
💡 Python リスト vs NumPy 配列:
# Python リスト(遅い・冗長) data = [1, 2, 3, 4, 5] result = [x * 2 for x in data] # ループが必要 # NumPy 配列(高速・簡潔) data = np.array([1, 2, 3, 4, 5]) result = data * 2 # 全要素に一括適用
10万件の数値計算で、NumPy はリストのループ処理の 数十〜百倍以上高速です。大規模なデータを扱うAI/MLでは NumPy(や PyTorch の Tensor)なしには成り立ちません。
2. ブロードキャスト演算
NumPy 配列に対して算術演算を行うと、要素ごとに一括処理されます(ブロードキャスト)。 Python の for ループを書かずに済み、コードが簡潔になるだけでなく、 内部では C 言語レベルで最適化されているため非常に高速です。
スカラー値(単一の数値)と配列を演算すると、そのスカラー値が全要素に適用されます。
例えば glucose / 18.016 なら、配列の全要素を 18.016 で割った新しい配列が返ります。
同じ shape の配列同士を演算すると、対応する位置の要素同士が計算されます(要素積)。
また、glucose > 120 のような比較演算は True/False の配列(ブール配列)を返します。
これをインデックスとして使うことで、条件を満たす要素だけを抽出できます。
💡 Min-Max 正規化について:
(x - min) / (max - min) により、元データの範囲に関わらず出力を 0〜1 に収める処理です。
機械学習モデルは特徴量のスケールが大きく異なると学習が不安定になるため、
入力データをあらかじめ 0〜1(または平均0・標準偏差1)に揃えることが一般的です。
これを前処理(preprocessing)と呼びます。NumPy のブロードキャストを使えば1行で実装できます。
3. スライスとインデックスアクセス
1次元配列はリストと同じ a[start:stop:step] でスライスできます。
2次元配列は a[行, 列] でアクセスします。
a[:, 0] は「全行の0列目」(列方向の抽出)、
a[1, :] または a[1] は「1行目の全列」(行方向の抽出)です。
ブール配列をインデックスとして使う条件インデックスも重要です。
vitals[low_spo2_mask] のように書くと、
条件が True の行だけをまとめて取り出せます。
大規模データから特定の患者グループを抽出する際によく使うパターンです。
💡 np.where について:
np.where(condition) は条件が True であるインデックス(位置)を返します。
返り値はタプルで、1次元配列の場合は [0] で取り出します。
mask = np.array([True, False, True, False]) np.where(mask) # → (array([0, 2]),) ← タプルで返る np.where(mask)[0] # → array([0, 2]) ← インデックスの配列 # 「0番目と2番目が True」という意味
また np.where(condition, x, y) という3引数形式もあり、
条件が True の要素を x、False の要素を y で置き換えた配列を返します。
例: np.where(spo2 < 95, "低い", "正常")
4. reshape と行列演算
reshape() は配列の形状を変える操作です。要素の総数が同じなら自由に変換できます。
例えば 28×28 ピクセルの画像(784要素)をAIモデルに渡すには、
reshape(784) または reshape(-1) で1次元ベクトルに変換します。
-1 は「残りの要素数から自動計算」を意味します。
@ 演算子(または np.dot())は行列積を計算します。
*(アスタリスク)が要素ごとの積(element-wise)なのに対し、
@ は線形代数の行列積です。
ニューラルネットワークには全結合層(Linear 層)という層があります。
これはAIが入力データを次の層へ変換する基本的な計算単位で、
その中身は「入力 @ 重み + バイアス」という行列積そのものです。
今は「AIの計算の根本は行列積でできている」とだけ覚えておけばOKです。
💡 PyTorch 文脈: X @ W + b は PyTorch の nn.Linear が内部でやっていること(テンソルで)と全く同じです。NumPy でこの計算を理解しておくと、PyTorch のモデル設計がスムーズになります。
# NumPy(このレッスン) output = X @ W + b # PyTorch(AI資格コース等で登場) linear = nn.Linear(in_features=3, out_features=2) output = linear(X_tensor) # 内部で同じ行列積が走る
💡 @(行列積)と *(要素積)の違い:
A = np.array([[1, 2], [3, 4]]) B = np.array([[5, 6], [7, 8]]) A * B # 要素ごとの積 → [[1*5, 2*6], [3*7, 4*8]] = [[ 5,12],[21,32]] A @ B # 行列積 → [[1*5+2*7, 1*6+2*8], ...] = [[19,22],[43,50]]
ニューラルネットの計算には行列積(@)を使います。要素積(*)と混同しないよう注意が必要です。
5. 練習問題
検査値の平均・標準偏差をNumPyで計算
以下の白血球数(WBC)データを np.array() に変換し、平均・標準偏差・最大・最小を計算してください。基準値(3500〜9000)を外れる件数も表示します。
ヒントを見る(答え+解説)
import numpy as np
wbc_data = [4200, 7800, 11500, 3200, 5600, 9200, 6800, 2900, 8100, 4500]
wbc = np.array(wbc_data, dtype=float)
print(f"平均: {wbc.mean():.0f} /μL")
print(f"標準偏差: {wbc.std():.0f} /μL")
print(f"最大: {wbc.max():.0f} /μL")
print(f"最小: {wbc.min():.0f} /μL")
abnormal = ((wbc < 3500) | (wbc > 9000)).sum()
print(f"基準外: {abnormal}件")
# → 平均: 6400 /μL / 基準外: 4件
(wbc < 3500) | (wbc > 9000) はブール配列を返し、.sum() で True の個数(=条件を満たす要素数)を数えます。NumPy のブール演算では Python の and/or ではなく &/| を使います。
2次元配列から特定の行・列を取得
4患者×4検査項目の2次元配列から、SpO2列(0列目)と P002の全検査値(1行目)を取得してください。
ヒントを見る(答え+解説)
import numpy as np
data = np.array([
[98, 75, 120, 95], # P001
[94, 110, 145, 180], # P002
[97, 82, 130, 110], # P003
[99, 68, 118, 88], # P004
])
spo2_col = data[:, 0]
print(f"全患者のSpO2: {spo2_col}")
# → 全患者のSpO2: [98 94 97 99]
p002 = data[1]
print(f"P002の検査値: {p002}")
# → P002の検査値: [ 94 110 145 180]
data[:, 0] は「全行の0列目」(列スライス)、data[1] は「1行目の全列」(行スライス)を取り出します。NumPy の2次元配列では [行, 列] の形式でインデックスを指定します。
Min-Max正規化を実装する
以下の血糖値データを 0〜1 に正規化してください。公式: (x - min) / (max - min)
ヒントを見る(答え+解説)
import numpy as np
glucose = np.array([95.0, 120.0, 98.0, 145.0, 110.0, 88.0, 135.0, 102.0])
normalized = (glucose - glucose.min()) / (glucose.max() - glucose.min())
print(f"元のデータ: {glucose}")
print(f"正規化後: {normalized.round(3)}")
print(f"最小値確認: {normalized.min():.3f} (0になるはず)")
print(f"最大値確認: {normalized.max():.3f} (1になるはず)")
# → 最小値確認: 0.000 / 最大値確認: 1.000
NumPy のブロードキャストにより、glucose - glucose.min() は配列の全要素から最小値を一括で引きます。1行で Min-Max 正規化ができるのが NumPy の強みで、機械学習の前処理で頻出です。
まとめ
このレッスンのポイント
import numpy as np— AI/MLコードの定番インポートnp.array(list)でリストを高速な多次元配列に変換.shape,.dtype,.ndimで配列構造を確認- ブロードキャスト:
a + 1,a * 2で全要素を一括処理 - 2次元配列:
a[i, j]で行列アクセス、a[:, 0]で列全体 - 条件フィルタ:
a[a > 90]で条件に合う要素を抽出 @演算子で行列積 — AIが内部で行う変換計算(全結合層)の基本
自由に試してみましょう:
⚠️ この自由練習について: ここでは胸部X線画像の前処理・標準化・バッチ次元の追加など、 ディープラーニングで実際に使う操作を先取りして体験できます。 まだ「なぜこの処理が必要か」がわからなくても大丈夫です — まずはコードを実行して出力を眺めるだけでOK です。 PyTorch や画像処理を学んだあとに改めて見返すと、 「あのレッスンでやっていたのはこれか」と繋がります。
完了するとトップページに進捗が表示されます
