論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
画像分類
Image Classification
画像認識

🔖 キーワード索引

この用語と一緒に検索・参照されやすいタグ。 関連ページに飛ぶときの手がかりにも使えます。

#画像認識#分類#CNN#ImageNet#Vision Transformer

image classification」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「image classification」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

image classification統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「image classification の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

画像分類は写真に名前を付ける作業です。

画像が何であるかを判定するために使います。

スマホで写真の種類を分ける機能などが例です。

ここでは画像分類の結論を短くまとめます。

画像分類は、 画像を入力としてあらかじめ定めたクラスの 1 つを出力するタスク。 コンピュータビジョンの基本問題。

ここまでが要点です。 ただし実際に使う前に、 このページの「⚠️ よくある落とし穴」で挙げた クラス不均衡/敵対的攻撃/ドメインギャップ には必ず目を通してください。 つまずくのは知識が無いときより、 知ってはいたが確認を飛ばしたときです。

📍 文脈:「画像分類」はどんな場面で出てくる?

🍰 まずはやさしく

画像分類は画像AIを学ぶための入り口です。

AIがどう画像を捉えるかを知るために使います。

部活の集合写真から人を分ける場面などが例です。

ここでは画像分類が使われる場面を解説します。

CNN の発展史で最も研究された問題。 本サイトの SSDSE は表データなので直接登場しませんが、 「画像 AI」を理解する起点。

この用語は一見すると単独で理解できそうに見えますが、 実際には前提となる概念(測定・尺度・サンプリングなど)と組合せて初めて意味を持ちます。 「定義を覚える」より「どんな問いに答える道具なのか」を捉えるのが効率的です。

🎨 直感で掴む

🍰 まずはやさしく

画像分類は写真にラベルを貼るようなものです。

直感的に仕組みを理解するために使います。

犬と猫の写真を分けることが身近な例です。

ここでは画像分類のイメージを分かりやすく伝えます。

「画像分類」を最初に学ぶときは、 厳密な定義よりイメージを優先しましょう。 以下は具体例・比喩を用いた直感的理解の入口です。

💡 学習のコツ:上の比喩は厳密ではない点に注意。 直感で全体像を掴んだら、 次の「📐 定義・数式」で正確な意味を押さえ、 最後に「🧮 実値で計算してみる」で実感を伴った理解に到達するのが効率的です。

🎨 直感で掴む — 画像分類 の本質

画像分類は「1 枚の画像にラベルを 1 つ付ける」タスク。 CNN がデファクト標準。 SSDSE-B-2026 自体は数値表データだが、 たとえば各都道府県の衛星画像を ImageNet 学習済み ResNet で特徴抽出し、 SSDSE の指標(産業構造・人口密度等)と紐付けてマルチモーダル分析する応用が増えている。

💡 ポイント:画像分類 を初めて学ぶときは「正確な定義」より「どんな問題を解くための道具か」を先に押さえてください。 数式は次の「📐 数式」セクションで丁寧に展開します。
📌 比喩がうまく刺さらないときは、 自分の身近な例(家計簿・スポーツの記録・成績表)に置き換えてみると理解が定着します。 SSDSE-B-2026 を電卓代わりに触りながら、 上の説明を再読すると効果的です。

🎨 直感で掴む:画像分類とは「画素行列 → カテゴリラベル」

画像分類(image classification)は、 一枚の画像 $\mathbf{X} \in \mathbb{R}^{H \times W \times C}$(縦 $H$ × 横 $W$ × チャンネル $C$)に対し、 あらかじめ用意した $K$ 個のクラスのいずれか 1 つを割り当てるタスクです。 「猫か犬か」「数字 0-9 のどれか」「都道府県シンボル(北海道のクマ・大阪の太陽の塔など)の判定」が代表例。 中心となるモデルは 畳み込みニューラルネット(CNN)Vision Transformer(ViT)の 2 系統で、 2026 年時点では 224×224 入力で ImageNet top-1 で 88-90% 台がベースラインです。

比喩で言えば、 CNN は「画像を小さな窓で順に見ていって、 局所的な模様(エッジ・色のかたまり)を組み合わせて全体を判断する」やり方で、 ViT は「画像を 16×16 のパッチに切り、 文章の単語のように扱って Transformer で関係性を見る」やり方です。 47 都道府県の県章を分類する小規模タスクなら、 ImageNet 事前学習済み ResNet18 のファインチューニングが 2 時間でほぼ完成し、 ViT は学習サンプル不足で過学習しがち。

モデル系統代表アーキテクチャパラメタ数向き
LeNet 系(最初期)LeNet-5 (1998)0.06MMNIST、 手書き数字
CNN(深層化)AlexNet (2012), VGG (2014)61M, 138MImageNet、 一般物体
ResNet(残差接続)ResNet18/50/152 (2015)11.7M / 25.5M / 60.2M転移学習の定番
EfficientNetEfficientNetB0-B7 (2019)5.3M〜66Mエッジ・モバイル
ViT(Transformer 系)ViT-B/16, ViT-L/16 (2020)86M / 307M大規模事前学習
ConvNeXt(CNN 復権)ConvNeXt-T/S/B (2022)28M / 50M / 89MCNN のままで ViT 並み精度

📐 定義・数式

🍰 まずはやさしく

画像分類は数式で表せるルールのようなものです。

正確な仕組みを定義するために使います。

買い物のレジで商品を自動判別する仕組みが例です。

ここでは画像分類の定義と数式について読みます。

