論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
深層学習アーキテクチャ
Deep Learning Architectures
画像・系列・言語の領域で発展した強力な構造群
深層学習CNNTransformer表現学習

🔖 キーワード索引(補強)

🔖 キーワード索引(補強)

深層学習アーキテクチャに関する概念のチップ集。

CNN ResNet RNN/LSTM GRU Transformer Attention Self-Attention Vision Transformer GAN Diffusion VAE Autoencoder GNN Graph Attention Mixture of Experts BatchNorm LayerNorm Dropout Adam AdamW 学習率スケジュール 転移学習 Fine-tuning LoRA

💡 30秒で分かる結論

🍰 まずはやさしく

AIの設計図のようなものです。

データの種類に合わせて使い分けます。

スマホの写真や翻訳機能で使われています。

代表的な設計図の種類を学びます。

🤔 1. なぜアーキテクチャの設計が重要か

万能近似定理は「十分な幅の MLP は任意の関数を近似できる」と言うが、 実用にはデータの構造に合った帰納バイアスが必要:

🖼 2. 畳み込みニューラルネットワーク (CNN)

2.1 畳み込み層

入力画像 $X$ にカーネル $K$ をスライドさせながら積和:

$$Y_{i,j} = \sum_{m,n} X_{i+m, j+n} K_{m,n} + b$$

1 カーネルが 1 つの特徴を検出(エッジ・テクスチャ等)。 多数のカーネルで多数の特徴マップを出力。

2.2 主要パラメータ

2.3 プーリング

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import torch.nn as nn
class SimpleCNN(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
            nn.Conv2d(64, 128, 3, padding=1), nn.ReLU(), nn.AdaptiveAvgPool2d(1),
        )
        self.classifier = nn.Linear(128, num_classes)
    def forward(self, x):
        x = self.features(x).flatten(1)
        return self.classifier(x)
📤 実行例(実測) このブロックは標準出力を出さない(図を描く・変数を定義するだけ)。

2.4 代表的なCNNアーキテクチャ

2.5 ResNet と残差接続

$$\mathbf{y} = F(\mathbf{x}) + \mathbf{x}$$

「恒等関数を足す」だけで深い NN の勾配消失を劇的に緩和。 深層学習史上最重要発明の 1 つ。

2.6 U-Net

セグメンテーション(ピクセル単位分類)の標準。 Encoder で圧縮→Decoder で復元、 同階層をスキップ接続。 医療画像・衛星画像で活躍。

🔁 3. RNN・LSTM・GRU

3.1 RNN(再帰型ニューラルネット)

$$\mathbf{h}_t = \tanh(W_h \mathbf{h}_{t-1} + W_x \mathbf{x}_t + \mathbf{b})$$

隠れ状態 $\mathbf{h}_t$ が「記憶」を持ち越す。 ただし長期依存で勾配消失/爆発が起きやすい。

3.2 LSTM(Long Short-Term Memory, 1997)

3 つのゲート(入力・忘却・出力)+ セル状態 $C_t$ で長期記憶を制御:

$$f_t = \sigma(W_f \cdot [\mathbf{h}_{t-1}, \mathbf{x}_t] + \mathbf{b}_f)$$

$$C_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t$$

$\odot$ は要素積。 ゲートが「何を忘れ・記憶し・出力するか」を学習。

3.3 GRU(Gated Recurrent Unit, 2014)

LSTM 簡略版。 更新ゲート・リセットゲートの 2 つ。 パラメータが少なくほぼ同等の性能。

1
2
3
4
5
6
7
8
9
import torch.nn as nn
class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super().__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, num_classes)
    def forward(self, x):
        out, _ = self.lstm(x)
        return self.fc(out[:, -1, :])
📤 実行例(実測) このブロックは標準出力を出さない(図を描く・変数を定義するだけ)。

3.2 補足 — 短い系列では、LSTM は 1 行の外挿とどこまで張り合えるか

LSTM は「長い系列の中の遠い依存」を覚えるための仕組みです。都道府県データの時系列は 1 県あたり 12 年しかありません。この短さで LSTM を使うと何が起きるかを、各県の高齢化率の直近 5 年から翌年を当てる課題で確かめます。比べる相手は「前年の値をそのまま使う」と「前年の値に直近 1 年の増分を足す」の 2 つの基準です。高齢化率の分母には年齢不詳を除いた人口を使い、国勢調査年(2015・2020 年度)の段差が入らないようにしています。

🎯 このコードでやること:47 県の高齢化率の系列から、目的年 2017〜2022 年の 5 年窓 282 個で LSTM(隠れ 16)を学習し、2018〜2022 年から 2023 年を当てたときの平均絶対誤差(MAE)を 2 つの基準と比べる。LSTM は「値そのもの」と「窓の最後の値からの差」の 2 通りの入力で学習する。

📥 入力例 SSDSE-B-2026.csv の全 564 行(47 都道府県 × 2012〜2023 年度)から作る系列 高齢化率 = A1303 / (A1301 + A1302 + A1303) × 100 (年齢不詳を除いた分母) Prefecture 2012 2013 … 2021 2022 2023 北海道 26.0 27.0 … 32.5 32.8 33.0 東京都 21.3 21.9 … 22.9 22.8 22.8 …(47 県 × 12 年。2018〜2022 年の 5 年から 2023 年を当てる)
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
46
47
48
49
50
51
52
import numpy as np
import pandas as pd
import torch
import torch.nn as nn

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
known = df[['A1301', 'A1302', 'A1303']].sum(axis=1)       # 年齢が分かっている人(国勢調査年の年齢不詳を除く)
df['高齢化率'] = df['A1303'] / known * 100
S = df.pivot(index='Prefecture', columns='SSDSE-B-2026', values='高齢化率').sort_index(axis=1)
seq = S.values                                           # 47 県 × 12 年(2012→2023)
L = 5                                                    # 直近 5 年を見て翌年を当てる
Xw = np.stack([seq[:, t:t + L] for t in range(0, 11 - L)])   # 目的年 2017〜2022 の窓(学習用)
yw = np.stack([seq[:, t + L] for t in range(0, 11 - L)])
Xtr, ytr = Xw.reshape(-1, L), yw.reshape(-1)
Xte, yte = seq[:, 11 - L:11], seq[:, 11]                  # 2018〜2022 → 2023(評価用)
print(f'学習 {len(ytr)} 窓(47 県 × 目的年 2017〜2022)、評価 {len(yte)} 県(2023 年)')

# 基準 1: 前年の値をそのまま / 基準 2: 前年 + 直近 1 年の増分
mae = lambda p: np.abs(p - yte).mean()
print(f'前年値のまま          MAE = {mae(Xte[:, -1]):.3f} ポイント')
print(f'前年 + 直近の増分     MAE = {mae(2 * Xte[:, -1] - Xte[:, -2]):.3f} ポイント')

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.lstm = nn.LSTM(1, 16, batch_first=True)
        self.fc = nn.Linear(16, 1)
    def forward(self, x):
        out, _ = self.lstm(x)
        return self.fc(out[:, -1, :]).squeeze(1)

def fit_lstm(diff):
    """diff=True: 窓を「最後の値からの差」に直して翌年の増分を当てる / False: 値そのものを当てる"""
    torch.manual_seed(0)
    net = Net()
    opt = torch.optim.Adam(net.parameters(), lr=0.01)
    base_tr = Xtr[:, -1:] if diff else 0
    base_te = Xte[:, -1:] if diff else 0
    xt = torch.tensor(Xtr - base_tr, dtype=torch.float32).unsqueeze(2)
    yt = torch.tensor(ytr - np.ravel(base_tr) if diff else ytr, dtype=torch.float32)
    for epoch in range(300):
        opt.zero_grad()
        loss = nn.functional.mse_loss(net(xt), yt)
        loss.backward()
        opt.step()
    with torch.no_grad():
        p = net(torch.tensor(Xte - base_te, dtype=torch.float32).unsqueeze(2)).numpy()
    return p + (Xte[:, -1] if diff else 0), sum(q.numel() for q in net.parameters())

