Python環境を起動中... 初回のみ数秒かかります
Lesson 19 / 20

NumPy入門

このレッスンで学ぶこと

  • NumPy 配列(ndarray)を作成し、shape/dtype を確認できる
  • ブロードキャスト演算でリスト全体を一括処理できる
  • スライス・インデックスで部分配列を取得できる
  • reshape・zeros・onesなど基本操作ができる

📘 このレッスンについて: 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 は「データ型」(例: int64float64)、 .ndim は「次元数」(1次元=ベクトル、2次元=行列、3次元=テンソル)です。 PyTorchの Tensor も全く同じ属性を持ちます。

sample_1.py
Ctrl+Enter
出力

💡 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 の配列(ブール配列)を返します。 これをインデックスとして使うことで、条件を満たす要素だけを抽出できます。

sample_2.py
Ctrl+Enter
出力

💡 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 の行だけをまとめて取り出せます。 大規模データから特定の患者グループを抽出する際によく使うパターンです。

sample_3.py
Ctrl+Enter
出力

💡 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です。

sample_4.py
Ctrl+Enter
出力

💡 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. 練習問題

問題 1

検査値の平均・標準偏差をNumPyで計算

以下の白血球数(WBC)データを np.array() に変換し、平均・標準偏差・最大・最小を計算してください。基準値(3500〜9000)を外れる件数も表示します。

exercise_1.py
出力
ヒントを見る(答え+解説)
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

2次元配列から特定の行・列を取得

4患者×4検査項目の2次元配列から、SpO2列(0列目)と P002の全検査値(1行目)を取得してください。

exercise_2.py
出力
ヒントを見る(答え+解説)
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次元配列では [行, 列] の形式でインデックスを指定します。

問題 3

Min-Max正規化を実装する

以下の血糖値データを 0〜1 に正規化してください。公式: (x - min) / (max - min)

exercise_3.py
出力
ヒントを見る(答え+解説)
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 や画像処理を学んだあとに改めて見返すと、 「あのレッスンでやっていたのはこれか」と繋がります。

free_practice.py
Ctrl+Enter
出力

完了するとトップページに進捗が表示されます