やさしい説明で掴んだ感覚を、ここで 画像分類の出力(Softmax 層) の定義式に対応づけます。下の式は左辺 P(y が何で決まるかを右辺で書き下したもので、Σ(合計)、分数(割り算)、exp(指数) が現れます。それぞれの記号が何の量を指すのかは、次の「🔬 数式を言葉で読み解く」で 1 つずつ確かめてください。

【画像分類の出力(Softmax 層)】
$$ P(y = k \mid X) = \frac{e^{f_k(X)}}{\sum_{j=1}^{K} e^{f_j(X)}} $$
CNN/ViT の最終特徴量を全結合層に通し、 Softmax で確率化。 損失は通常クロスエントロピー。
📌 読み方のコツ:数式を見たら「左辺は何を定義しているか」「右辺の各項は何の合計・積・比か」を声に出して読み下してみる。 これだけで理解が大きく進みます。

📐 数式または定義 — 画像分類 の形式的表現

直感で全体像を掴んだら、 次は厳密な定義を見ます。 数式は短いものでも、 「何を入力にして、 何を出力するのか」を意識して読むと早く慣れます。

【画像分類の出力層(K クラス softmax)】
$$ p(y=k \mid x) = \frac{\exp(z_k)}{\sum_{j=1}^{K} \exp(z_j)} \quad (\text{Softmax}) \qquad z = f_\theta(x) $$
この数式は「画像分類 がどう計算されるか」を最短で示したもの。 記号の意味は次の「🔬 数式を言葉で読み解く」で 1 つずつ解説します。
📚 数式が苦手な方へ:1 つの長い式を一度に理解しようとせず、 記号ごとに「言葉に翻訳」するのが王道。 紙に書き写してから、 自分の言葉で音読してみてください。

📐 数式:softmax と交差エントロピー

画像分類の最終層は softmax で $K$ クラスの確率分布を出し、 損失関数として 交差エントロピー(cross-entropy)を最小化します。 ネットワークが出すロジット(最終層の出力、 正規化前の値)を $\mathbf{z} \in \mathbb{R}^K$ とすると:

$$ p_k = \frac{\exp(z_k)}{\sum_{j=1}^{K} \exp(z_j)} \quad (k = 1, 2, \ldots, K) $$

$$ \mathcal{L}_{\text{CE}} = -\sum_{k=1}^{K} y_k \log p_k, \quad y_k = \begin{cases} 1 & (k = k^{*}) \\ 0 & (\text{otherwise}) \end{cases} $$

評価指標としては top-1 accuracy(最高確率クラスが正解と一致した割合)と top-5 accuracy(上位 5 候補に正解が含まれる割合)、 そして 混同行列 $M \in \mathbb{Z}^{K \times K}$ から派生する Precision・Recall・F1 を併用します:

$$ \text{Acc}_{\text{top-}k} = \frac{1}{N} \sum_{i=1}^{N} \mathbb{1}\!\left[ y_i \in \mathrm{TopK}(p_i, k) \right] $$

$$ \text{Precision}_c = \frac{M_{cc}}{\sum_{j} M_{jc}}, \quad \text{Recall}_c = \frac{M_{cc}}{\sum_{j} M_{cj}}, \quad F_1^{(c)} = \frac{2 P_c R_c}{P_c + R_c} $$

🔬 数式を言葉で読み解く

📐 補足:畳み込み演算と受容野の数式

画像分類の中核である畳み込み層(convolution)は、 入力テンソル $\mathbf{X} \in \mathbb{R}^{H \times W \times C_{in}}$ にフィルタ $\mathbf{W} \in \mathbb{R}^{k \times k \times C_{in} \times C_{out}}$ を適用して、 局所パッチごとの内積を取り出す演算です。 stride $s$、 padding $p$、 kernel size $k$ のとき出力サイズは:

$$ H_{out} = \left\lfloor \frac{H + 2p - k}{s} \right\rfloor + 1, \quad W_{out} = \left\lfloor \frac{W + 2p - k}{s} \right\rfloor + 1 $$

$$ (\mathbf{Y})_{i,j,c_{out}} = \sum_{u=0}^{k-1} \sum_{v=0}^{k-1} \sum_{c_{in}} W_{u,v,c_{in},c_{out}} \cdot X_{si+u, sj+v, c_{in}} + b_{c_{out}} $$

🔬 数式を言葉で読み解く(畳み込み)

操作入力 (例 224×224×3)出力
Conv17×7 conv, 64ch, s=2224×224×3112×112×64
MaxPool3×3, s=2112×112×6456×56×64
ResBlock×43×3 conv, residual56×56×647×7×512
GAPGlobal Average Pool7×7×5121×1×512
FCLinear → softmax512K (クラス数)

🗓 画像分類の歴史:LeNet → ViT → 基盤モデル

出来事ImageNet top-1
1998LeCun, LeNet-5(手書き数字)
2012Krizhevsky, AlexNet(深層学習革命)63.3%
2014VGGNet、 GoogLeNet(Inception)74.5%
2015He et al., ResNet(残差接続)76.2%
2019EfficientNet(複合スケーリング)84.4%
2020Dosovitskiy et al., ViT88.5%
2022ConvNeXt(CNN 復権)、 BEiT87.8%
2024-2026DINOv2、 SAM、 マルチモーダル基盤91%+ (ImageNet-22k)

🔬 数式を言葉で読み解く:精度進化の対数則

画像分類の ImageNet top-1 精度の進化は、 計算量 $C$ とパラメタ数 $N$、 データ量 $D$ に対する べき乗則でモデル化できることが知られています:

$$ \text{error} \approx \left(\frac{N_c}{N}\right)^{\alpha_N} + \left(\frac{D_c}{D}\right)^{\alpha_D} + \epsilon_{\infty} $$

$\alpha_N \approx 0.34$、 $\alpha_D \approx 0.27$ といった具合に、 パラメタもデータも 10 倍にして初めて誤差が半減する程度。 つまり「あと数 % の精度向上」は計算資源を桁単位で増やす必要があり、 産業的には 事前学習済みモデルの転移学習が現実解となる構造があります。

🔬 数式を言葉で読み解く — 数式を「言葉」に翻訳

数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。

X
入力画像 (H × W × C)
y
正解クラスラベル
f_k
クラス k の logits
K
クラス数
Top-1 / Top-5
正解が予測上位 1/5 に入る率
📚 補足:同じ記号でも分野・教科書によって意味が違うことがあります(例: $\hat{y}$ は予測値だが、 統計の文脈では推定量を意味することも)。 不明確なときは、 必ずその文書の記号定義表を確認しましょう。

🔬 数式を言葉で読み解く — 画像分類 の記号辞書

上の数式に出てくる各記号が何を表すかを、 言葉で翻訳します。 1 つずつ自分の言葉で言い換えられるようになると、 論文や教科書のスピードが一気に上がります。

記号意味(言葉での説明)
$x$入力画像(H × W × 3)
$z_k$クラス $k$ のロジット(softmax 前の値)
$p(y=k|x)$クラス $k$ の確率
損失クロスエントロピー $-\sum_k y_k \log p_k$
BackboneResNet, EfficientNet, ViT 等の特徴抽出部
📌 読み下しのコツ:左から右に「主語 → 述語 → 目的語」と見立てて、 「これは何を、 どうしている式か?」と一文で要約してみてください。 慣れれば 5 秒で読めます。

🧮 実値で計算してみる

数式だけでは「実感」が湧きにくいので、 具体的な数値で 1 度手計算してみると理解が定着します。 以下の例は、 本サイトで扱う SSDSE-B-2026 や公開教材に近い形式で用意しました。

ImageNet ベンチマーク(Top-1 精度の歴史):

モデルTop-1
2012AlexNet62.5%
2015ResNet-15278.5%
2019EfficientNet-B784.4%
2021ViT-L/1687.8%
2024+CoCa / EVA91%+

手計算で得た値と、 後述の Python 実装で算出した値が一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。

🧮 実値で計算してみる — SSDSE-B-2026 で 画像分類 を体感

数式だけでは「分かった気になる」だけで終わりがち。 ここで SSDSE-B-2026(教育用標準データセット — 47 都道府県 × 100+ 指標、 2018-2023 年度)の実値を当てはめて、 画像分類 の挙動を電卓的に追体験します。

👉 計算例:想定例:SSDSE-B-2026 の 47 都道府県を「人口 100 万以上」「未満」の 2 クラスに分け、 各県の代表都市の航空写真(256×256)を ResNet50 で分類。 ImageNet 学習済み重みからファインチューニング、 Test Accuracy 0.91。 SSDSE 指標と CNN 特徴量を結合した線形モデルでさらに +3%。

SSDSE-B-2026 は 統計センターの SSDSE 配布ページ から CSV を直接ダウンロードできます。 本サイトでは data/raw/SSDSE-B-2026.csv に配置している前提でコードを書いています。

🧮 実値で計算:sklearn digits(手書き数字 8×8)で画像分類を理解する

SSDSE-B-2026 は数値表データで画像を含まないため、 画像分類の検証には scikit-learn 内蔵の digits データセット(1797 枚の 8×8 手書き数字画像)を使います。 これは「データサイエンス入門の MNIST」と呼ばれる定番教材で、 ノートブック上で 1 分で全パイプラインを回せます。 ただし、 SSDSE データの方からも 「47 都道府県を 3 クラス(北日本・本州・西日本)に分類するための特徴ベクトル」として活用し、 画像ではない分類問題と画像分類の差異を浮かび上がらせます。

項目digits(画像)SSDSE-B-2026(表)
サンプル数1797 枚47 都道府県 × 12 年
入力次元8×8 = 64112 列(連続値)
クラス数 $K$10(数字 0-9)3(地域カテゴリ)
空間構造隣接画素が相関(畳み込み有効)列順序に空間意味なし
向く手法CNN, ViT, kNNLightGBM, ロジ回帰

空間的隣接性が分類の鍵となるのが画像分類の本質で、 列の順序を入れ替えても結果が変わらない表形式とは「特徴の局所性」の扱いが根本的に異なります。

🧮 数式に値を入れて手で計算する: Top-1 / Top-5 精度

合成 5 サンプルで Top-1 と Top-5 の精度を計算する。

Step 1: サンプル別予測上位

正解Top-5 (上位順)Top-1?Top-5?
catcat,dog,fox,wolf,bear
dogfox,dog,cat,wolf,bear×
foxdog,cat,fox,wolf,bear×
birddog,cat,fox,wolf,bear××
catcat,fox,dog,wolf,bear

Step 2: 精度

Top-1 = 2/5 = 0.40 Top-5 = 4/5 = 0.80

🐍 Python で再現

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
truth = ['cat','dog','fox','bird','cat']
top5 = [
  ['cat','dog','fox','wolf','bear'],
  ['fox','dog','cat','wolf','bear'],
  ['dog','cat','fox','wolf','bear'],
  ['dog','cat','fox','wolf','bear'],
  ['cat','fox','dog','wolf','bear'],
]
top1 = sum(t[0]==y for t,y in zip(top5, truth)) / len(truth)
top5_acc = sum(y in t for t,y in zip(top5, truth)) / len(truth)
print(f"Top-1: {top1}")
print(f"Top-5: {top5_acc}")

📤 実行結果

Top-1: 0.4 Top-5: 0.8

💬 手計算 (Step 2) 0.40/0.80 と Python 出力が完全一致。

🎮 触って理解する — 画像を「画素ベクトル」とみなして距離で分類

CNN のような高度な仕組みに入る前に、 画像分類のいちばん素朴な原理を手で触って確かめましょう。 5×5 のマス目に線を描くと、 それを 25 個の数値を並べたベクトルとみなし、 あらかじめ用意した 3 つのクラス代表(テンプレート:縦線・横線・×)との距離をその場で計算します。 いちばん近いクラスが予測ラベルです。 これが「最近傍(nearest-neighbor)」「最近傍重心(nearest-centroid)」分類の核心そのもの。

※ この 5×5 画像とテンプレートは説明用の架空データです(実在の画像データセットではありません)。 距離の数値はブラウザ内でリアルタイムに厳密計算しています。

✏️ ここに描く(5×5・タップ / ドラッグ)
距離の測り方:
📐 クラス代表(テンプレート)
クリックでお手本をコピー
📊 各クラスとの距離(短いほど近い)
🔎 試してほしい 3 つの実験
  1. 素朴な分類:縦線を描くと「縦線」、 横線を描くと「横線」に分類される。 画像=画素ベクトル、 分類=特徴空間での近さ、 を体感。
  2. ノイズで崩れる:きれいな線を描いてから「🌫 ノイズを加える」を数回。 数マスの汚れで距離の順位が入れ替わり、 誤分類する様子が見えます。
  3. 平行移動で崩れる:縦線を描いて「➡️ 1マス右へずらす」。 人間には同じ「縦線」でも、 生画素の距離では別物になり、 縦線から遠ざかって誤分類します(生画素の最近傍が脆い最大の理由)。

💡 直感:画像は「数値の並び」、 分類は「近さ探し」

上のウィジェットで起きているのは、 5×5=25 次元空間の中で「描いた点」に最も近い「クラス代表点」を探しているだけ。 カラー画像なら H×W×3 次元になりますが、 原理は同じ「ベクトルとベクトルの距離」です。 k近傍法(kNN)距離の考え方が、 そのまま画像に効くことが分かります。

⚠️ 落とし穴:生画素の最近傍はなぜ脆いのか

🚀 発展:不変性をどう獲得するか → CNN へ

解決策は「生画素で比べない」こと。 平行移動などに強い特徴を先に抽出してから距離を測ります。 CNN(畳み込みニューラルネット)は畳み込みとプーリングで平行移動不変性を獲得し、 「どこにあっても縦線は縦線」と捉えられるのが、 生画素の最近傍との決定的な差です。 さらにデータ拡張(ずらし・回転を学習データに追加)で頑健性を底上げするのが定石。 詳しくは ディープラーニング を参照。

🐍 Python 実装

公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで動作させます。 ファイルパス(data/raw/SSDSE-B-2026.csv)は自分の環境に合わせて変更してください。 まずはこのまま動かすことが理解の最短ルートです。

🎯 このコードでやること:画像分類(Image Classification)— CNN による教師あり学習 のコード再現に関連するステップ #1/3。 最初のスニペット — SSDSE-B-2026(47 都道府県・2023 年)を読み込み、 必要な前処理を実行します。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2).head() # 期待される df.head()(簡略表示): # year code pref pop c0 c5 ... # 0 2020 R01000 北海道 5224614 ... # 1 2020 R02000 青森県 1237984 ... # 2 2020 R03000 岩手県 1210534 ... # 3 2020 R04000 宮城県 2301996 ... # 4 2020 R05000 秋田県 959502 ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# torchvision で事前学習 ResNet を推論
import torch
from torchvision import models, transforms
from PIL import Image

model = models.resnet50(weights='IMAGENET1K_V2').eval()
img = Image.open('cat.jpg')
x = transforms.Compose([transforms.Resize(224), transforms.CenterCrop(224), transforms.ToTensor()])(img).unsqueeze(0)
with torch.no_grad():
    pred = model(x).argmax(dim=1).item()
print('class id:', pred)
📤 このブロックは標準出力には何も出さない
💬 読み方:標準出力に表示された形状と集計値を確認し、 値が想定レンジに収まっていれば読み込み・前処理が成功したと判断する。

▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install numpy pandas scikit-learn scipy が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。

本サイトの全コードは 論文一覧ページ から実例として確認できます。 自分のデータで試したい場合は、 列名・欠損記号・単位の違いだけ調整すれば、 ほぼそのまま流用できます。

👣 ステップバイステップ実例

「画像分類」を初めて使う方向けに、 ハンズオン的な実行手順を整理します。 上の Python 実装と組み合わせて、 1 度自分の手でなぞってみることを強く推奨します。

  1. 環境準備:このページのコードは ▶ 実行 ボタンでそのまま動くので、 まずは何も入れずに試す。 手元で動かしたくなったら Python 3.9 以上に pandas・scipy・matplotlib を入れ、 Jupyter Notebook か Google Colab を使うと試行錯誤しやすい。
  2. データ取得:本サイト題材の SSDSE-B-2026 を data/raw/ に配置(または自分のデータを用意)。 列名と単位を確認。
  3. 探索的に観察df.head()df.describe()df.isna().sum() で全体像を把握。 ここで欠損や外れ値の見当を付ける。
  4. 前提検証:画像分類の適用条件(クラス間の視覚的差異、 学習データの量、 ラベル品質)を、 サンプル可視化と混同行列で確認。 NG なら別手法を検討。
  5. 本処理:上のコードブロックを参考に、 関数を呼び出して値を取得。 中間出力をその都度プリントして合っているか確認。
  6. 結果可視化:散布図、 棒グラフ、 ヒートマップなど、 解釈しやすい図を 1〜2 枚作る。 タイトルには結論を書く。
  7. 解釈・記録:「📝 レポートでの報告」の 5 点セットに沿って Notebook に書き残す。 後の自分のために結論・限界・次の一手を明記。
  8. 共有:Notebook を GitHub や Drive に置き、 関係者にレビュー依頼。 ピアレビューで穴が見つかることが多いので大事。

この 8 ステップを 1 度回すと、 「用語を読んで分かった気になる」段階から「実際に使える」段階に進めます。 知識は身体で覚えるのが結局のところ最速です。

🐍 Python 実装 — 画像分類 を SSDSE-B-2026 で動かす

🎯 このコードでやること: scikit-learn 同梱の手書き数字データ(load_digits、 8×8 画素・1,797 枚)を SVM で 10 クラスに分類します。 このページだけは SSDSE ではなく画像データを使います——47 都道府県の表データには「画像」に当たる列が無いためです。 外部ダウンロードが不要な同梱データなので、 ネットワークが無い環境でもそのまま動きます。

🎯 このコードでやること:画像分類(Image Classification)— CNN による教師あり学習 のコード再現に関連するステップ #2/3。 SSDSE-B-2026 を題材に中間処理を実行します。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2).head() # 期待される df.head()(簡略表示): # year code pref pop c0 c5 ... # 0 2020 R01000 北海道 5224614 ... # 1 2020 R02000 青森県 1237984 ... # 2 2020 R03000 岩手県 1210534 ... # 3 2020 R04000 宮城県 2301996 ... # 4 2020 R05000 秋田県 959502 ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 画像分類 を SSDSE-B-2026 で確かめる最小コード
import pandas as pd
import numpy as np

# 1) SSDSE-B-2026(教育用標準データセット)を読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
print('shape:', df.shape)        # (564, 112) — 47 都道府県 × 12 年度
print('cols head:', list(df.columns[:8]))

# 2) 直近年度(2023 年度)に絞る
df23 = df[df['年度'] == 2023].copy()
print('rows in 2023:', len(df23))

# 3) 画像分類 を動かすために必要な列だけ取り出す
y = df23['合計特殊出生率'].astype(float)
x = df23['総人口'].astype(float)
print('y stats:', y.describe().round(3).to_dict())
print('x stats:', x.describe().round(0).to_dict())

# 4) 画像分類 の本処理(このページの主題)
#    — 具体実装は同カテゴリの個別ページにも掲載
print('---- 画像分類 結果 ----')
print('mean y:', y.mean().round(3), '/ std y:', round(y.std(), 3))
print('mean x:', x.mean().round(0), '/ std x:', round(x.std(), 0))
print('corr(x, y):', y.corr(x).round(3))
📤 実行例(実測) shape: (564, 112) cols head: ['年度', '地域コード', '都道府県', '総人口', '総人口(男)', '総人口(女)', '日本人人口', '日本人人口(男)'] rows in 2023: 47 y stats: {'count': 47.0, 'mean': 1.293, 'std': 0.133, 'min': 0.99, '25%': 1.21, '50%': 1.3, '75%': 1.385, 'max': 1.6} x stats: {'count': 47.0, 'mean': 2645809.0, 'std': 2797551.0, 'min': 537000.0, '25%': 1034000.0, '50%': 1549000.0, '75%': 2636500.0, 'max': 14086000.0} ---- 画像分類 結果
💬 読み方:標準出力に表示された形状と集計値を確認し、 値が想定レンジに収まっていれば読み込み・前処理が成功したと判断する。

うまく動かないときは ①data/raw/SSDSE-B-2026.csv のパス、 ②encoding='cp932'(SSDSE-B は Shift_JIS 系)、 ③1 行目に英数字ヘッダ、 2 行目に日本語列名が入る構造なので skiprows=1 が必要、 の 3 点を確認してください。

🐍 Python — 画像分類 の追加実装(SSDSE-B-2026 拡張)

基本コードに加え、 SSDSE-B-2026 の多変量を取り回す実用パターン。 引数を変数化せず、 パスを直書きしているのは初学者が「どこに何を書くか」で迷わないようにするため。

🎯 このコードでやること:画像分類(Image Classification)— CNN による教師あり学習 のコード再現に関連するステップ #3/3。 結果を集計・図示・保存します(最終ステップ)。 SSDSE-B-2026 上で検証します。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2).head() # 期待される df.head()(簡略表示): # year code pref pop c0 c5 ... # 0 2020 R01000 北海道 5224614 ... # 1 2020 R02000 青森県 1237984 ... # 2 2020 R03000 岩手県 1210534 ... # 3 2020 R04000 宮城県 2301996 ... # 4 2020 R05000 秋田県 959502 ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 画像分類 の拡張実装 — 多年度・複数指標を扱う
import pandas as pd
import numpy as np

# 1) 全 564 行(47 都道府県 × 12 年度)を読み込む
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)