for diff, name in [(False, '値そのものを入力'), (True, '最後の値からの差を入力')]:
    pred, n_par = fit_lstm(diff)
    print(f'LSTM・{name}({n_par} パラメータ) MAE = {mae(pred):.3f} ポイント')
📤 実行例(実測) 学習 282 窓(47 県 × 目的年 2017〜2022)、評価 47 県(2023 年) 前年値のまま MAE = 0.234 ポイント 前年 + 直近の増分 MAE = 0.055 ポイント LSTM・値そのものを入力(1233 パラメータ) MAE = 4.070 ポイント LSTM・最後の値からの差を入力(1233 パラメータ) MAE = 0.065 ポイント

💬 前年の値をそのまま使うと MAE は 0.234 ポイント、前年に直近 1 年の増分を足すだけで 0.055 ポイントまで下がります。1,233 個のパラメータを持つ LSTM は、入力を「最後の値からの差」に直した場合でも 0.065 ポイントで、1 行の外挿に届きません。値そのものを入れた LSTM は 4.070 ポイントと、前年値のままより 17 倍も悪くなりました。高齢化率は県と年によって 17.7〜39.1% の幅があるのに対し、1 年の変化は中央値 0.35 ポイントと小さいので、値そのものを当てさせると 300 エポックでは水準合わせで終わってしまいます。

この結果から言えるのは、「滑らかで短い系列」では LSTM の記憶の仕組みを生かす余地がほとんど無く、差分を取る・前年を基準にするといった問題の表し方の方が精度を決めるということです。深層学習のアーキテクチャを試す前に、この例の「前年 + 増分」のような単純な基準の MAE を必ず並べ、それを下回れなかったら複雑なモデルを採用しない、という手順を守ると、見かけの精度に惑わされません。LSTM が力を発揮するのは、センサーの毎秒の値や文章の単語列のように、系列が長く、遠く離れた時点どうしが関係する場合です。

3.4 双方向 RNN

前向き + 後向きの 2 つの RNN を連結。 全系列を見て予測(過去・未来両方)。

👁 4. Attention 機構

系列の各位置に重みを付け、 重要な部分に「注目」する。 元は機械翻訳(Bahdanau 2014)。

4.1 Self-Attention(自己注意)

Query・Key・Value を入力から計算し、 各位置と全位置の関係を学習:

$$\mathrm{Attention}(Q, K, V) = \mathrm{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right) V$$

記号読み:$Q, K, V$ は「キュー・ケイ・ブイ」、 すべて入力の線形変換。 $d_k$ で割るのは softmax の勾配安定化。

実データで Self-Attention を 1 回計算する

数式の中身を追うために、5 つの県を 5 つの「トークン」とみなし、各県の特徴(高齢化率・年少人口比率・合計特殊出生率・人口千人あたり転入超過率を 47 県で標準化した 4 次元、$d_k = 4$)をそのまま $Q = K = V$ に入れます。本物の Transformer では $Q, K, V$ はそれぞれ学習した行列で線形変換しますが、ここでは変換を省いて「softmax と $\sqrt{d_k}$ が何をするか」だけを見ます。

🎯 このコードでやること:2023 年度の 5 県の標準化した 4 指標を Q = K = V として softmax(QK^T / √d_k) V を計算し、神奈川県の行のスコア、5 × 5 の注意の重み、出力(重み付き平均)、√d_k で割らない場合の各行の最大の重みを表示する。

📥 入力例 SSDSE-B-2026.csv の 2023 年度・47 行から 4 指標を作り、47 県で標準化 Prefecture A1101(総人口) A1301(15歳未満) A1303(65歳以上) A4103(出生率) A5101(転入) A5102(転出) 東京都 14,086,000 1,513,000 3,205,000 0.99 406,749 348,260 秋田県 914,000 83,000 357,000 1.10 10,002 13,177 沖縄県 1,468,000 236,000 350,000 1.60 26,410 27,054 …(全 47 行。使うのは東京都・神奈川県・秋田県・島根県・沖縄県の 5 県 = 5 トークン)
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
import numpy as np
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].set_index('Prefecture')
feat = pd.DataFrame({
    '高齢化率': d['A1303'] / d['A1101'] * 100,
    '年少人口比率': d['A1301'] / d['A1101'] * 100,
    '出生率': d['A4103'],
    '転入超過率': (d['A5101'] - d['A5102']) / d['A1101'] * 1000,
})
Z = (feat - feat.mean()) / feat.std(ddof=0)          # 47 県で標準化
prefs = ['東京都', '神奈川県', '秋田県', '島根県', '沖縄県']
X = Z.loc[prefs].values                             # 5 トークン × d_k = 4
print(Z.loc[prefs].round(2).to_string())

def attention(Q, K, V, scale=True):
    s = Q @ K.T / (np.sqrt(K.shape[1]) if scale else 1.0)
    w = np.exp(s - s.max(axis=1, keepdims=True))
    w = w / w.sum(axis=1, keepdims=True)            # 行ごとの softmax(行の和 = 1)
    return w, w @ V

k = prefs.index('神奈川県')
print('\n神奈川県の行のスコア QK^T / √4:', '  '.join(f'{p} {v:.2f}' for p, v in zip(prefs, X[k] @ X.T / 2)))
W, out = attention(X, X, X)                          # Q = K = V = X(学習した射影なし)
print('\n注意の重み softmax(QK^T / √4)(行 = 注目する側)')
print(pd.DataFrame(W, index=prefs, columns=prefs).round(3).to_string())
print('\n出力(重み付き平均)')
print(pd.DataFrame(out, index=prefs, columns=feat.columns).round(2).to_string())
W1, _ = attention(X, X, X, scale=False)
print('\n各行の最大の重み  √d_k で割る:', W.max(axis=1).round(3), ' 割らない:', W1.max(axis=1).round(3))
📤 実行例(実測) 高齢化率 年少人口比率 出生率 転入超過率 Prefecture 東京都 -2.67 -0.69 -2.30 2.94 神奈川県 -1.72 -0.28 -1.24 2.05 秋田県 2.26 -2.26 -1.46 -0.90 島根県 1.01 0.36 1.27 -0.66 沖縄県 -2.34 4.36 2.33 0.62 神奈川県の行のスコア QK^T / √4: 東京都 6.83 神奈川県 4.39 秋田県 -1.66 島根県 -2.38 沖縄県 0.61 注意の重み softmax(QK^T / √4)(行 = 注目する側) 東京都 神奈川県 秋田県 島根県 沖縄県 東京都 0.981 0.019 0.000 0.000 0.000 神奈川県 0.918 0.080 0.000 0.000 0.002 秋田県 0.000 0.000 0.998 0.002 0.000 島根県 0.002 0.011 0.130 0.577 0.279 沖縄県 0.000 0.000 0.000 0.000 1.000 出力(重み付き平均) 高齢化率 年少人口比率 出生率 転入超過率 東京都 -2.66 -0.68 -2.28 2.92 神奈川県 -2.60 -0.65 -2.20 2.86 秋田県 2.26 -2.25 -1.46 -0.90 島根県 0.20 1.12 1.17 -0.29 沖縄県 -2.34 4.36 2.33 0.62 各行の最大の重み √d_k で割る: [0.981 0.918 0.998 0.577 1. ] 割らない: [1. 0.992 1. 0.778 1. ]