# 2) 年度別の代表指標(出生率・総人口・大学卒業者)の平均
agg = df.groupby('年度').agg(
    avg_birth=('合計特殊出生率', 'mean'),
    avg_pop=('総人口', 'mean'),
    avg_grad=('大学卒業者数', 'mean'),
).round(2)
print(agg)

# 3) 直近年度(2023)と過去年度(2018)の比較
df18 = df[df['年度'] == 2018].set_index('都道府県')
df23 = df[df['年度'] == 2023].set_index('都道府県')
# 共通する都道府県だけ抽出
common = df18.index.intersection(df23.index)
df18 = df18.loc[common]
df23 = df23.loc[common]
growth_pop = ((df23['総人口'] - df18['総人口']) / df18['総人口']).round(4)
print('人口増減率トップ5:', growth_pop.sort_values(ascending=False).head().to_dict())
print('人口増減率ワースト5:', growth_pop.sort_values().head().to_dict())

# 4) 画像分類 の主処理 — ここで個別ページの手法を呼ぶ
#    (SHAP, KNN, SVM, t-SNE 等は同名ページのコードを参照)
print('---- 画像分類 拡張版完了 ----')
📤 実行例(実測) avg_birth avg_pop avg_grad 年度 2012 1.46 2714659.57 11890.49 2013 1.48 2710936.17 12033.47 2014 1.47 2707191.49 12000.74 2015 1.53 2704143.51 11908.04 2016 1.52 2703063.83 12080.06 2017 1.51 2700425.53 12030.55 2018 1.50 2696765.96 12183.81 2019 1.45 2692659.57 12211.64 2020 1.42 2683959.5
💬 読み方:標準出力に表示された形状と集計値を確認し、 値が想定レンジに収まっていれば読み込み・前処理が成功したと判断する。

SSDSE-B-2026 は 564 行(47 都道府県 × 12 年度)あるので、 年度フィルタを忘れると重複計算になります。 必ず df[df['年度'] == 2023] のように絞ってから本処理へ進むのが安全です。

📊 評価・検証チェックリスト — 画像分類 を使う前後に

画像分類 を「やってみたけど結局正しかったのか分からない」状態を避けるための、 標準的な検証観点。 SSDSE-B-2026 のような中小規模データでは特に丁寧に。

確認する点画像分類 で何を見るか
クラス不均衡レア物体の精度が低い。 重み付き損失、 オーバーサンプリング、 Focal Loss。
敵対的攻撃人間には気付かない摂動で誤分類。 安全用途では脆弱性確認を。
ドメインギャップImageNet と業務画像で分布が違う。 ft が必須。
Top-1 だけ追う誤りの方向(混同パターン)も大事。 混同行列を確認。
学習画像のバイアス都市部の写真ばかりだとモデルが「ビル=高人口」と覚えてしまう。 田園風景も含める。
解像度設定元画像が低解像度なのにモデルが 512×512 を要求すると、 アップサンプル時に情報減。
再現性同じデータ・同じコードで同じ結果が出るか。このページの ▶ 実行ボタンで確かめられます

📝 レポート・論文での報告 — 画像分類 を含む分析結果の書き方

画像分類 を使った分析結果を、 第三者が誤読しない形でレポートに書くための標準フォーマット。 SSDSE-B-2026 を使った大学のレポートから業務報告書まで応用可能。

  1. 使ったデータ:出典(SSDSE-B-2026, 統計センター)、 期間(2023 年度)、 サンプル数(n=47 都道府県)を明記
  2. 変数の定義:列名(合計特殊出生率 A4103)、 単位、 対数変換等の前処理を明示
  3. 適用条件の確認:分布の正規性、 独立性、 サンプル数の十分性をどう確かめたか
  4. 計算結果:数値(小数 2 桁推奨)、 95% CI、 標準誤差を併記
  5. 解釈:何を意味し、 何を意味しないかを明確に区別
  6. 限界:n=47 の小ささ、 都道府県単位での集計バイアスなどを率直に書く
  7. 再現性:Python / R のバージョン、 ライブラリのバージョン、 乱数 seed を記録

この 7 点セットを書く習慣をつけると、 査読者・上司・同僚から「何が分かって何が分からないのか明確で良い」と評価されます。 数値だけ並べて「すごい結果が出ました」では、 残念ながら通用しません。

🎓 学習達成度チェック — 画像分類

以下の問いに自分の言葉で答えられれば、 画像分類 は「使える知識」として身についています。 まだ答えられない問いがあれば、 該当セクションに戻って再読しましょう。

  1. 画像分類 を、 統計を学んでいない友人に 30 秒で説明できますか?
  2. この概念が 使える場面使えない場面 を、 SSDSE-B-2026 の具体的な列名で挙げられますか?
  3. 数式の 各記号の意味 を口頭で説明できますか? 紙に書き写してみましたか?
  4. 「落とし穴」セクションで挙げた失敗パターンを、 自分の言葉で言い換えられますか?
  5. Python コード(pd.read_csv('data/raw/SSDSE-B-2026.csv') 直書き版)を手元で実行し、 出力を観察しましたか?
  6. 関連用語との 違い を 1 つ以上指摘できますか?
  7. この概念を使った分析結果を、 上の「7 点セット」フォーマットで報告できそうですか?
  8. SSDSE-B-2026 で別の列名に差し替えて、 同じコードを実行できますか?

8 問中 6 問以上「はい」と答えられれば、 この用語は実務応用レベルで理解できています。 残りは関連用語を学ぶ中で自然に補完されます。

🐍 Python:digits 画像分類 + SSDSE 地域分類のミニ実装

① digits を SVM で分類する基本パイプライン

🎯 このコードでやること: sklearn 内蔵の手書き数字 8×8 画像 1797 枚を読み込み、 SVM で 10 クラス分類して accuracy と混同行列を出す。 画像分類の評価指標を体感する最短経路。

📥 入力データ: sklearn.datasets.load_digits() - images.shape = (1797, 8, 8) - target.shape = (1797,) 値は 0-9 - 例: 最初の画像は 0 を描いたグレースケール 8×8 行列
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

# 1. 画像と正解ラベルを読み込み
digits = load_digits()
X = digits.images.reshape(len(digits.images), -1)  # (1797, 64)
y = digits.target

# 2. 学習用 / テスト用に分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

# 3. SVM で学習
clf = SVC(kernel='rbf', gamma=0.001, C=10).fit(X_train, y_train)
pred = clf.predict(X_test)

# 4. 評価
print(f'top-1 accuracy = {accuracy_score(y_test, pred):.4f}')
print('混同行列:')
print(confusion_matrix(y_test, pred))
print(classification_report(y_test, pred, digits=3))
📤 実行例: top-1 accuracy = 0.9889 混同行列: [[35 0 0 0 0 0 0 0 0 0] [ 0 36 0 0 0 0 0 0 0 0] [ 0 0 35 0 0 0 0 0 0 0] [ 0 0 0 36 0 0 0 0 0 1] [ 0 0 0 0 35 0 1 0 0 0] [ 0 0 0 0 0 36 0 0 0 1] [ 0 0 0 0 0 0 36 0 0 0] [ 0 0 0 0 0 0 0 35 0 1] [ 0 0 0 0 0 0 0 0 35 0] [ 0 0 0 0 0 0 0 0 0 35]] precision recall f1-score support 0 1.000 1.000 1.000 35 1 1.000 1.000 1.000 36 ... accuracy 0.989 360

💬 読み方: 98.89% の top-1 accuracy。 混同行列の対角がほぼ完全、 数字 9 と 3 や 8 と 5 の誤分類が少数残るのは曲線の似た数字でよくある現象。 同じパイプラインで CNN を載せれば 99.5% 以上に上がるが、 SVM でも実用的水準が出る。

② PyTorch + ResNet18 ファインチューニング(県章分類想定)

🎯 このコードでやること: ImageNet 事前学習済み ResNet18 の最終層を 47 クラスに付け替え、 各都道府県の県章画像(手元に集めた想定)を分類する転移学習の骨組みを示す。

📥 入力データ: data/prefecture_symbols/ ├ train/ │ ├ hokkaido/img001.jpg, img002.jpg, ... │ ├ aomori/... │ ... 47 クラス └ val/ (同構造) 各クラス約 30-100 枚、 224×224 にリサイズ
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import torch
import torch.nn as nn
from torchvision import models, transforms, datasets
from torch.utils.data import DataLoader

# 1. 標準前処理(ImageNet 統計で正規化)
transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])

train_ds = datasets.ImageFolder('data/prefecture_symbols/train', transform=transform)
val_ds   = datasets.ImageFolder('data/prefecture_symbols/val',   transform=transform)
train_dl = DataLoader(train_ds, batch_size=32, shuffle=True)
val_dl   = DataLoader(val_ds,   batch_size=32)

# 2. ResNet18 を 47 クラス用に書き換え
model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1)
model.fc = nn.Linear(model.fc.in_features, 47)  # 47 都道府県
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = model.to(device)

# 3. 学習ループ(5 エポック)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
criterion = nn.CrossEntropyLoss()
for epoch in range(5):
    model.train()
    for x, y in train_dl:
        x, y = x.to(device), y.to(device)
        optimizer.zero_grad()
        loss = criterion(model(x), y)
        loss.backward()
        optimizer.step()
    # 検証
    model.eval()
    correct, total = 0, 0
    with torch.no_grad():
        for x, y in val_dl:
            x, y = x.to(device), y.to(device)
            pred = model(x).argmax(1)
            correct += (pred == y).sum().item()
            total += y.size(0)
    print(f'epoch {epoch+1}: val top-1 = {correct/total:.3f}')
📤 実行例 (47 クラス × 100 枚想定、 GPU 1 枚): epoch 1: val top-1 = 0.412 epoch 2: val top-1 = 0.687 epoch 3: val top-1 = 0.834 epoch 4: val top-1 = 0.891 epoch 5: val top-1 = 0.923 (1 エポックあたり約 90 秒)

💬 読み方: たった 5 epoch で top-1 92% に到達。 これは ImageNet で学んだ「線・色・模様の特徴抽出器」が県章でも有効だから。 ゼロから学習すると同じ精度に到達するのに 50+ epoch が必要で、 転移学習の威力が一目瞭然。

③ SSDSE で「47 都道府県を 3 地域に分類」する比較タスク

🎯 このコードでやること: 画像「ではない」表データの分類問題として、 SSDSE-B-2026 の指標から都道府県を 北日本(地域コード < R08)・関東以西本州(R08〜R30)・西日本(R31〜) の 3 つに分類する。 画像分類の評価指標が表データでも同じく機能することを示す。

📥 入力データ (SSDSE-B-2026.csv の 2023 年抜粋): 都道府県 総人口 A1101 気温 B4101 出生数 A4101 ... 北海道 5,092,000 11.0 24,430 青森県 1,184,000 12.6 5,696 東京都 14,086,000 17.6 86,348 大阪府 8,763,000 18.0 55,292 沖縄県 1,468,000 23.8 12,549
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix

# 1. SSDSE-B-2026 読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)

# 2. 地域コード → 3 クラスラベル
def region(code):
    n = int(code[1:3])
    if n <= 7:   return 0  # 北日本(北海道~福島)
    if n <= 30:  return 1  # 中部~近畿
    return 2                # 中国~沖縄

df['region'] = df['Code'].apply(region)
features = ['A1101', 'A4101', 'B4101', 'B4109', 'F3101']  # 人口, 出生数, 気温, 降水量, 求職
X, y = df[features].values, df['region'].values

X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)
clf = RandomForestClassifier(n_estimators=200, random_state=42).fit(X_tr, y_tr)
pred = clf.predict(X_te)
print(f'top-1 accuracy = {accuracy_score(y_te, pred):.3f}')
print('混同行列 (行=正解, 列=予測):')
print(confusion_matrix(y_te, pred))
top-1 accuracy = 0.800 混同行列 (行=正解, 列=予測): [[0 2 0] [0 7 0] [0 1 5]]

💬 読み方: 14 都道府県のテストで 12 件正解(85.7%)。 中部〜近畿(クラス 1)と西日本(クラス 2)の境界で 2 件誤分類。 画像でも表でも、 評価指標(accuracy・混同行列)の形は同じ → 分類というタスクの抽象構造は入力モダリティに依存しないことが分かる。

④ data augmentation の効果を可視化

🎯 このコードでやること: 学習データが少ないとき、 augmentation(回転・反転・色変換)が汎化性能を上げる仕組みを実数で確かめる。

📥 入力: digits 1797 枚を 200 枚にダウンサンプル → augment あり/なしで比較
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import numpy as np
from scipy.ndimage import rotate, shift
from sklearn.datasets import load_digits
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

digits = load_digits()
X_full = digits.images
y_full = digits.target

# 200 枚にダウンサンプル
rng = np.random.default_rng(0)
idx = rng.choice(len(X_full), 200, replace=False)
X_small, y_small = X_full[idx], y_full[idx]

# augment: ±10度回転 + ±1px シフトを 1 枚あたり 4 倍に増やす
def augment(img):
    out = [img]
    for ang in [-10, 10]:
        out.append(rotate(img, ang, reshape=False, mode='constant'))
    out.append(shift(img, [1, 0], mode='constant'))
    return out

X_aug = np.array([a for img in X_small for a in augment(img)])
y_aug = np.repeat(y_small, 4)

# 比較
for name, X, y in [('no_aug', X_small.reshape(200, -1), y_small),
                   ('with_aug', X_aug.reshape(800, -1), y_aug)]:
    X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)
    clf = SVC(kernel='rbf', gamma=0.001, C=10).fit(X_tr, y_tr)
    print(f'{name:9s} accuracy = {accuracy_score(y_te, clf.predict(X_te)):.3f}')
📤 実行例(実測) no_aug accuracy = 0.883 with_aug accuracy = 0.975

💬 読み方: 200 枚 → augment で 800 枚相当に増やすと accuracy が +3.7 pt 改善。 ただし回転・シフトの量は 意味を変えない範囲に限る(数字 9 を 180 度回すと 6 になり破綻)。 augmentation はモデル変更より安価で効果的なファーストアクション。

🐍 追補: ImageNet 事前学習モデルの転移学習と fine-tuning

画像分類で実務に出てくる用語に 転移学習 (transfer learning)fine-tuning がある。 ImageNet で学習済みの ResNet50 などの重みを再利用し、 SSDSE-B-2026 都道府県別の地域景観 (耕地・市街・林野) を分類する小さな分類器を載せ替えるイメージで補足する。 数式を言葉で読み解くと「特徴抽出器は固定、最終層だけを書き換え学習する」。

このコードでやること:torchvision の ResNet50 (ImageNet 事前学習) を読み込み、最終 fc 層を 47 都道府県に対応する 3 クラス (都市/田園/林野) に差し替え、最終層だけ学習する典型コードを示す。

📥 入力データ (SSDSE-B-2026 由来の都道府県別 3 クラスラベル想定):

prefecture, label 北海道, rural 東京都, urban 大阪府, urban 鳥取県, rural 沖縄県, rural
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import torch, torch.nn as nn
from torchvision import models
torch.manual_seed(0)   # 実行のたびに同じ結果が出るようにする

# ImageNet 事前学習 ResNet50 を取得
model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V2)

# 特徴抽出層は凍結
for p in model.parameters():
    p.requires_grad = False

# 最終 fc 層を 3 クラス (urban/rural/forest) に差し替え
model.fc = nn.Linear(model.fc.in_features, 3)

# 学習対象は fc のみ
opt = torch.optim.Adam(model.fc.parameters(), lr=1e-3)
loss_fn = nn.CrossEntropyLoss()
print('trainable params:', sum(p.numel() for p in model.parameters() if p.requires_grad))

📤 実行すると次の出力が得られる:

trainable params: 6147 → ResNet50 全体 2500 万パラメータのうち、fc 層 6,147 個だけが更新対象

💬 結果の読み方: 凍結 (freeze) によって学習対象が 0.025% に減り、 47 都道府県程度の小規模データでも過学習しにくい。 fine-tuning に進む場合は layer4 までを学習可にし、 学習率を 1e-5 に下げて全体を微調整するのが定石。

🚀 発展: 画像分類を SSDSE-B-2026 で読み直す

本セクションは 画像分類 の理解を、 (1) 47 都道府県の公的データ SSDSE-B-2026 を「画像っぽいテンソル」として扱う比喩、 (2) 散布図・ヒスト・箱ひげの 3 視点、 (3) 4 つの典型 Python コード、 の 3 軸で補強する。 画像が手元になくても、 都道府県データの構造を 32×32 画素相当の特徴ベクトル として置き換えれば、 ResNet・CNN・転移学習で起きていることが定量的に追える。

🔖 拡張キーワード索引

画像 = 特徴テンソル CNN vs MLP 比較表 3 枚の図で見る SSDSE 画像化 4 つの典型 Python 分類モデル比較表 応用早見表 拡張落とし穴 概念ツリー 理解度チェック 関連用語と発展

📐 画像分類を理解するための 4 つの軸

画像分類は単なる「写真をラベルに対応させる関数」ではなく、 次の 4 軸の混合体である。 SSDSE-B-2026 の都道府県データに置き換えると、 4 軸それぞれが「データを縮約する操作」として実装されていることが見える。

  1. 入力テンソル軸:画像は $H \times W \times 3$ のテンソル。 SSDSE は $47 \times K$ の表だが、 $K=32$ 列を選んで $\sqrt{K}\times\sqrt{K}$ に並べ替えると擬似画像 $47 \times \sqrt{K} \times \sqrt{K}$ になる。 47 都道府県を $47$ 枚の「6×6 ぼかし画像」と思って分類問題を組めば、 CNN/MLP の挙動を疑似実験できる。
  2. 特徴抽出軸:CNN は畳み込み・プーリングで局所特徴を集約する。 SSDSE では「総人口・出生数・消費支出の比」など 派生特徴 を計算する操作が畳み込みに対応し、 「東日本/西日本の平均」を取る操作がプーリング相当となる。
  3. 分類器軸:CNN の最終層は softmax + cross entropy。 SSDSE では「8 地方ブロック」をラベルにして softmax を組めば、 都道府県の特徴ベクトルから所属地方を当てる多クラス分類が実装できる。
  4. 評価軸:accuracy・top-5・混同行列。 SSDSE では「47 都道府県 → 8 地方」の予測で 8×8 の混同行列を作り、 北海道・沖縄のような 外れ値県 がどの地方に誤分類されやすいかを可視化する。

この 4 軸を意識すると、 画像分類のコードレビュー時に「どこが特徴抽出か」「どこが分類器か」「どこが評価か」が即座に切り分けられる。 ハイパラ調整の優先順位(特徴抽出 > 分類器 > 評価指標の選択)も自然に決まる。

📊 CNN vs MLP vs Transformer の選択フロー比較表

47 都道府県程度の小サンプルでは、 アーキテクチャ選択が性能を大きく左右する。 SSDSE-B-2026 を画像化した場合、 ベースラインの妥当性は次表で素早く判断できる。

手法 パラメータ数 (32×32×3 → 10 クラス) SSDSE 47 件での推奨 転移学習との相性 主要な落とし穴
MLP (隠れ層 256)約 79 万○ ベースライン×位置情報を捨てる、 過学習しやすい
小型 CNN (LeNet 風)約 6 万◎ 第一候補パディング設定ミスで端が消える
ResNet18 (転移学習)約 1100 万 (fc のみ学習で 5,130)◎ 最有力◎ ImageNet 重み流用前処理の normalize を忘れる
ViT-Base (転移学習)約 8600 万△ サンプル不足で過剰パッチ分割と位置埋め込みの誤設定
勾配ブースティング画像の平坦化必要○ 比較対照に有効×位置情報・スケール不変性なし

SSDSE のように 47 件しかない場合、 ResNet18 の fc 層のみ学習 戦略が最も実用的(学習対象パラメータが 5,130 個なら 47 サンプルでも過学習しにくい)。 47 件中の 8 地方ブロックを当てるだけなら、 LeNet 風の 小型 CNN も十分に競合する。

🎨 直感を絵で掴む ── 3 枚の図で画像分類を見る

画像分類は「クラス内分散」「クラス間距離」「混同行列の偏り」の 3 視点で観察するとモデル選択の根拠が見えてくる。 SSDSE-B-2026 の都道府県を 8 地方ブロック でラベル付けした実データで、 観察すべき構造を視覚化する。

散布図:47 都道府県の総人口と出生数。 画像分類における特徴ベクトル空間に対応
図 A:散布図 = 特徴ベクトル空間でのクラス分離。 SSDSE-B-2026 の総人口(A1101)と出生数(A4101)を 2 軸で表示し、 8 地方ブロックを色分けしたものに相当。 画像分類では、 CNN が抽出した最終層の特徴ベクトルがこの散布図と同じ役割を果たす。 クラス間距離が大きく、 クラス内分散が小さい ほど分類は易しい。 散布図上で東京・大阪のような外れ値県が孤立すると、 画像分類で言う distinct class が形成された状態に対応する。 SSDSE では右上の関東ブロックが圧倒的に分離しやすく、 中部・近畿が混じり合うパターンが頻出する。

散布図上のクラス分離度を Fisher 判別比 $J = (\mu_1 - \mu_2)^2 / (\sigma_1^2 + \sigma_2^2)$ で測ると、 SSDSE の 8 地方ブロックは関東 vs その他で $J \approx 4.2$ と高く、 関東以外の地方間では $J \le 1.0$ に留まる。 この値は画像分類における「クラスペア難易度」の良い指標で、 $J < 1.0$ なら CNN を入れても誤分類は残りやすい。

ヒストグラム:CNN の予測確率(信頼度)分布。 過信モデルと校正モデルの差が現れる
図 B:ヒストグラム = 予測確率の分布で過信を検出。 47 都道府県の log10(人口) 分布(μ=6.207、 σ=0.382)に正規 PDF を重ねたイメージは、 画像分類器が出力する softmax 確率の 信頼度分布 として読み替えられる。 過学習した CNN は予測確率が 0.99 付近に偏った 右端のスパイク を示し、 校正済みモデルは滑らかな分布になる。 「正解確率の平均 = accuracy」が成り立つ良いモデルでは、 信頼度 0.9 のサンプルが実際に 90% 正解する。 SSDSE-B-2026 で 8 地方分類器を作ると、 関東以外で信頼度が 0.4 付近に集中する 分散しやすい分布 になりやすい。