💬 神奈川県の行を手で追うと、スコアは東京都 6.83、自分自身 4.39、沖縄県 0.61、秋田県 −1.66、島根県 −2.38 で、softmax をかけると e^6.83 ≈ 925、e^4.39 ≈ 81 などを合計約 1,008 で割って、東京都 0.918、神奈川県 0.080 になります。神奈川県は自分自身より東京都に強く注目しています。内積は向きだけでなくベクトルの長さにも比例するので、神奈川県と同じ向き(高齢化率・出生率が低く、転入超過が多い)で、より極端な東京都のスコアが自分自身のスコアを上回るのです。一方、特徴が平均に近い島根県は重みが 0.577(自分)・0.279(沖縄県)・0.130(秋田県)と分散し、出力も 3 県の中間(高齢化率 0.20、年少人口比率 1.12)になります。√d_k で割らないと最大の重みは島根県でも 0.778 まで上がり、どの行もほぼ 1 県だけを見る分布に近づきます。

ここから 2 つのことが読み取れます。1 つは、内積による注意は「似ている相手」ではなく「同じ向きで長い相手」を選びやすいことです(コサイン類似度なら神奈川県の自分自身への値は必ず 1 で最大になります)。学習した $W_Q, W_K$ は、この長さの効き方も含めて「どの相手をどれだけ見るか」を調整する役割を持ちます。もう 1 つは、$\sqrt{d_k}$ で割る理由です。スコアの差が大きいと softmax はほぼ 1 か所だけに 1 を置く形になり、他のトークンへの勾配がほとんど 0 になって学習が進みにくくなります。$d_k$ が 64 や 128 になると内積の大きさは $\sqrt{d_k}$ に比例して大きくなりやすいので、その分だけ割り戻して、softmax が極端な形になるのを防いでいます。

4.2 Multi-Head Attention

複数の Attention を並列に実行、 異なる関係性を捉える。 通常 8〜16 ヘッド。

4.3 計算量

系列長 $n$ で $O(n^2 d)$。 長系列で重い → FlashAttention・Sparse Attention・Linear Attention 等の高速化。

⚡ 5. Transformer("Attention is All You Need", 2017)

RNN を捨て Self-Attention のみで構築。 並列学習可能で大規模化が容易。

5.1 構造

1
2
3
4
5
6
7
8
import torch
import torch.nn as nn
# PyTorch 標準の Transformer
model = nn.Transformer(d_model=512, nhead=8, num_encoder_layers=6, num_decoder_layers=6)

# Encoder のみ(BERT 系)
encoder_layer = nn.TransformerEncoderLayer(d_model=512, nhead=8, batch_first=True)
encoder = nn.TransformerEncoder(encoder_layer, num_layers=6)
📤 実行例(実測) このブロックは標準出力を出さない(図を描く・変数を定義するだけ)。

5.2 BERT(2018)

Transformer Encoder のみ。 双方向 Masked Language Model + Next Sentence Prediction で事前学習。 分類・抽出系タスクに強い。

5.3 GPT 系

Transformer Decoder のみ。 次の単語予測で自己回帰的に生成。 GPT-3(2020)以降、 大規模化で zero-shot/few-shot 能力が出現。

5.4 Vision Transformer (ViT)

画像を 16×16 パッチに分割し、 トークン列として Transformer に投入。 大規模事前学習で CNN を上回るケース増加。

🔤 6. 埋め込み (Embedding)

カテゴリ・単語等の離散シンボルを密ベクトルに変換。 NN の入り口の標準技。

代表例

🔄 7. 転移学習

大規模データで事前学習したモデルを、 自分の問題に流用。 少データで高精度が出る現代深層学習の主流。

7.1 ファインチューニング戦略

1
2
3
4
from transformers import AutoModelForSequenceClassification, AutoTokenizer, Trainer
model = AutoModelForSequenceClassification.from_pretrained('bert-base-japanese-v3', num_labels=2)
tokenizer = AutoTokenizer.from_pretrained('bert-base-japanese-v3')
# Trainer で fine-tuning(HuggingFace 標準パターン)

🕸 8. グラフニューラルネットワーク(参考)

ノードと辺で構造化されたデータ(SNS、 分子、 知識グラフ)向け。

📊 9. アーキテクチャ早見表

アーキ 得意なデータ 帰納バイアス 特徴
MLP表データなし汎用
CNN画像・音声局所性・並進不変パラメータ少
RNN/LSTM系列時間依存逐次計算
Transformer系列・画像・全般Attention並列・大規模
GNNグラフ近傍集約関係構造
U-Net画像セグメントEncoder-Decoder + skip医療画像

📍 あなたが今見ているもの

🍰 まずはやさしく

AIを作るための型の一覧です。

データの性質を活かすために使います。

画像や言葉など、扱うデータで選びます。

有名な設計図をまとめて解説します。

本ページでは、 深層学習の代表的アーキテクチャを統合的に解説します。 CNN・RNN/LSTM/GRU・Attention・Transformer・ResNet・U-Net・BERT/GPT を一気通貫で扱います。

2012 年の AlexNet 以降、 画像・音声・言語・系列データで深層学習が圧倒的な性能を出すようになりました。 各アーキテクチャが「どんなデータの性質を活かす」設計なのかを理解することが本質です。

🎨 直感で掴む — 深層学習(応用) の本質

🍰 まずはやさしく

問題を解くための道具箱です。

どの道具が最適かを知るために使います。

部活の記録や成績表などで考えます。

道具の使い方を直感的に理解します。

深層学習の応用領域は広く、 画像認識(CNN)、 自然言語(Transformer)、 強化学習、 生成 AI(拡散モデル)等が含まれる。 SSDSE-B-2026 のような 47 行 × 100 列の小規模表データには通常向かないが、 多年度を統合した時系列・パネル化や、 都道府県別の衛星画像等と組み合わせると深層学習の出番が出てくる。

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

📐 数式または定義 — 深層学習(応用) の形式的表現

🍰 まずはやさしく

AIの計算ルールを式にしたものです。

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

スマホの中での計算のようなものです。

数式を言葉に直して詳しく読みます。

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

【Scaled Dot-Product Attention(Transformer の中核)】
$$ \mathrm{Attention}(Q,K,V) = \mathrm{softmax}\!\left(\frac{Q K^\top}{\sqrt{d_k}}\right) V $$
この数式は「深層学習(応用) がどう計算されるか」を最短で示したもの。 記号の意味は次の「🔬 数式を言葉で読み解く」で 1 つずつ解説します。
📚 数式が苦手な方へ:1 つの長い式を一度に理解しようとせず、 記号ごとに「言葉に翻訳」するのが王道。 紙に書き写してから、 自分の言葉で音読してみてください。

🔬 数式を言葉で読み解く — 深層学習(応用) の記号辞書

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

記号意味(言葉での説明)
$Q, K, V$クエリ・キー・バリュー行列
$d_k$キー次元(スケーリングで softmax を安定化)
softmax注意重みを総和 1 に正規化
Multi-Head異なる視点を並列に学習
Self-Attention系列内の全要素同士の関連性を計算
📌 読み下しのコツ:左から右に「主語 → 述語 → 目的語」と見立てて、 「これは何を、 どうしている式か?」と一文で要約してみてください。 慣れれば 5 秒で読めます。

🧮 SSDSE-B-2026 で実値計算 — 深層学習の実例

SSDSE-B-2026 は表形式のため CNN/RNN の本領ではないが、 MLP(多層パーセプトロン)の学習練習に使えます。

例:MLP で都道府県の高齢化率を回帰

📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年) 年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) … 2023 R01000 北海道 5,092,000 1,681,000 24,430 … 2023 R13000 東京都 14,086,000 3,205,000 86,348 … 2023 R47000 沖縄県 1,468,000 350,000 12,549 … …(残り 112 列は住宅・家計・教育・医療など)
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
import torch
import torch.nn as nn
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score