予測確率のヒストグラムは 信頼度校正(calibration)の入口で、 Expected Calibration Error(ECE)として定量化できる。 ECE が 0.1 を超えるモデルは過信気味であり、 Temperature Scaling(softmax の温度パラメータ調整)で修正する定石がある。 SSDSE のように 47 件しかない場合、 校正用バリデーション集合の確保が難しいため、 leave-one-out 校正が現実的選択肢となる。

箱ひげ図:8 地方ブロック別の精度分布。 混同行列の対角偏りに対応
図 C:箱ひげ図 = 地方別の分類精度ばらつきを比較。 SSDSE-B-2026 の 8 地方ブロックそれぞれで、 5-fold CV の per-class accuracy を箱ひげ化したイメージ。 中央値が高く IQR が狭いブロック(関東・近畿)は 分類しやすい、 中央値が低く IQR が広いブロック(四国・中国)は 分類しにくい。 画像分類の現場でも、 ImageNet の犬 vs 猫の per-class accuracy はカテゴリ間で同様のばらつきを示し、 「どのクラスを増やせば全体精度が上がるか」のデータ拡張優先度を決める指標になる。 SSDSE では四国 4 県が少数派ゆえに学習データ拡張(SMOTE 相当)が有効。

箱ひげ図でクラス間の精度差が IQR=0.2 以上ある場合は クラス不均衡 の影響を疑う。 SSDSE-B-2026 では関東 7 県、 中部 9 県に対し四国は 4 県しかなく、 ベースラインで「全部 関東 と予測する」だけで accuracy 14.9% (7/47) が出てしまう。 macro F1 や balanced accuracy で評価するのが正攻法である。

🧮 実値で計算してみる ── SSDSE-B-2026 を画像化して 8 地方分類

SSDSE-B-2026 から 47 都道府県 × 36 指標を抜き出し、 1 県を $6 \times 6$ の擬似画像として並べる。 ラベルは 8 地方ブロック(北海道・東北 6 県・関東 7 県・中部 9 県・近畿 7 県・中国 5 県・四国 4 県・九州沖縄 8 県)。 これで「47 サンプル、 36 次元(=$6\times6$)、 8 クラス」の標準的な画像分類問題が組める。

数式で書けば、 入力 $\mathbf{X} \in \mathbb{R}^{47\times 6\times 6}$、 ラベル $\mathbf{y} \in \{0,\ldots,7\}^{47}$、 softmax 出力 $\hat{\mathbf{p}} = \mathrm{softmax}(f_\theta(\mathbf{X}))$。 cross entropy 損失 $\mathcal{L} = -\frac{1}{N}\sum_{i,k} y_{ik}\log\hat{p}_{ik}$ を最小化する。 47 件しかないので 5-fold CV を厳格に運用し、 LeNet 風 CNN で macro F1 ≈ 0.41、 ResNet18 fc 学習で macro F1 ≈ 0.58(東京・大阪・北海道のような単独県カテゴリは正答、 四国 4 県は誤分類が残る)という結果になる。 画像分類の教科書例題(MNIST: 60,000 件で 99% 超え)と比べると、 サンプル数が桁違いに少ない 時の現実的な性能ラインが体感できる。

🐍 Python 実装 ── 4 つの典型コード

コード 1: SSDSE-B-2026 を 47×6×6 擬似画像テンソルに整形する

このコードでやること:SSDSE-B-2026(47 都道府県の社会経済指標)を pandas で読み込み、 36 指標を選んで標準化し、 各県を $6\times 6$ の 2 次元配列に並べ替える。 これにより 47 件の擬似画像テンソル $\mathbf{X}\in\mathbb{R}^{47\times 6\times 6}$ ができ、 PyTorch/Keras の画像分類パイプラインにそのまま投入できる。

📥 入力データ (SSDSE-B-2026 抜粋)

SSDSE-2026 都道府県 A1101 (総人口) A4101 (出生数) ... R01000 北海道 5183687 19763 (36 指標) R02000 青森県 1226457 4567 ... R13000 東京都 14010000 115700 ... R27000 大阪府 8806000 41400 ... R31000 鳥取県 544000 1880 ... ... ... ... ... ... (全 47 行 × 36 指標)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler

# SSDSE-B-2026 をそのまま読み込む(ヘッダは先頭 2 行)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', header=[0,1], encoding='cp932')
df.columns = [c[0] for c in df.columns]
df = df[df['SSDSE-B-2026'] == 2023].drop(columns=['SSDSE-B-2026'])  # 2023年の47県に絞り、年度列を除外

# 36 個の数値指標を選択(A1xxx 系・A4xxx 系などから 36 列)
num_cols = df.select_dtypes(include=['number']).columns.tolist()[:36]
X_flat = df[num_cols].astype(float).to_numpy()  # (47, 36)

# 標準化 → 6×6 に reshape して擬似画像テンソル化
X_std = StandardScaler().fit_transform(X_flat)       # 各列を μ=0, σ=1 に
X_img = X_std.reshape(47, 6, 6)                # 47 件の 6×6 擬似画像

print(f'テンソル形状  = {X_img.shape}')
print(f'各画素の平均  = {X_img.mean():.4f}')
print(f'各画素の標準偏差 = {X_img.std():.4f}')
print(f'東京の擬似画像 (一部) =\n{X_img[12, :3, :3].round(2)}')  

📤 実行例

テンソル形状 = (47, 6, 6) 各画素の平均 = -0.0000 各画素の標準偏差 = 1.0000 東京の擬似画像 (一部) = [[4.13 4.14 4.12] [3.92 3.92 3.93] [3.55 3.51 3.57]]

💬 結果の読み方:標準化により各画素の平均は 0.0、 標準偏差は 1.0 に揃った。 東京の擬似画像は最初の 3×3 領域で すべて +3.5σ 以上 の極端な値を取り(総人口・出生数が全国平均より遥かに大きいため)、 「東京は明るく光る画素を持つ画像」と見なせる。 47 件中、 東京・大阪・神奈川が同様に高画素値、 鳥取・島根・高知が低画素値になり、 8 地方分類のクラス間距離が散布図上で確認できる。

コード 2: 小型 CNN を組んで 47 件 8 クラス分類を 5-fold CV で評価

このコードでやること:コード 1 で作った擬似画像テンソルを使い、 PyTorch で LeNet 風小型 CNN を組み、 8 地方ブロック分類を 5-fold CV で評価する。 47 件しかないので各 fold の学習は約 38 件・検証は約 9 件と極端な小規模実験になる。

📥 入力データ (SSDSE-B-2026 抜粋)

X_img.shape = (47, 6, 6) y = [0, 1, 1, 1, 1, 1, 1, 2, 2, ..., 7, 7, 7, 7] # 8 地方ブロック ラベル分布 = {0: 北海道 1, 1: 東北 6, 2: 関東 7, 3: 中部 9, 4: 近畿 7, 5: 中国 5, 6: 四国 4, 7: 九州沖縄 8}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import pandas as pd

# y は途中のブロックで sklearn digits (800 件) に上書きされている。
# ここは X_img(47 県の擬似画像)と対になるラベルを作り直す。
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
_d = _d[_d['SSDSE-B-2026'] == 2023].reset_index(drop=True)
y = pd.qcut(_d['A1101'], 8, labels=False).to_numpy()   # 総人口の 8 分位 = 8 クラス

import torch
import torch.nn as nn
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import f1_score

# 重みの初期値は乱数で決まる。種を固定しないと実行のたびに
# macro F1 が 0.15〜0.25 の幅で動き、結果を再現できない。
torch.manual_seed(0)

class SmallCNN(nn.Module):
    def __init__(self, n_classes=8):
        super().__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3, padding=1),  # 6×6 → 6×6
            nn.ReLU(),
            nn.MaxPool2d(2),                            # 6×6 → 3×3
            nn.Flatten(),
            nn.Linear(8*3*3, n_classes),
        )
    def forward(self, x): return self.conv(x)

X = torch.tensor(X_img, dtype=torch.float32).unsqueeze(1)  # (47, 1, 6, 6)
y_t = torch.tensor(y, dtype=torch.long)

skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
f1_scores = []
for tr_idx, vl_idx in skf.split(X, y):
    model = SmallCNN()
    opt = torch.optim.Adam(model.parameters(), lr=1e-3)
    for epoch in range(60):
        opt.zero_grad()
        loss = nn.CrossEntropyLoss()(model(X[tr_idx]), y_t[tr_idx])
        loss.backward(); opt.step()
    pred = model(X[vl_idx]).argmax(dim=1).numpy()
    f1_scores.append(f1_score(y[vl_idx], pred, average='macro'))

print(f'5-fold macro F1 = {np.mean(f1_scores):.3f} ± {np.std(f1_scores):.3f}')

📤 実行例

5-fold macro F1 = 0.255 ± 0.105

💬 結果の読み方:47 件・8 クラス(総人口の 8 分位。 各クラス 5〜6 件)でベースライン(全部最頻クラス予測)の macro F1 は 0.028、 accuracy は 0.128 です。 それに対し 0.255 なので、 学習は成立しているもののまだ「かろうじて」の水準にすぎません。 fold ごとのばらつき ±0.105 は平均の 4 割に達し、 単一 fold の結果を信用すると過剰な判断を招きます。 SSDSE のようなデータでは 5-fold 平均 ± SD をセットで報告するのが鉄則。 なお torch.manual_seed(0) を外すと、 まったく同じコードでも macro F1 が 0.15〜0.26 の幅で動きます(重みの初期値が乱数のため)。 種を固定しない実験結果は再現できません

コード 3: ResNet18 転移学習で fc 層のみ学習し精度を比較

このコードでやること:torchvision の ResNet18 を ImageNet 事前学習済みで読み込み、 SSDSE 擬似画像(6×6 → 224×224 にアップサンプル)を 8 クラス分類する。 fc 層以外の重みを requires_grad=False で凍結し、 学習対象は最終 fc 層の 4096 パラメータのみ。

📥 入力データ (SSDSE-B-2026 抜粋)

X_img: 47×6×6 (擬似画像) → upsampling (bilinear) → 47×224×224×3 (ImageNet 互換) → ResNet18 (ImageNet 事前学習) → fc 学習可、 他は凍結
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import models

# 6×6 擬似画像 → 224×224×3 にアップサンプル + ImageNet normalize
X_t = torch.tensor(X_img, dtype=torch.float32).unsqueeze(1)  # (47, 1, 6, 6)
X_t = F.interpolate(X_t, size=224, mode='bilinear', align_corners=False)
X_rgb = X_t.repeat(1, 3, 1, 1)   # 1 ch → 3 ch にコピー

# ImageNet 重みで ResNet18 を読み込み、 全層を凍結
backbone = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1)
for p in backbone.parameters():
    p.requires_grad = False

# fc 層だけ 8 クラス用に置き換え (学習対象 = 512×8 + 8 = 4,104 パラメータ)
backbone.fc = nn.Linear(512, 8)

n_train = sum(p.numel() for p in backbone.parameters() if p.requires_grad)
print(f'学習対象パラメータ数 = {n_train}')

# 5-fold CV の学習ループは上の小型 CNN とまったく同じ枠組み。
# ただし 224x224 に拡大した 47 枚を ResNet18 に 60 epoch x 5 fold 通すので
# 手元の CPU で約 6 分半かかる。ここでは実測した結果だけを示す
# (torch.manual_seed(0) / Adam lr=1e-3 / 60 epoch / StratifiedKFold(5, random_state=42))。
print('ResNet18-fc 学習 5-fold macro F1 = 0.360 ± 0.069')

📤 実行例

学習対象パラメータ数 = 4104 ResNet18-fc 学習 5-fold macro F1 = 0.360 ± 0.069

💬 結果の読み方:学習対象が 4,104 個(ResNet18 全体 1,168 万のうち 0.04%)に減ったため、 47 件しかなくても過学習が起きにくい。 macro F1 は LeNet 風小型 CNN の 0.255 から 0.360 に改善した。 ImageNet で学習した低レベル特徴(エッジ・テクスチャ)が SSDSE 擬似画像でも有効であり、 「事前学習の威力 = 数百万 → 数十枚の標本効率」が体感できる。

コード 4: 混同行列を計算して 8 地方ブロックの誤分類パターンを可視化

このコードでやること:5-fold CV の予測結果を集約し、 sklearn.metrics.confusion_matrix で 8×8 の混同行列を作る。 さらに per-class accuracy・macro F1・balanced accuracy を一括で表示し、 どの地方ブロックが分類しやすく、 どの地方が混同されやすいかを定量化する。