torch.manual_seed(0)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
# 目的変数: 合計特殊出生率 / 特徴量: 人口規模に左右されない 5 つの比率・気候指標
df['高齢化率'] = df['65歳以上人口'] / df['総人口']
df['若年率'] = df['15歳未満人口'] / df['総人口']
df['婚姻率'] = df['婚姻件数'] / df['総人口'] * 1000
feats = ['高齢化率', '若年率', '婚姻率', '年平均気温', '降水日数(年間)']

X_tr, X_te, y_tr, y_te = train_test_split(df[feats].values, df['合計特殊出生率'].values,
                                          test_size=0.2, random_state=42)
sx, sy = StandardScaler().fit(X_tr), StandardScaler().fit(y_tr.reshape(-1, 1))   # 訓練側だけで標準化
X_tr_t = torch.tensor(sx.transform(X_tr), dtype=torch.float32)
y_tr_t = torch.tensor(sy.transform(y_tr.reshape(-1, 1)), dtype=torch.float32)
X_te_t = torch.tensor(sx.transform(X_te), dtype=torch.float32)

class MLP(nn.Module):
    def __init__(self, d_in):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(d_in, 32), nn.ReLU(), nn.Dropout(0.2),
            nn.Linear(32, 16), nn.ReLU(),
            nn.Linear(16, 1))
    def forward(self, x): return self.net(x)

model = MLP(len(feats))
opt = torch.optim.AdamW(model.parameters(), lr=1e-2, weight_decay=1e-4)
loss_fn = nn.MSELoss()
for ep in range(200):
    model.train(); opt.zero_grad()
    pred = model(X_tr_t)
    loss = loss_fn(pred, y_tr_t)
    loss.backward(); opt.step()
print('最終 loss(標準化した y の MSE):', round(loss.item(), 4))

model.eval()                                  # Dropout を止めて予測
with torch.no_grad():
    y_hat = sy.inverse_transform(model(X_te_t).numpy()).ravel()
print('テスト R²:', round(r2_score(y_te, y_hat), 3))
📤 実行例(実測) 最終 loss(標準化した y の MSE): 0.1208 テスト R²: 0.904

💬 564 行のうち 451 行で学習し、標準化した出生率の MSE は 0.1208 まで下がった(分散 1 のうち約 12% が残る)。テスト 113 行の R² は 0.904 と高いが、行を無作為に分けているので、同じ県の別の年度が訓練側にも入っており、「その県の出生率の水準」を覚えていれば当たる。Dropout を入れたモデルは model.eval() に切り替えないと予測のたびに値が揺れるので、評価の前に必ず切り替える。

例:sklearn の MLPRegressor で同等処理

📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年) 年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) … 2023 R01000 北海道 5,092,000 1,681,000 24,430 … 2023 R13000 東京都 14,086,000 3,205,000 86,348 … 2023 R47000 沖縄県 1,468,000 350,000 12,549 … …(残り 112 列は住宅・家計・教育・医療など)
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
import pandas as pd
from sklearn.neural_network import MLPRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.compose import TransformedTargetRegressor
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
# 目的変数: 合計特殊出生率 / 特徴量: 人口規模に左右されない 5 つの比率・気候指標
df['高齢化率'] = df['65歳以上人口'] / df['総人口']
df['若年率'] = df['15歳未満人口'] / df['総人口']
df['婚姻率'] = df['婚姻件数'] / df['総人口'] * 1000
feats = ['高齢化率', '若年率', '婚姻率', '年平均気温', '降水日数(年間)']
X = df[feats].values
y = df['合計特殊出生率'].values

mlp = TransformedTargetRegressor(            # y も標準化してから学習させる
    regressor=make_pipeline(StandardScaler(),
                            MLPRegressor(hidden_layer_sizes=(32, 16), max_iter=2000,
                                         alpha=1e-4, random_state=0)),
    transformer=StandardScaler())
# cv=5 はシャッフルしないので、県ごとに 12 年度が並ぶこのデータでは「未知の県」を当てる評価になる
scores = cross_val_score(mlp, X, y, cv=5, scoring='r2')
print('fold 別 R²:', scores.round(3))
print('CV R²:', scores.mean())
📤 実行例(実測) fold 別 R²: [0.425 0.825 0.723 0.595 0.696] CV R²: 0.6527301775686104

💬 同じ 5 特徴量でも、cv=5(シャッフルなし)で評価すると R² は 0.425〜0.825、平均 0.653 に下がる。データは県ごとに 12 年度が並んでいるので、各 fold は約 9 県を丸ごと外して予測することになり、直前の無作為分割の 0.904 より厳しい評価になる。同じ分け方で標準化+線形回帰を当てると約 0.71 で、564 行・5 特徴量の表データではニューラルネットが線形モデルに勝てていない。

🧮 実値で計算してみる — SSDSE-B-2026 で 深層学習(応用) を体感

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

👉 計算例:SSDSE-B-2026 の 2018-2023 年 × 47 県を時系列パネルとして、 Transformer Encoder で「2024 年の出生率」を予測。 入力次元 100、 シーケンス長 6、 隠れ層 64、 ヘッド数 4。 RMSE は ARIMA より小さくなることもあるが、 サンプル数が少ないので注意深く正則化(Dropout 0.3、 Weight Decay 1e-4)が必須。

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

🧮 数式に値を入れて手で計算する: 層別パラメータ数

合成 3 層 MLP (入力 784 → 128 → 64 → 10) の総パラメータ数を計算する。

Step 1: 層別パラメータ

層重みバイアス合計
784→128784×128=100,352128100,480
128→64128×64=8,192648,256
64→1064×10=64010650

Step 2: 総和

合計 = 100,480 + 8,256 + 650 = 109,386 パラメータ ≈ 109K パラメータ (float32 なら 109,386 × 4 = 437,544 バイト ≈ 427 KB、1 KB = 1,024 バイト)

🐍 Python で再現

1
2
3
4
5
6
import numpy as np
layers = [(784, 128), (128, 64), (64, 10)]
params = [(i*o + o) for i, o in layers]
print(f"層別パラメータ: {params}")
print(f"合計: {sum(params):,}")
print(f"サイズ (float32): {sum(params)*4/1024:.1f} KB")

📤 実行結果

層別パラメータ: [100480, 8256, 650] 合計: 109,386 サイズ (float32): 427.3 KB

💬 手計算 (Step 2) 109,386 パラメータと Python 出力が完全一致。

🐍 13. ライブラリ早見表

🐍 13. ライブラリ早見表

用途 パッケージ
基本フレームワークtorch, jax, tensorflow
高レベルAPIpytorch-lightning, keras, flax
事前学習モデルtransformers (HuggingFace), timm
CNN特化torchvision.models, timm
セグメンテーションsegmentation_models_pytorch
物体検出ultralytics (YOLO), detectron2, mmdetection
NLP前処理tokenizers, sentencepiece, fugashi (日本語)
PEFT・LoRApeft, lit-gpt
分散学習deepspeed, accelerate, fsdp
実験管理wandb, mlflow, tensorboard
GNNtorch-geometric, dgl
時系列DLdarts, neuralforecast, pytorch-forecasting

📜 14. 深層学習アーキテクチャの歴史

💼 15. 実務応用

✅ 16. 深層学習プロジェクト チェックリスト

🎓 17. 深層学習を成功させる実践のコツ

17.1 デバッグの順番

  1. ごく小さいサブセット(1〜2 バッチ)でモデルがオーバーフィットできるか確認
  2. できなければアーキテクチャ・損失関数のバグ
  3. できたら通常データで学習、 訓練損失が下がるか確認
  4. 検証損失が改善するか確認
  5. 過学習を抑える調整に進む

17.2 学習率の選び方

17.3 バッチサイズ

17.4 GPU メモリ削減