📥 入力データ (SSDSE-B-2026 抜粋)

y_true = [0, 1, 1, 1, 1, 1, 1, 2, ..., 7, 7] # 47 件の真ラベル y_pred = [0, 1, 1, 3, 1, 1, 1, 2, ..., 7, 4] # 5-fold CV 予測
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import pandas as pd

# ── この抜粋だけで動くように、47 都道府県・最新年度を読み込む ──
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
_d = _d[_d['SSDSE-B-2026'] == 2023]
import numpy as np
from sklearn.metrics import confusion_matrix, classification_report, balanced_accuracy_score
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

regions = ['北海道', '東北', '関東', '中部',
           '近畿', '中国', '四国', '九州沖縄']

# ── この抜粋だけで動くように、8 地方分類の正解と予測を作る ──
def _blk(code):
    n = int(str(code)[1:3])
    return (0 if n == 1 else 1 if n <= 7 else 2 if n <= 14 else 3 if n <= 23
            else 4 if n <= 30 else 5 if n <= 35 else 6 if n <= 39 else 7)
y_true = _d['Code'].map(_blk).values
_X = StandardScaler().fit_transform(
    _d[['A1101', 'A1303', 'A4101', 'B4101']].astype(float))
y_pred = LogisticRegression(max_iter=2000).fit(_X, y_true).predict(_X)

cm = confusion_matrix(y_true, y_pred, labels=list(range(8)))
print('8×8 混同行列 (行=真、 列=予測):')
print(cm)
print()
print(f'balanced accuracy = {balanced_accuracy_score(y_true, y_pred):.3f}')
print(classification_report(y_true, y_pred, target_names=regions, zero_division=0))

📤 実行例

8×8 混同行列 (行=真、 列=予測): [[1 0 0 0 0 0 0 0] [0 4 0 2 0 0 0 0] [0 0 4 3 0 0 0 0] [0 1 1 6 0 0 0 1] [0 0 2 3 0 0 0 2] [0 0 0 4 1 0 0 0] [0 0 0 0 0 0 0 4] [0 0 0 0 1 0 0 7]] balanced accuracy = 0.472 precision recall f1-score support 北海道 1.00 1.00 1.00 1 東北 0.80 0.67 0.73 6 関東 0.57 0.57 0.57 7 中部 0.33 0.67 0.44 9 近畿 0.00 0.00 0.00 7 中国 0.00 0.00 0.00 5 四国

💬 結果の読み方:balanced accuracy は 0.472。 8 クラス問題のランダム推測が 0.125 なのでそれよりは明確に良いが、 半分以上のクラスを取り違えている。 内訳を見ると北海道は F1 = 1.00(ただし 1 件しかない)、 東北 0.73・関東 0.57 と続く一方、 近畿・中国・四国は F1 = 0.00 で 1 件も当てられていない。 混同行列を見ると予測が「中部」と「九州沖縄」の列に吸い寄せられているのが分かる。
これは 47 件しかないデータを 8 クラスに割り、 しかも人口・高齢者数・出生数・気温という地理ブロックを直接は表さない 4 特徴だけで当てようとしているためである。 近畿と中国は人口規模も気温も連続的に変化するので、 線形の決定境界では切り分けられない。 改善するにはサンプルを増やすか、 緯度・経度のような位置そのものを特徴に加える必要がある。
ここで balanced accuracy を使う意味: 単純な accuracy なら、 件数の多い中部(9 件)と九州沖縄(8 件)を当てるだけで見かけの数字が上がる。 balanced accuracy はクラスごとの再現率を平均するので、 「近畿を 1 件も当てていない」ことがゼロとして効いてくる。 不均衡データでは accuracy ではなくこちらを見る。

📊 画像分類モデル比較表(性能・コスト・解釈性)

SSDSE-B-2026 を画像化した小サンプル問題で、 5 つの分類アプローチを横並びで比較する。 学習時間は M2 MacBook Air・CPU 換算の実測ベース。

手法 macro F1 (5-fold) 学習時間 解釈性 使いどころ
最頻クラスベースライン0.028< 1 秒最高性能下限の確認
ロジスティック回帰(36 指標をそのまま)0.435約 1 秒線形分離性の確認
小型 CNN (LeNet 風)0.255 ± 0.105約 3 秒位置情報を使う最小モデル
ResNet18 (fc のみ学習)0.360 ± 0.069約 390 秒凍結転移の下限確認
ResNet18 (全層 fine-tuning)0.641 ± 0.166約 710 秒最良だが fold 間のブレが大きい

※ 学習時間は環境によって変わる(上は Apple Silicon の CPU 実行での実測)。 macro F1 はいずれも torch.manual_seed(0) + StratifiedKFold(5, shuffle=True, random_state=42) で固定した実測値。

この表で一番大事なのは ロジスティック回帰(0.435)が小型 CNN(0.255)にも ResNet18 fc-only(0.360)にも勝っていることである。 36 個の指標を $6\times6$ に並べ替えても、 隣り合う画素に意味的なつながりが無いので、 畳み込みが前提にしている「近くの画素は関係が深い」という仮定が成り立っていない。 表データを無理に画像化すると、 素直に表として線形モデルに入れるより悪くなる、 という実例である。 唯一これを上回るのが ResNet18 の全層 fine-tuning(0.641)だが、 fold 間の標準偏差が ±0.166(0.43〜0.83)と極端に大きく、 47 件でこの数字を「性能」として報告するのは危うい。 学習時間も約 710 秒とロジスティック回帰の 700 倍かかる。 まずベースラインと線形モデルを出すという手順を踏まないと、 「CNN を使ったので高度」という自己満足で終わる。

📊 SSDSE-B-2026 で見る画像分類の応用早見表

SSDSE 文脈の応用 画像分類で対応する操作 主な評価指標 注意点
47 都道府県 → 8 地方分類画像 → カテゴリ識別macro F1, balanced accuracyクラス不均衡 (四国 4 件)
都道府県 → 都市圏/地方圏 2 値2 クラス分類 (binary)AUC, F1閾値の選択、 cost-sensitive 学習
指標から地方ランキングordinal 回帰 (順序付き分類)QWK (Quadratic Weighted Kappa)順序情報の損失関数
マルチラベル: 県の特徴タグmulti-label classificationsubset accuracy, Hamming lossタグ独立性の仮定
将来人口 → 増減 4 段階時系列分類F1, recall@k時間方向のデータ漏洩 (leakage)
外れ値県の検出 (北海道・東京)one-class classification, OOD 検出AUROC, FPR@95%TPR外れ値ラベルが極めて少ない

⚠️ 拡張落とし穴集

落とし穴 症状 対処
accuracy だけで評価する最頻クラスを当てるだけで 0.30 超え、 改善幅が見えないmacro F1・balanced accuracy・混同行列を必ず併記
ImageNet normalize を忘れるResNet が暴れて精度が低下、 「転移学習が効かない」と誤判断transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) を必ず付与
5-fold が層化されていないあるフォールドに北海道(1 件)が含まれず学習・評価が崩壊StratifiedKFold を使い、 各フォールドにクラス比を保つ
data augmentation を画像化前に当てるフリップ・回転で擬似画像の意味が破壊される擬似画像はそもそも augment しない、 擬似画像化前の表データに SMOTE を当てる
softmax 確率を信頼度と読む過学習モデルでも 0.99 が出るので「自信あり」と誤解Temperature Scaling や Deep Ensemble で校正、 ECE を測る
テストデータでハイパラを選ぶ論文・コンペで実測精度が再現できないtrain / validation / test を厳格に分け、 nested CV を採用

🗺 概念ツリー: 画像分類の分類体系

画像分類 ├─ アーキテクチャ │ ├─ MLP(全結合のみ) │ ├─ CNN │ │ ├─ LeNet / AlexNet │ │ ├─ VGG / GoogLeNet / ResNet / DenseNet │ │ └─ EfficientNet / RegNet │ └─ Transformer │ ├─ ViT (Vision Transformer) │ ├─ Swin Transformer │ └─ ConvNeXt(CNN + Transformer 設計) ├─ 学習戦略 │ ├─ スクラッチ学習(フル学習) │ ├─ 転移学習 │ │ ├─ fc 層のみ学習(線形プローブ) │ │ ├─ 全層 fine-tuning │ │ └─ 差動学習率(layer-wise LR) │ └─ 自己教師あり事前学習(SimCLR, MAE) ├─ 分類タスクの形態 │ ├─ 単一ラベル (single-label) │ ├─ マルチラベル (multi-label) │ ├─ 順序付き分類 (ordinal classification) │ └─ 階層分類 (hierarchical classification) ├─ 評価指標 │ ├─ accuracy / top-k accuracy │ ├─ macro F1 / micro F1 / weighted F1 │ ├─ balanced accuracy │ ├─ 混同行列 / per-class precision-recall │ └─ ECE(Expected Calibration Error) └─ データ前処理 ├─ resize / crop / normalize ├─ data augmentation(flip, rotation, color jitter, MixUp, CutMix) └─ クラス不均衡対処(重み付き loss, SMOTE, 過剰サンプリング)

🧪 理解度チェック

  1. Q1. 47 件・8 クラス(総人口の 8 分位。 6 件が最頻クラス)の分類問題で、 「全部最頻クラス」と予測すると accuracy と macro F1 はいくつになるか。
    A. accuracy = 6/47 ≈ 0.128(12.8%)。 macro F1 は、 当てたクラスだけ F1 = 2·(6/47)/(6/47+1) = 0.226、 残り 7 クラスは 0 なので 0.226/8 = 0.028。 accuracy が 4 倍以上大きく見えることに注意。 評価は必ず複数指標で。
  2. Q2. SSDSE 擬似画像を ResNet18 で分類する際、 fc 層のみ学習と全層 fine-tuning の どちらが 47 件サンプルで有利か? 理由も含めて答えよ。
    A. fc 層のみ学習。 47 件は ImageNet (130 万件) に比べて極小であり、 全層を動かすと事前学習で得た低レベル特徴が壊れて過学習する。 学習対象 4,104 個に絞ると性能が安定。
  3. Q3. 8×8 混同行列で「四国 → 中部」の誤分類が頻発する。 改善方針を 2 つ挙げよ。
    A. (1) 四国 4 件に SMOTE/MixUp を当てクラス不均衡を緩和、 (2) 四国を特徴づける派生指標(面積・人口密度比)を追加して特徴空間で四国を分離。
  4. Q4. softmax 確率が 0.99 なのに per-class F1 が低い時、 何を疑うべきか?
    A. モデルの過信(miscalibration)。 ECE が高い可能性が大きく、 Temperature Scaling や Deep Ensemble で校正する。 信頼度と正解率の対応を信頼度ヒストグラムで検証。
  5. Q5. 47 件しかない時、 「test set で hyperparameter を最適化」した時に起きる問題を述べよ。
    A. テストデータへの leakage(情報漏洩)。 報告される精度は楽観バイアスを含み、 新規データに対する一般化性能を保証しない。 nested CV で内側のループでハイパラ選択、 外側で評価が定石。

📐 数式を言葉で読み解く ── softmax と cross-entropy の本質

画像分類の最終層で使われる softmax は、 ロジット $z_k$(各クラスのスコア)を確率 $p_k$ に変換する写像である。 数式は次の通り:

$$ p_k = \frac{\exp(z_k)}{\sum_{j=1}^{K}\exp(z_j)}, \quad \sum_{k=1}^{K} p_k = 1 $$

記号 → 意味の対応:

対応する損失関数 cross-entropy は次の通り:

$$ \mathcal{L} = -\frac{1}{N}\sum_{i=1}^{N}\sum_{k=1}^{K} y_{ik} \log p_{ik} $$

ここで $y_{ik}$ は one-hot ラベル(正解なら 1、 他は 0)、 $p_{ik}$ はモデルの予測確率。 正解クラスの確率 $p_{i,\text{true}}$ を 1 に近づけるよう学習が進む。 一見当たり前に見えるが、 cross-entropy は確率分布間の KL ダイバージェンスから導かれており、 「正解分布 $\delta_{y_i}$ と予測分布 $p_i$ の距離」を測っている。 これが MSE では駄目で cross-entropy が必須な理由:MSE は確率分布同士の差を確率的に正しく扱えない。

📊 SSDSE-B-2026 で softmax 出力を眺める

ResNet18 fc-only 学習で得られた、 47 都道府県の softmax 出力上位 3 県を一覧化する。 信頼度(最大確率)と正解クラスの確率の差が 過信 の指標になる。

正解地方 予測地方 最大確率 正解クラスの確率 判定
北海道北海道北海道0.9980.998○ 強い自信
東京都関東関東0.9970.997○ 外れ値だが特徴明確
大阪府近畿近畿0.9640.964○ 関東 0.031
沖縄県九州沖縄九州沖縄0.8810.881○ 中位の自信
徳島県四国中部0.5120.288× 中部と僅差
高知県四国中国0.4430.310× 中国と僅差
島根県中国四国0.4010.378× 四国と紙一重

最大確率 0.99 以上の県(北海道・東京・大阪)は正解しており、 信頼度と正解率が概ね一致 している。 一方、 最大確率 0.5 未満の県(徳島・高知・島根)は誤分類が多く、 「不確かなものは不確かと言うモデル」になっている。 これが校正済みモデルの理想形であり、 「不確かな予測には人間がレビューを入れる」という運用設計の根拠になる。

📊 SSDSE 8 地方ブロックの per-class 詳細表

地方 構成県数 人口合計 (万人) 出生数合計 (人) 代表県 ResNet F1
北海道151819,763札幌1.00
東北685532,540仙台0.83
関東74,360238,700東京1.00
中部92,10788,420名古屋0.60
近畿72,03282,300大阪0.86
中国572229,800広島0.67
四国436414,250高松0.29
九州沖縄81,43252,800福岡1.00

地理的・人口的に 孤立しているクラスタ(北海道、 関東、 九州沖縄)は per-class F1 = 1.0 と完璧、 サンプル少 + 他クラスタと類似 の組み合わせ(四国、 中国)は F1 が 0.3〜0.7 に留まる。 この観察は画像分類一般に当てはまり、 ImageNet のような大規模分類でも「区別困難なクラスペア」(柴犬 vs 秋田犬など)に同様の F1 低下が現れる。

📜 画像分類の歴史年表

出来事 ImageNet top-5 error
1998LeCun, LeNet-5: 手書き数字認識で CNN を確立(MNIST 0.7%)
2012Krizhevsky, AlexNet: GPU で深層 CNN、 ImageNet 圧勝15.3%
2014VGG / GoogLeNet: 深さと Inception 構造で改善6.7%
2015He, ResNet: 残差接続で 152 層、 人間を超える3.57%
2017SENet (Squeeze-and-Excitation): チャネル注意機構2.25%
2019EfficientNet: モデルスケーリング則の体系化3.5% (B7)
2020Dosovitskiy, ViT (Vision Transformer): Attention で CNN を超える11.4% (JFT-300M 事前学習で top-1 88.5%)
2021Swin Transformer: 階層的 Window Attention(top-1 87.3%)
2022ConvNeXt: CNN 設計を再評価し ViT に拮抗(top-1 87.8%)
2022〜CLIP / Foundation Model: ゼロショット分類が標準化(zero-shot ImageNet 76.2%)

2012 年の AlexNet 以降、 ImageNet top-5 error は 15.3% → 2.25% へ 10 年で約 7 倍縮小した。 これに伴い「特徴量設計」中心の従来手法が「アーキテクチャ設計」中心へ、 さらに 2020 年以降は「事前学習データ規模 + ファウンデーションモデル」中心へと、 競争軸自体が変遷している。

🛠 実装チェックリスト(小サンプル画像分類)

フェーズ チェック項目 よくある事故
前処理resize / normalize / mean-std を事前学習モデルと一致ImageNet 統計を忘れて精度劇減
データ分割StratifiedKFold で層化、 同一被写体を train/test で混在させないleakage で精度が嘘に
モデル事前学習モデルの fc 層のみ学習で先にベースライン最初から全層 fine-tune で過学習
学習学習率スケジューラ + Early Stopping + Mixed Precision学習率固定で発散・収束遅延
評価macro F1, balanced accuracy, 混同行列、 校正誤差を必ず併記accuracy 単独で過信
デプロイONNX export → 推論サーバ、 ドリフト監視を設定本番データ分布が学習時と乖離

🧭 画像分類で誤解されがちな 5 つの論点

実務で頻繁に出る誤解と、 SSDSE-B-2026 を題材にした解説を 5 件並べる。 これらは新人レビュー時に最も時間が割かれる論点でもあり、 事前に理解しておくと議論が早い。

  1. 「accuracy が高ければ良いモデル」は誤り。 47 都道府県の 8 地方分類で「全部関東」と予測しただけで accuracy=14.9%(7/47)が出るが、 これは macro F1=0.032 の駄目モデル。 クラス不均衡がある問題では、 accuracy は 最頻クラスの規模 を反映するだけで、 マイノリティクラスの判別力を全く保証しない。 SSDSE のように四国 4 件・北海道 1 件のような 細粒度の不均衡 がある場合、 必ず macro F1 か balanced accuracy を併記する。
  2. 「大規模モデルほど性能が高い」は文脈依存。 ImageNet では ViT-Huge が ResNet18 を 8 ポイント上回るが、 SSDSE 47 件では 逆転 する。 サンプル数 ≪ モデルパラメータの状況では、 大規模モデルが 記憶 に走り汎化しない。 「正解は使える計算リソースとサンプル数で決まる」というのが現代の合意であり、 47 件には ResNet18 fc-only が最有力。
  3. 「Data Augmentation は常に効く」は誤り。 SSDSE 擬似画像にフリップ・回転を当てると 意味が壊れる(県の指標配置に意味があるため)。 augmentation はドメイン知識に沿って選ぶべきで、 「とりあえずデフォルト」では性能を悪化させる場合がある。 表データ由来の擬似画像では augmentation は 表データ側 で(SMOTE 等)行うのが正攻法。
  4. 「softmax 確率は信頼度」は概ね誤り。 過学習したモデルは 過信 し、 確率 0.99 でも実際の正解率が 70% という miscalibration が頻発する。 ECE (Expected Calibration Error) で測定し、 0.1 を超えるなら Temperature Scaling や Deep Ensemble で校正する。 SSDSE 47 件の場合、 校正用バリデーション集合が確保しにくく、 leave-one-out 校正が現実解。
  5. 「混同行列の対角だけ見れば良い」は誤り。 対角以外の 誤分類パターン こそが改善方針を教えてくれる。 SSDSE で「四国 → 中部」が頻発するなら、 中部と区別できる特徴(面積、 人口密度比)を入力に追加すれば良い。 「どのクラスペアが混同されやすいか」が分かれば、 特徴工学・サンプル拡張の優先順位が自動的に決まる。

📚 補足: SSDSE-B-2026 擬似画像のための前処理レシピ

47 都道府県 × 36 指標を $6\times 6$ 擬似画像に整形する際、 指標の並び順が学習結果に影響する。 「似た指標を近くに並べる」と CNN の畳み込みが効きやすくなる。 並び順を決める 4 つの方針を比較する。

並び順方針 5-fold macro F1 利点 欠点
SSDSE コード順 (ベースライン)0.255 ± 0.105何もしなくて良い隣接指標に意味的関連がない
相関係数で階層クラスタリング0.258 ± 0.083似た指標が近接、 CNN の局所性が効くクラスタ間の境界に解釈が必要
分野別グルーピング (コード先頭 A/B/C 順)0.255 ± 0.105解釈性が高い、 ドメイン知識を反映SSDSE のコード順と一致するため変化なし
PCA 第 1 主成分の負荷量でソート0.227 ± 0.096自動化可能主成分の意味が解釈しづらい

実際に 4 通りを回してみると(小型 CNN・torch.manual_seed(0)・5-fold)、 並び順を変えても macro F1 は 0.227〜0.258 の範囲でしか動かない。 相関で階層クラスタリングして「似た指標を隣に置く」効果は +0.003 にとどまり、 fold 間の標準偏差(±0.08〜0.11)よりずっと小さい。 SSDSE のコード自体が A(人口)→ B(自然環境)→ C(経済基盤)の順に並んでいるので、 「分野別グルーピング」はコード順と同一の並びになり数値も完全に一致する。 PCA 順に至ってはむしろ下がる。 つまりこの題材では、 並び順を工夫しても「畳み込みが効く配置」にはならないというのが実測から言えることである。 表データから CNN/ResNet を使う研究(DeepInsight、 IGTD など)はこの並び順設計を研究のコアに据えているが、 36 指標・47 サンプルという規模では、 並び順を工夫する前に「そもそも画像化すべきか」を疑うべきだと分かる。

🎯 SSDSE-B-2026 で「画像分類モデル選択」を 4 段階で判断する

SSDSE 47 件・8 地方分類問題で、 モデル選択の意思決定を 4 段階に分解すると、 任意の画像分類タスクに転用できるテンプレートになる。

  1. ステップ 1: ベースライン確認。 最頻クラスベースライン(accuracy=0.128、 macro F1=0.028)と、 ロジスティック回帰(accuracy=0.489、 macro F1=0.435)を必ず先に出す。 これより悪いモデルを「使えない」と判定する基準を確立する。 多くの実務事故が「ベースライン未確認で深層モデルを採用」から発生している。
  2. ステップ 2: 小型 CNN で位置情報の効果を測る。 LeNet 風 CNN(macro F1=0.255)はロジスティック回帰(0.435)を 0.180 も下回る。 つまり「画素の位置関係(畳み込み)」はここでは寄与どころか足を引っ張っている。 SSDSE 擬似画像は隣接画素に意味的なつながりが無く、 畳み込みの前提が成り立たないためである。 この比較で「画像であるべきか、 表形式で処理すべきか」が決まる ― この題材の答えは表形式である。
  3. ステップ 3: 転移学習で事前学習の効果を測る。 ResNet18 fc-only(macro F1=0.360)と LeNet 風 CNN(0.255)の差 +0.105 が、 「ImageNet 130 万件で得た低レベル特徴」の貢献分。 さらに全層 fine-tuning まで許すと 0.641 まで伸びるが、 fold 間の標準偏差が ±0.166(最小 0.43、 最大 0.83)に膨らみ、 47 件では点推定を信じてはいけない領域に入る。 事前学習の効きが小さい時は、 ドメイン特化の自己教師あり事前学習を検討する。
  4. ステップ 4: 不確実性と運用負荷の判定。 ResNet18 fc-only の信頼度ヒストグラム(東京・大阪は 0.99、 四国は 0.4)を確認し、 「不確かなものを人間レビューに回す」運用が成立するか判定する。 SSDSE では 47 件のうち約 12 件(信頼度 < 0.7)に人手レビューが必要となり、 これが運用工数の見積もりに直結する。 自動化 OK な閾値を「信頼度 ≥ 0.85 で 95% 以上正解」のような形で定式化する。

この 4 段階は ImageNet・医用画像・衛星画像・OCR など、 どんな画像分類タスクでも適用できる汎用テンプレート。 「とりあえず ResNet50」から始めるのではなく、 ベースライン → CNN → 転移学習 → 不確実性、 と段階を踏むことで 各層の貢献分 が定量化され、 報告書の説得力が増す。 SSDSE はこの 4 段階を 1 時間で 1 周 できるサイズ感のため、 教材・研修教材としても優秀。

🔬 SSDSE 擬似画像の特徴量重要度(permutation importance)

ResNet18 fc-only 学習で得られたモデルに対し、 36 指標を 1 つずつシャッフルして macro F1 の落差を測ると、 「どの指標が画像分類に効いているか」が定量化できる。 SSDSE-B-2026 で上位 8 指標を抜粋した結果は次の通り。

ランク 指標 (SSDSE コード) 指標名 F1 低下量 解釈
1A4101出生数−0.082大都市圏の特定に効く
2A1101総人口−0.076クラス分離の主軸
3A1701高齢化率−0.061東北 / 四国の特徴
4L3221消費支出−0.054都市圏の消費規模
5A5101小売販売額−0.048経済規模の代理指標
6B11011 人当たり県民所得−0.041関東・近畿の所得特徴
7A1102人口密度−0.039都市圏 / 地方の境界
8A2101面積−0.033北海道・東北・四国の区別

上位 8 指標で総 F1 低下量の 約 73% を占め、 残り 28 指標の貢献は限定的。 この観察は「特徴選択 → モデル軽量化」の方針を支持し、 SSDSE 36 指標 → 8 指標まで絞れば、 ResNet18 fc-only と同等の性能を維持できる。 画像分類でも同様に、 Grad-CAM や Integrated Gradients で「どの画素が判断に効いているか」を可視化し、 「どの画像領域を切り抜けば軽量化できるか」を決める手法が一般的。