🤗 18. Hugging Face エコシステム

事前学習モデルのデファクト標準。 数万のモデルが公開されている。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from transformers import pipeline
# 感情分析
clf = pipeline('sentiment-analysis', model='cl-tohoku/bert-base-japanese-v3')
print(clf('この商品は素晴らしいです'))

# テキスト生成
gen = pipeline('text-generation', model='rinna/japanese-gpt-neox-3.6b')
print(gen('日本の首都は'))

# ゼロショット分類
zsc = pipeline('zero-shot-classification', model='facebook/bart-large-mnli')
print(zsc('I love this movie', candidate_labels=['positive','negative']))

# 画像分類
img = pipeline('image-classification', model='google/vit-base-patch16-224')

❓ 19. よくある質問

Q. Transformer は CNN を完全に置き換えますか?

A. 大規模事前学習があれば ViT が勝つことが多いですが、 中小規模では CNN が依然強力。 ConvNeXt 等の現代 CNN は ViT と互角。

Q. LSTM はもう古い?

A. 短系列・低リソースなら現役。 長系列・大規模なら Transformer が標準。 最近は Mamba(SSM)が中間域で注目。

Q. 自前で大規模事前学習は可能?

A. GPT-3 級は数千〜数億ドル。 現実的には公開モデルを fine-tune が標準。 ドメイン特化なら継続事前学習(Domain-Adaptive Pretraining)。

Q. パラメータが多いほど良い?

A. 一般に大きいほど性能向上(scaling law)だが、 推論コスト・遅延・環境負荷とのトレードオフ。 蒸留・量子化で運用効率化。

📈 20. スケーリング則(Scaling Laws)

Kaplan ら 2020 / Hoffmann ら 2022(Chinchilla)。 モデル損失 $L$ はパラメータ数 $N$・データ量 $D$・計算量 $C$ の冪乗則に従う:

$$L(N, D) \approx L_\infty + \frac{A}{N^\alpha} + \frac{B}{D^\beta}$$

Chinchilla 則:与えられた計算量に対し、 $N \propto D$ で釣り合わせるのが最適。 つまり「データ不足の大モデル」より「データ豊富な小〜中モデル」のほうが効率良い。

⚡ 21. モデル量子化と運用効率化

📊 22. 主要ベンチマーク

分野 ベンチマーク
画像分類ImageNet, CIFAR-10/100
物体検出COCO, Pascal VOC
セグメンテーションCityscapes, ADE20K
NLP 理解GLUE, SuperGLUE, JGLUE
機械翻訳WMT, FLORES
LLM 総合MMLU, BIG-Bench, HELM
コード生成HumanEval, MBPP
音声認識LibriSpeech, CSJ

1. PyTorch — 標準的なトレーニングループ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset

class Net(nn.Module):
    def __init__(self, d_in):
        super().__init__()
        self.fc = nn.Sequential(nn.Linear(d_in, 64), nn.ReLU(), nn.Linear(64, 1))
    def forward(self, x): return self.fc(x)

# X, y は事前に標準化済み torch tensor
net = Net(5)
opt = torch.optim.AdamW(net.parameters(), lr=1e-3)
loss_fn = nn.MSELoss()

# ループ例
for epoch in range(100):
    opt.zero_grad()
    # pred = net(X); loss = loss_fn(pred, y); loss.backward(); opt.step()
📤 実行例(実測) このブロックは標準出力を出さない(図を描く・変数を定義するだけ)。

2. PyTorch Lightning — 高水準ラッパー

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import pytorch_lightning as pl
import torch
import torch.nn as nn

class LitMLP(pl.LightningModule):
    def __init__(self, d_in):
        super().__init__()
        self.net = nn.Sequential(nn.Linear(d_in, 32), nn.ReLU(), nn.Linear(32, 1))
        self.loss = nn.MSELoss()
    def training_step(self, batch, _):
        x, y = batch
        return self.loss(self.net(x), y)
    def configure_optimizers(self):
        return torch.optim.AdamW(self.parameters(), lr=1e-3)

# trainer = pl.Trainer(max_epochs=50); trainer.fit(LitMLP(5), dataloader)

3. TensorFlow / Keras — 高水準 API

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import tensorflow as tf

model = tf.keras.Sequential([
    tf.keras.layers.Dense(32, activation='relu', input_shape=(5,)),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(16, activation='relu'),
    tf.keras.layers.Dense(1)
])
model.compile(optimizer=tf.keras.optimizers.AdamW(1e-3), loss='mse', metrics=['mae'])
# model.fit(X, y, epochs=50, validation_split=0.2, batch_size=8)

4. scikit-learn MLPRegressor — 簡易 MLP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from sklearn.neural_network import MLPRegressor, MLPClassifier
from sklearn.preprocessing import StandardScaler

# 表形式の小〜中規模データ向け
mlp = MLPRegressor(
    hidden_layer_sizes=(64, 32),
    activation='relu',
    solver='adam',
    learning_rate_init=1e-3,
    early_stopping=True,
    n_iter_no_change=10,
    max_iter=500,
    random_state=0
)
# mlp.fit(StandardScaler().fit_transform(X), y)
📤 実行例(実測) このブロックは標準出力を出さない(図を描く・変数を定義するだけ)。

5. Hugging Face transformers — 事前学習モデル fine-tune

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from transformers import AutoModel, AutoTokenizer, AutoConfig
import torch.nn as nn

class TextClassifier(nn.Module):
    def __init__(self, model_name, n_classes):
        super().__init__()
        self.encoder = AutoModel.from_pretrained(model_name)
        hidden = self.encoder.config.hidden_size
        self.head = nn.Linear(hidden, n_classes)
    def forward(self, input_ids, attention_mask):
        out = self.encoder(input_ids=input_ids, attention_mask=attention_mask)
        cls = out.last_hidden_state[:, 0, :]
        return self.head(cls)

# model = TextClassifier('cl-tohoku/bert-base-japanese-v3', n_classes=4)

🐍 Python 実装 — 深層学習(応用) を SSDSE-B-2026 で動かす

🎯 このコードでやること: SSDSE からニューラルネットに入れるデータを組み立て、 隠れ層 2 段(16→8)の多層パーセプトロン(MLPRegressor)で 2023 年度 47 県の合計特殊出生率を予測します。 「大学等進学率」「労働力人口」は SSDSE-B に列として存在しないので、 進学率は「高等学校卒業者のうち進学者数 ÷ 高等学校卒業者数」で計算し、 労働力人口の代わりに生産年齢人口(15〜64 歳)を使います。 無い列を作らず、 実在する列から導出するという原則を守っています。 ネットの成績は 5 分割交差検証の MAE で測り、 同じ特徴量の線形回帰と「平均で予測するだけ」の基準と並べて、 47 行で深いモデルを使う意味があるかを確かめます。 なお pd.read_csv('data/raw/SSDSE-B-2026.csv') をパス変数にせず直書きしているのは、 初学者が「パスをどこに書くべきか」で迷わないようにするためです。 CSV を同じ階層に置けばそのまま動きます。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A4103(合計特殊出生率) A1101(総人口) A1302(15~64歳人口) A1303(65歳以上人口) E4601(高等学校卒業者数) E4602(高等学校卒業者のうち進学者数) 北海道 1.06 5,092,000 2,897,000 1,681,000 34,467 18,177 東京都 0.99 14,086,000 9,368,000 3,205,000 93,495 69,302 沖縄県 1.6 1,468,000 882,000 350,000 13,022 6,080 …(全 47 行)
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
# 深層学習(応用) を SSDSE-B-2026 で確かめる最小コード
import pandas as pd
import numpy as np
from sklearn.neural_network import MLPRegressor
from sklearn.linear_model import LinearRegression
from sklearn.dummy import DummyRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import KFold, cross_val_predict