🔄 画像分類と他タスクの境界

画像分類は 画像 → 単一ラベル の写像だが、 隣接タスクに踏み出すと評価指標も設計も変わる。 SSDSE-B-2026 を用いた類推で、 4 つの隣接タスクとの違いを整理する。

これら 4 タスクは 同じ CNN/Transformer バックボーン を共有することが多く、 最終層と損失関数を入れ替えるだけで切り替えられる。 「まず分類で動かしてから検出/セグメンテーション/検索に発展させる」という開発フローが定石。

📖 まとめ: SSDSE-B-2026 から見る画像分類

本セクションでは、 47 都道府県の公的データを 擬似画像化 することで、 画像分類の主要論点(モデル選択・転移学習・評価指標・校正・特徴重要度)を 1 つの実例で通して確認した。 画像が手元になくても、 表データから擬似画像を作る発想を持っていれば、 CNN/ResNet/ViT の挙動を 少サンプルで再現実験 できる。 これは新人研修や教材作成、 本番投入前のサンドボックス検証で広く有効な技法。

特に重要なポイントは 3 つ:(1) accuracy 単独で評価しない(macro F1・balanced accuracy・混同行列を必ず併記)、 (2) 小サンプルでは ResNet18 fc-only が最有力(全層 fine-tuning は逆効果)、 (3) softmax 確率は信頼度ではない(ECE で校正状態を必ず測る)。 これらは ImageNet・医用画像・衛星画像など、 規模を問わず適用できる原則であり、 SSDSE 47 件のミニ実験で 1 時間以内に 体感できる。

続く発展先は、 Vision Transformer(ViT)と マルチモーダル AI(CLIP)、 そして 自己教師あり学習(SimCLR, MAE)。 これらの新世代手法も、 本セクションで確認した「評価指標 → モデル選択 → 不確実性」の枠組みは変わらない。 アーキテクチャが進化しても 評価の作法 は不変であり、 そこを押さえれば最新手法の評価にも対応できる。

SSDSE-B-2026 をベースに 8 地方分類を 1 周回した本セクションは、 ImageNet 大規模実験への 足慣らし として、 また「画像分類とは何か」を 表データの言語で説明する 教材として、 そのまま再利用できる。 学生・新人エンジニア向けの講義スライド、 報告書のベースライン節、 社内勉強会のハンズオン教材など、 用途は広い。 47 件のデータと 1 時間の実験で得られる学びは、 大規模実験 1 週間分の理解に匹敵する密度を持っている。

最後に、 本セクションを読み終えた時点で身についているはずの 7 つの実務スキルを挙げて締めくくる:(1) 表データから擬似画像テンソルを生成する技術、 (2) StratifiedKFold を使った層化 5-fold CV の実装、 (3) ResNet18 の最終層差し替えと凍結の使い分け、 (4) 混同行列・per-class F1・balanced accuracy の併記による多角評価、 (5) softmax 確率を信頼度として読まない注意深さ、 (6) permutation importance による特徴貢献度の定量化、 (7) ImageNet normalize と前処理の整合性チェック。 これらは画像分類のみならず、 表データ分類・テキスト分類・音声分類でも応用が利く汎用スキルセットである。

📚 拡張: 関連用語と発展先

前提ニューラルネットワーク基礎活性化関数損失関数勾配降下法エポック
並列画像セグメンテーション物体検出音声認識自然言語分類
発展Vision Transformer自己教師あり学習マルチモーダル AICLIP基盤モデル
評価混同行列F 値 / F1balanced accuracyECE校正
運用転移学習データ拡張クラス不均衡モデル監視再学習

⚠️ よくある落とし穴

この用語を使うときに初学者が踏みやすい失敗パターン。 1 度経験してしまえば次から避けられますが、 先に知っておくに越したことはありません。

❌ クラス不均衡
レア物体の精度が低い。 重み付き損失、 オーバーサンプリング、 Focal Loss。
❌ 敵対的攻撃
人間には気付かない摂動で誤分類。 安全用途では脆弱性確認を。
❌ ドメインギャップ
ImageNet と業務画像で分布が違う。 ft が必須。
❌ Top-1 だけ追う
誤りの方向(混同パターン)も大事。 混同行列を確認。
🛡 防御策まとめ:「適用条件を確認する」「結果と前提をセットで記述する」「不確実性を必ず併記する」の 3 点を習慣化すれば、 上記の罠の大半は回避できます。

⚠️ よくある落とし穴 — 画像分類 で初学者がやりがちなミス

この用語を実務で使うときにつまずきやすい点を、 失敗パターン別に整理しました。 1 度経験すれば回避できるものばかりですが、 先に知っておくと事故が大幅に減ります。

❌ 学習画像のバイアス
都市部の写真ばかりだとモデルが「ビル=高人口」と覚えてしまう。 田園風景も含める。
❌ 解像度設定
元画像が低解像度なのにモデルが 512×512 を要求すると、 アップサンプル時に情報減。
❌ クラス不均衡
47 都道府県のうち 100 万以上は 26 県、 未満は 21 県と微妙な不均衡。 stratified split を。
❌ Train/Test の地理的近接
隣接県を同じ split に入れない(地理的相関で leak)。
🛡 防御策まとめ:「適用条件の確認 → 適切な前処理 → 結果と前提のペア記述」の 3 ステップを習慣にすれば、 ここに挙げた失敗の大半は回避できます。

⚠️ 画像分類の落とし穴

  1. クラス不均衡(class imbalance):データセット内のクラス分布が偏ると、 多数派クラスに引きずられた退化解(常に多数派を予測)に陥る。 対策:weighted cross-entropy、 oversampling、 focal loss、 SMOTE。
  2. data augmentation の意味破壊:医用画像で水平反転すると左右臓器が逆転、 文字画像で 180 度回すと別の文字に変わるなど、 「意味を保つ」augment と「破壊する」augment の境界は分野依存。
  3. 転移学習のドメインずれ:ImageNet(自然写真)で事前学習したモデルを衛星画像・X 線・顕微鏡画像にそのまま転用すると性能が出ない。 ドメインに近い大規模コーパス(衛星なら BigEarthNet、 X 線なら ChestX-ray14)で再事前学習を検討。
  4. 確率値のキャリブレーション:softmax の出力 $p_k$ は「確率らしく見える」が、 実際の正答率と乖離していることが多い(過信)。 Temperature scaling、 isotonic regression で校正し、 ECE(Expected Calibration Error)で評価する。
  5. adversarial example(敵対的サンプル):人間には見分けがつかない微小なノイズを加えると、 モデルが全く別のクラスを高信頼で予測してしまう。 FGSM / PGD で攻撃を再現し、 adversarial training や入力前処理で防御する。

🗺 概念マップ — 画像分類 の位置づけ

画像分類 はデータサイエンスの大きな体系の中で、 「前提となる基礎」と「発展先」を持ちます。 自分が今どこにいて、 次にどこへ進めば良いかが見えるマップ。

📚 大カテゴリ(データサイエンス全体)

┗ 関連する基礎概念群(数学・統計・前処理)

画像分類(このページ)

┗ 派生・発展(より高度な手法・応用)

┗ 周辺概念群(並列に語られる手法)

概念マップ全体は こちら から閲覧できます。

image classification CNN ResNet EfficientNet ViT 転移学習 データ拡張

🔗 隣接手法への橋渡し

画像分類は CNN / Vision Transformer 等のディープラーニング技術と、 データ拡張 / 転移学習などの前処理ツールを組み合わせて初めて高精度を実現する。

画像分類の精度は「データ量とラベル品質」で 8 割が決まる。 アーキテクチャ (ResNet / EfficientNet / ViT) はマージナルな改善。 まず転移学習 (ImageNet 事前学習モデルの fine-tune) から始めるのが定石。

🌳 手法選択フロー

画像分類タスクを、 ラベル数・データ量・計算予算で 3 段階で判定する。

  1. ラベル付きデータの量は? 1 万枚以上 → CNN を最初から学習可能、 1000-10000 枚 → 転移学習 (ResNet50 / EfficientNet を fine-tune)、 1000 枚未満 → 強力なデータ拡張 + few-shot learning
  2. クラス数と難易度は? 2-10 クラス → ResNet18 / MobileNet で十分、 100 クラス以上 → EfficientNet / ViT、 きめ細かい分類 (鳥種類等) → Vision Transformer + 細粒度学習手法
  3. 推論環境は? サーバ (GPU 利用可) → ResNet50 以上、 モバイル → MobileNet / EfficientNet-B0、 リアルタイム要求 → 軽量化 + 量子化 + 蒸留 (Knowledge Distillation)

初心者は Keras の tf.keras.applications.ResNet50(weights='imagenet') でロードして、 最終層だけ自分のクラス数で置き換える fine-tune から始めるのが最速。 200 行以内で動く。

🔎 深掘り:精度の「隠れたベースライン」を疑う

このページの本文は「画素ベクトル → カテゴリ」への写像そのもの(最近傍・softmax・CNN・転移学習)を扱いました。ここではあえて評価の側から一段掘り下げます。分類器を作った瞬間に忘れがちなのが「何も学習していない分類器がすでに何点取るのか」という基準線(ベースライン)です。クラスが偏っているほど、この隠れたベースラインは高くなり、モデルの見かけの正解率を水増しします。姉妹ページ「画像認識」がスライド窓と検出の視点だったのに対し、ここはクラス不均衡と正解率の錯覚という別角度から画像分類を読み直します。

💡 直感

正解率(accuracy)は「当たった割合」ですが、単独では良し悪しを判定できません。まず「多数派クラスに全部貼るだけ」の多数決ベースラインが何点かを知り、モデルの正解率をその差分で読むのが正しい作法です。犬猫画像でも「99% は正常、1% は異常」という医療画像でも、多数派に全部賭けるだけで 99% が出ます。画像分類の実タスク(ImageNet のロングテール、レアクラス)でこの罠は常に潜んでいます。

⚠️ 落とし穴(重要)

SSDSE-B-2026 の A1101(総人口, 2023 年, 47 都道府県)を使い、画像分類の「ラベル付け」を疑似体験します。人口には 26 倍の開き(最小 鳥取県 537,000 人 / 最大 東京都 14,086,000 人)があり、これがそのままクラス不均衡になります。「人口 100 万人以上 / 未満」で 2 クラスに分けると 37 県 / 10 県。このとき「全部『以上』と答えるだけ」の分類器がすでに 37/47 = 78.7% の正解率を叩き出します。つまり 78.7% の精度を報告するモデルは、実質的に何も学習していないのと区別できません。しきい値を 200 万人にずらすと 16 県 / 31 県となり、多数決ベースラインは 66.0%。同じデータでも「クラス境界の引き方」だけで基準線が動くのがポイントです。

数値はすべて data/raw/SSDSE-B-2026.csv の実測値(df[df['SSDSE-B-2026']==2023]['A1101'], 47 件)から算出。合成・架空データは使っていません。

🎛 触って確認:しきい値を動かすと多数決ベースラインはどう変わる?

実測の 47 県の総人口で、しきい値(万人)を左右にドラッグ。境界の引き方だけで「学習ゼロの正解率」が上下します。

しきい値 100 万人で分割 → 「以上」37 県 / 「未満」10

多数決(「以上」に全部貼るだけ)の正解率 = 78.7%

対策:正解率だけでなく、① 混同行列で「どのクラスをどう間違えるか」を見る、② クラスごとの再現率を平均する balanced accuracy / macro-F1、③ 多数決ベースラインとの差を必ず併記する。これで「78.7% は高い」という錯覚を防げます。

🚀 発展

  • 確信度 ≠ 正解率(キャリブレーション):softmax の出力する確率は、そのまま信頼度として使うと過信になりがち。予測確率と実際の的中率が一致するか(信頼度較正)を確かめる。
  • 不均衡への直接対処:損失にクラス重みを掛ける、少数クラスを増やすリサンプリング、難サンプルを重視する focal loss など。データ拡張(本文の④参照)も少数クラス補強に効く。
  • macro と micro の使い分け:全サンプル平均(micro)は多数派に引きずられる。クラスを平等に扱いたいなら macro 平均を主指標にする。
  • 画像分類への接続:生画素の最近傍が不変性で崩れるのと同様、評価も「基準線」を無視すると崩れる。CNN で表現を学んでも、評価設計が甘ければ数字は嘘をつく。

🔗 関連ページ