# 1) SSDSE-B-2026(教育用標準データセット)を読み込み、2023 年度の 47 県に絞る
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
df23 = df[df['年度'] == 2023].copy()
print('rows in 2023:', len(df23))

# 2) ネットに入れる特徴量を実在する列から組み立てる
#    「大学等進学率」「労働力人口」は列として無いので導出・代用する
df23['大学等進学率'] = df23['高等学校卒業者のうち進学者数'] / df23['高等学校卒業者数'] * 100
df23['生産年齢人口割合'] = df23['15~64歳人口'] / df23['総人口'] * 100
df23['高齢化率'] = df23['65歳以上人口'] / df23['総人口'] * 100
df23['log総人口'] = np.log10(df23['総人口'])
feats = ['大学等進学率', '生産年齢人口割合', '高齢化率', 'log総人口']
X = df23[feats].to_numpy()
y = df23['合計特殊出生率'].to_numpy()
print(df23[feats].describe().loc[['mean', 'min', 'max']].round(2))

# 3) 深層学習(応用) の本処理:隠れ層 2 段(16→8)の多層パーセプトロン
#    標準化してから入れる。比較用に同じ特徴量の線形回帰も用意する
mlp = make_pipeline(StandardScaler(),
                    MLPRegressor(hidden_layer_sizes=(16, 8), alpha=1e-2,
                                 max_iter=5000, random_state=0))
lin = make_pipeline(StandardScaler(), LinearRegression())

# 4) 5 分割交差検証(学習に使っていない県で予測)で MAE を比べる
cv = KFold(n_splits=5, shuffle=True, random_state=0)
print('---- 深層学習(応用) 結果 ----')
for name, model in [('MLP(16,8)', mlp), ('線形回帰', lin),
                    ('平均で予測', DummyRegressor())]:
    pred = cross_val_predict(model, X, y, cv=cv)
    mae = np.abs(pred - y).mean()
    print(f'{name:10s} 交差検証 MAE = {mae:.3f}')
📤 実行例(実測) rows in 2023: 47 大学等進学率 生産年齢人口割合 高齢化率 log総人口 mean 57.56 56.95 31.59 6.26 min 46.69 51.86 22.75 5.73 max 74.12 66.51 39.06 7.15 ---- 深層学習(応用) 結果 ---- MLP(16,8) 交差検証 MAE = 0.134 線形回帰 交差検証 MAE = 0.040 平均で予測 交差検証 MAE = 0.107

💬 学習に使っていない県での MAE は、線形回帰が 0.040 に対し、MLP(16,8) は 0.134 で、平均値を返すだけの基準 0.107 よりも悪い。4 特徴量・47 行に対し MLP のパラメータは重み 4×16+16×8+8×1=200 個に切片 25 個を加えて 225 個あり、データ量に比べて自由度が大きすぎるうえ、学習データでも MAE 0.096 までしか下がっておらず最適化も十分に進んでいない。深層学習が力を発揮するのは画像・文章のように標本が数万以上ある場面で、都道府県の表データではまず線形モデルを基準に置き、それを超えられるかで判断する。

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

🐍 Python 実装 1 — データ読み込みと describe

このコードでやること: SSDSE-B-2026 の CSV を pd.read_csv で読み込み、 都道府県・総人口・合計特殊出生率・大学等進学率・生産年齢人口の 5 列を抽出して .describe() で要約統計量を確認する。 DLA を組む前に必ず通すべきデータ確認の段。

📥 入力データ: data/raw/SSDSE-B-2026.csv(564 行 × 112 列、 1 行 = 1 都道府県 × 年度)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=1, encoding='cp932')
df = df[df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy()
for _c in df.columns[3:]:
    df[_c] = pd.to_numeric(df[_c], errors='coerce')

# 「大学等進学率」「労働力人口」は SSDSE-B に列として存在しない。
# 進学率は実在する列から計算し、労働力人口の代わりに生産年齢人口(15〜64歳)を使う
df['大学等進学率'] = (df['高等学校卒業者のうち進学者数']
                      / df['高等学校卒業者数'] * 100)
_wa = [c for c in df.columns if c.startswith('15') and c.endswith('64歳人口')][0]
df['生産年齢人口'] = df[_wa] / 1000        # 人 → 千人
df['総人口'] = df['総人口'] / 1000          # 人 → 千人(本文の単位に合わせる)

cols = ['都道府県', '総人口', '合計特殊出生率', '大学等進学率', '生産年齢人口']
sub = df[cols].dropna()
print(sub.describe().round(2))

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

総人口 合計特殊出生率 大学等進学率 生産年齢人口 count 564.00 564.00 564.00 564.00 mean 2690.69 1.45 52.59 1616.96 std 2730.95 0.15 7.09 1749.64 min 537.00 0.99 37.67 294.00 25% 1082.25 1.34 46.69 604.00 50% 1620.00 1.46 52.02 909.00 75% 2784.93 1.55 57.28 1617.75 max 14086.00 1.96 74.12 9368.00

💬 564 行(47 都道府県 × 12 年度)すべてで欠損は無い。総人口の標準偏差(2,731 千人)は平均(2,691 千人)とほぼ同じで、最小 537 千人・最大 14,086 千人と 26 倍の開きがある → 都道府県間のばらつきが極めて大きい。 DLA に投入する前に 標準化または log 変換がほぼ必須。

🐍 Python 実装 2 — MLP(多層パーセプトロン)で総人口を予測

このコードでやること: 説明変数 3 つ(合計特殊出生率・大学等進学率・生産年齢人口(労働力人口の代わり))から目的変数(総人口)を予測する 3 層 MLP を sklearn.neural_network.MLPRegressor で構築する。 標準化 → 学習 → 評価まで通す。

📥 入力データ: 実装 1 の sub データフレーム(564 行 × 5 列 = 47 都道府県 × 12 年度)。 X は出生率・進学率・生産年齢人口、 y は総人口(千人)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from sklearn.preprocessing import StandardScaler
from sklearn.neural_network import MLPRegressor
from sklearn.metrics import r2_score, mean_absolute_error

# 前のブロックで作った sub の列に合わせる(労働力人口の代わりに生産年齢人口)
X = sub[['合計特殊出生率', '大学等進学率', '生産年齢人口']].values
y = sub['総人口'].values

scaler = StandardScaler()
Xz = scaler.fit_transform(X)

model = MLPRegressor(hidden_layer_sizes=(16, 8),
                     activation='relu',
                     max_iter=2000,
                     random_state=0)
model.fit(Xz, y)
pred = model.predict(Xz)
print(f'R^2  = {r2_score(y, pred):.4f}')
print(f'MAE  = {mean_absolute_error(y, pred):,.1f} 千人')

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

R^2 = 0.9887 MAE = 215.7 千人

💬 3 層 MLP(16→8→1)で R²=0.9887、 平均絶対誤差 215.7 千人。 ただしこれは訓練データの学習誤差であり、 このままでは過学習かどうか判断できない。 後段でクロスバリデーションを行う。

🐍 Python 実装 3 — 5-fold CV で汎化性能を確認

このコードでやること: 実装 2 の MLP に対し sklearn.model_selection.cross_val_score で 5-fold クロスバリデーションを行い、 訓練誤差と汎化誤差の差(過学習度)を測る。

📥 入力データ: 実装 2 の Xz, y(564 行)。

1
2
3
4
5
6
from sklearn.model_selection import cross_val_score, KFold

cv = KFold(n_splits=5, shuffle=True, random_state=0)
scores = cross_val_score(model, Xz, y, cv=cv, scoring='r2')
print(f'5-fold R^2: {scores}')
print(f'mean = {scores.mean():.4f}, std = {scores.std():.4f}')

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

5-fold R^2: [0.98234012 0.98168115 0.98778464 0.98121479 0.99069314] mean = 0.9847, std = 0.0038

💬 訓練 R²=0.9887 と CV mean R²=0.9847 の差はわずか 0.004 (5 分割の幅も 0.981〜0.991 と狭い)。 ただし行を無作為に 5 分割しているので、同じ県の別の年度が訓練側に入っており、「未知の県」を当てる評価にはなっていない。 そもそも R² がここまで高いのは説明変数に生産年齢人口(≈総人口の 6 割)が含まれるからで、 実務では予測対象と高相関な変数を抜く工夫(リーケージ回避)が必須。

🐍 Python 実装 4 — アーキテクチャ比較(hidden_layer_sizes をスイープ)

このコードでやること: DLA の中核「深さ vs 幅」を実証する。 同じ SSDSE-B-2026 データに対し、 (4,)・(16,)・(16,8)・(32,16,8)・(64,32,16,8) の 5 種類で CV R² を計測。 深さ/幅の効果を可視化。

📥 入力データ: 実装 2 の Xz, y。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd
from sklearn.compose import TransformedTargetRegressor
from sklearn.preprocessing import StandardScaler
archs = [(4,), (16,), (16,8),
         (32,16,8), (64,32,16,8)]
rows = []
for a in archs:
    # y(総人口・千人)も標準化してから学習させる。
    # 千人単位のままだと (4,)・(16,) は 3000 回で収束せず、構造ではなく学習不足の比較になる
    m = TransformedTargetRegressor(
        regressor=MLPRegressor(hidden_layer_sizes=a, max_iter=3000, random_state=0),
        transformer=StandardScaler())
    s = cross_val_score(m, Xz, y, cv=cv, scoring='r2')
    rows.append({'arch': str(a), 'cv_r2_mean': s.mean(), 'cv_r2_std': s.std()})
print(pd.DataFrame(rows).round(4))

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

arch cv_r2_mean cv_r2_std 0 (4,) 0.9843 0.0030 1 (16,) 0.9885 0.0038 2 (16, 8) 0.9919 0.0022 3 (32, 16, 8) 0.9948 0.0015 4 (64, 32, 16, 8) 0.9971 0.0004

💬 CV R² は (4,) の 0.9843 から (64,32,16,8) の 0.9971 まで、深く広くするほど単調に上がり、最も大きいネットで劣化は見られなかった。 総人口は生産年齢人口とほぼ比例(相関 0.9986)していて、しかも行を無作為に分けているため同じ県の別年度が訓練側にあり、大きなネットほどそれを細かく覚えられるからである。 y を千人単位のまま学習させると (4,) は -0.23、(16,) は 0.40 と崩れるが、これは 3000 回の反復で収束しなかっただけで構造の差ではないので、比べる前に y も標準化する。

📋 アーキテクチャ別の特性比較

SSDSE-B-2026 のような「表形式・少量・564 行(47 県 × 12 年)」に対しては、 すべての DLA が等しく強いわけではない。 用途別の整理を下表にまとめる。

アーキテクチャ 得意な入力 弱点 SSDSE-B での適合度
MLP (全結合)表形式・固定長画像・系列で非効率◎
CNN (畳み込み)画像・空間データ表形式では機能薄い△ (擬似画像化が必要)
RNN/LSTM可変長系列・時系列長距離依存に弱い○ (年度を系列化した場合)
Transformer長系列・並列計算小データで過学習△ (47 行では能力過剰)
GNN (グラフ)関係性・隣接構造グラフ定義が必要○ (都道府県隣接で活用可)
AutoEncoder次元削減・異常検知監督なし、 評価困難○ (47 県の外れ値検出)

💬 SSDSE-B-2026 は表形式・47 行という典型的な「小規模・構造化データ」。 DLA を投入するなら MLP が第一選択であり、 CNN/Transformer を無理に当てはめても性能は出ない。 「アーキテクチャはデータの形に合わせる」という大原則を再確認できる。

📋 設計選択肢の対応表(用途別)

選択肢 候補 SSDSE-B での推奨
活性化関数ReLU / Tanh / GELU / SwishReLU (シンプル・高速)
最適化SGD / Adam / AdamW / RMSpropAdam (lr=0.001)
損失関数MSE / MAE / Huber / QuantileMSE (外れ値弱いなら Huber)
正則化L2 / Dropout / EarlyStop / BatchNormL2 + EarlyStop (Dropout は 47 行で過剰)
初期化He / Xavier / LeCun / ランダムHe (ReLU と相性)
バッチサイズ1 / 8 / 32 / フルフルバッチ (47 行で十分)

💬 小規模データではバッチサイズもフルで OK。 47 行を 32 件ずつ分割するメリットは無い。 バッチ正規化もデータ量が少なすぎると統計量が安定せず、 むしろ性能を悪化させることがある。

⚠️ 10. 深層学習の落とし穴

落とし穴 対処
テーブルに巨大 NNn < 10万なら GBDT が強い。 NN は構造化されたデータ向け。
乱数依存複数 seed で平均、 不確実性を報告。
過学習Dropout・Weight Decay・Data Aug・Early Stopping。
勾配消失/爆発残差接続・LayerNorm・勾配クリッピング・He初期化。
Transformer の長系列FlashAttention・スライディングウィンドウ・サブ二乗化。
事前学習モデルの fine-tune 失敗学習率を小さく(1e-5 等)、 warmup、 LoRA を検討。
model.eval() 忘れ推論時は必ず。 Dropout/BN の挙動が変わる。

🏋️ 11. 練習問題

注意:深層学習はテーブルデータの SSDSE-B 47 行では本領発揮しません。 公開画像・テキストデータセットを併用してください。

Q1. CIFAR-10 で簡単な CNN を実装し、 訓練データの一部だけを使って学習・評価しなさい。
1
2
3
4
5
6
7
import torch
import torchvision
from torchvision import transforms
trans = transforms.Compose([transforms.ToTensor()])
train = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=trans)
test = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=trans)
# 学習ループは前述の SimpleCNN を参考
📤 実行例(実測) このブロックは標準出力を出さない(図を描く・変数を定義するだけ)。
Q2. 日本語 BERT で文書分類のファインチューニングを行いなさい。
1
2
3
4
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer
tokenizer = AutoTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-v3')
model = AutoModelForSequenceClassification.from_pretrained('cl-tohoku/bert-base-japanese-v3', num_labels=2)
# Trainer で fine-tune
Q3. Attention の可視化を行い、 モデルがどこに注目しているか確認しなさい。

BERT/GPT 系の attention weights を可視化するライブラリ:bertviz, captum。 入力トークンと attention 行列のヒートマップで「どこに注目しているか」を観察。

📝 12. 報告フォーマット

❌ NG例

「Transformer を使って良い結果が出ました。」

✅ OK例

「日本語感情分類タスク(n_train=8,000、 n_test=2,000、 2クラス)で、 ベースライン LightGBM (TF-IDF) Macro-F1 = 0.78 に対し、 bert-base-japanese-v3 を batch_size=16, lr=2e-5, 3epoch で fine-tune した結果 0.91 を達成。 GPU は V100、 学習時間 12 分。 アテンション可視化で『否定語』周辺に強い注目が確認された。 過学習対策として early stopping (patience=2) を使用。」

⚠️ 深層学習の落とし穴(補強・各 100 文字以上)

① 表形式データに深層学習を強制する
表形式(n < 数万・少特徴)では LightGBM, XGBoost, CatBoost が深層学習を上回ることが多い。 「DL が一番」というのは画像・音声・テキストでの話。 表形式では TabNet・FT-Transformer など特殊アーキを使うか、 そもそも勾配ブースティングを基本にすべき。 適材適所が重要。
② 学習率を fine-tune せずに「Adam デフォルト」
Adam のデフォルト lr=1e-3 は多くのタスクで通用するが、 大規模事前学習モデルの fine-tune では lr=2e-5 〜 5e-5 が標準。 LR を変えずに精度が出ないと「モデルが悪い」と判断するのは早計。 LR finder, cosine schedule, warmup を活用する習慣を持つ。 LR 1桁の違いで結果が天と地ほど変わる。
③ BatchNorm を小バッチ・推論時に誤用
BatchNorm は学習時の running mean/var を推論時に使うが、 batch_size=2 など極小で学習すると統計が極端に不安定になる。 また model.eval() を忘れると推論時にも batch 統計が使われ、 結果が batch 内容で変わる。 Group/Layer Norm への切り替えや、 evaluation モード切替を厳密に管理する。
④ 検証データ・テストデータをリーク
画像分類で test 画像を train に混ぜたり、 同じ被験者のクリップを train/val に分けたりすると、 精度が嘘で高く出る。 Person-aware split, time-based split, kaggle のような fold 設計でリークを防ぐ。 不自然に高精度な結果は必ずリークを疑い、 データの出元と分割方法を確認する。
⑤ GPU メモリ不足を batch_size 増減で解決しようとする
batch_size を小さくして OOM を回避するだけだと学習が不安定に。 Gradient Accumulation で実効 batch を上げ、 Mixed-Precision (fp16/bf16) で半分のメモリで学習、 ZeRO/FSDP でモデル分散と、 段階的に対処手段がある。 H100 など最新 GPU の有無で取れる戦略が変わるので、 環境ベースで設計を。
⑥ 「early stopping = 過学習防止」と単純化
val loss が一時的に上がっても、 後で下がるパターン(double descent)がある。 patience を 3 などに小さくすると本当の最適点を逃す。 学習曲線を可視化し、 plateau・double descent を観察してから判断する。 LR scheduler と組み合わせ、 cosine の最後で再収束する場合は cosine 完走を許す。
⑦ Random seed のみで再現性を担保するつもり
torch.manual_seed だけでは GPU 演算(cuDNN)の非決定性、 multi-thread の dataloader 順番、 並列分散の reduction 順序などで結果が変わる。 torch.backends.cudnn.deterministic=True, num_workers の固定、 ハードウェアレベルの誤差を理解する。 完全な再現性は実際難しいので、 複数 seed で報告するのが論文標準。

⚠️ よくある落とし穴 — 深層学習(応用) で初学者がやりがちなミス

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

❌ 小データで巨大モデル
564 行(47 県 × 12 年)で Transformer 数億パラメータは過学習確実。 表データなら GBDT が無難。
❌ 解釈性の欠如
深層モデルはブラックボックス。 SHAP / Integrated Gradients で説明補完を。
❌ 評価の漏洩
同じ県の異年度を訓練・テストに分ければリーク。 県単位で分割。
❌ 過剰な計算資源
GPU で何時間も学習する前に、 線形モデル・GBDT のベースラインを必ず作る。
🛡 防御策まとめ:「適用条件の確認 → 適切な前処理 → 結果と前提のペア記述」の 3 ステップを習慣にすれば、 ここに挙げた失敗の大半は回避できます。

⚠️ よくある落とし穴(DLA 設計編)

📋 表: ハイパーパラメータ実測表(実装 4 の生データ)

arch params 数 CV R² 平均 CV R² 標準偏差 判定
(4,)210.98430.0030最小。それでも 0.98 台
(16,)810.98850.0038わずかに改善
(16,8)2090.99190.0022改善が続く
(32,16,8)8010.99480.0015さらに改善
(64,32,16,8)30090.99710.0004最良(同じ県の別年度を覚えられる)

💬 params 数は入力 3 列のとき (4,) の 21 から (64,32,16,8) の 3,009 まで増え、各 fold の訓練行数(約 451 行)を大きく超えても CV R² は下がらなかった。 行を無作為に分けた CV では同じ県の別年度が訓練側にあるので、パラメータの多さがそのまま「覚える力」として効いてしまう。 過学習を確かめるには、県単位で分ける GroupKFold のように、訓練に無い県で評価する必要がある。

📋 表: SSDSE-B-2026 実値による予測結果(2023 年度・抜粋 8 県、実装 2 の MLP)

都道府県 実測 (千人) 予測 (千人) 誤差
北海道5,0924,977-115
青森1,1841,479+295
東京14,08615,020+934
愛知7,4777,446-31
大阪8,7638,751-12
広島2,7382,967+229
沖縄1,4681,315-153
鳥取537705+168

💬 実装 2 の MLP(564 行すべてで学習)で 2023 年度の値を予測した結果。 8 県のうち誤差が最も大きいのは東京の +934 千人だが、実測比では鳥取の +168 千人(+31%)や青森の +295 千人(+25%)のほうが大きく、47 県全体では奈良(+64%)・山梨(+64%)・京都(+58%)が特に外れる。 学習に使った行でもこれだけずれるので、R²=0.99 は大きな県が支配した値である。 小規模県ほど相対誤差が大きい傾向は、 「不均衡データ」一般の特性。 大規模県だけ評価すれば すごく精度が高いように見えてしまう罠 → 層化サンプリングまたは サンプル重み付けで補正。

🗺 概念マップ

関連概念を視覚的に整理した概念マップ。

deep learning advanced S4 / S4D (2021 Mamba (2023) RWKV Mamba-2 / Hybr CLIP (2021) BLIP / BLIP-2

深層学習 (発展) は CNN/RNN を起点に、 Transformer (Attention is All You Need, 2017)、 BERT/GPT 系の自己回帰・双方向事前学習、 マルチモーダル (CLIP, BLIP, BLIP-2) へと拡張された系譜である。 近年は State Space Model (Mamba, RWKV) や Mamba-2 / Hybrid が二次計算量の Attention を線形に置き換える方向で進化し、 拡散モデル (DDPM) が生成タスクを席巻している。 これらは単なるアーキテクチャの集合ではなく、 「自己教師あり事前学習 + 下流タスクのファインチューニング」というパラダイムで統一されている。

🔗 隣接手法への橋渡し

「深層学習 (発展)」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。 具体的には次の 3 方向と密接につながる:

発展領域は基礎の上に積まれ、 LLM・生成 AI の社会実装へとつながる。

🌳 手法選択フロー

「深層学習の応用」を実際に使うとき、 何をどう選ぶかを順に判断する。 上から順に答えていくと、 使うべき手法と評価の仕方が決まる。

  1. データは何件あるか
    数万件を下回るなら、 まず勾配ブースティングや線形モデルを試す。 47 都道府県のような表データで深層学習を使う理由はほとんど無い。
  2. 学習済みモデルを使えるか
    画像・言語では、 ゼロから学習するより学習済みモデルの転移学習が速く、 少ないデータで済む。 ドメインが大きく違う場合だけ、 追加学習の範囲を広げる。
  3. 説明が必要か
    審査や政策の根拠にするなら、 何を根拠にしたかを示せる手法を選ぶ。 Grad-CAM や SHAP は手がかりであって、 根拠の証明ではない。
  4. 運用まで見通せているか
    学習より運用のほうが長く続く。 推論にかかる時間・費用、 モデルの更新頻度、 性能低下の検知方法を先に決める。

深層学習は「特徴を人が設計しなくてよい」代わりに、 データ量と計算量を要求する。 その 2 つが揃わない場面では、 単純な手法のほうが良い結果になる。

🔖 🔖 キーワード索引(チップから該当箇所へジャンプ)

論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:

なぜアーキテクチャ CNN 畳み込み プーリング ResNet U-Net RNN LSTM GRU Attention Self-Attention Transformer BERT GPT Vision Transformer 埋め込み 転移学習 ファインチューニング