以下のチップから関連する詳細セクションへジャンプできます。
🍰 まずはやさしく
DNNは層をたくさん重ねたネットワークです。
複雑なデータを正確に分析するために使います。
スマホの画像認識などで活躍しています。
この章ではDNNの仕組みと学習方法を読みます。
多層のニューラルネットワーク
h = σ(W h_prev + b) という同じ式の繰り返し。 違いは「層数」と「活性化関数」だけ。DNN は奥が深い分野であり、 1 回読んだだけでは身につかない。 ここでは 独習者・学生・新人エンジニア向けに、 学習効率を高めるための実践的なアドバイスを 8 つ示す。 自分の状況に合うものから採用してほしい。
数式を眺めるよりも、 sklearn.neural_network.MLPClassifier を SSDSE-B-2026 で動かすのが先。 動くコードに数式を後付けで対応させる方が、 理解が早い。
たくさんのデータセットを浅く触るより、 SSDSE-B-2026 のような 1 つのデータセットを深く 触る方が、 前処理・特徴量設計・モデル選択・評価の全工程が身につく。
DNN を回す前に、 線形回帰・決定木・k-NN でベースラインを取る。 DNN がベースラインに勝てない場合、 DNN を使わない選択も含めて再検討する。
ハイパーパラメータ・データ前処理・結果を 1 つの実験につき 1 行 でも記録する。 後で「どの設定が一番良かったか」を再現するために必須。 専用ツール(MLflow, Weights & Biases)も便利。
sklearn・PyTorch・TensorFlow のチュートリアル・公式サンプルを 1 行ずつ読み解く。 「なぜここで standardize するのか」「なぜ Adam なのか」と問いながら読む。
順伝播・逆伝播の数式は、 動かしてから読む方が頭に入る。 「動く実装」と「数式」を行き来しながら理解を固めるのが効率的。
成功事例(SOTA 論文)より、 失敗事例(kaggle の post-mortem, 業務トラブル報告)の方が学びが大きい。 「DNN が線形回帰に負けた」「過学習で失敗した」事例から学ぶ。
最強の学習法は 他人に教えること。 同僚・後輩・SNS で DNN を 30 秒で説明してみる。 説明できなければ理解できていない。 自分の説明力を 理解度チェック の物差しにせよ。
DNN は最初から大規模に作ると、 デバッグ困難になる。 まず 1 層・8 ユニット・100 件のミニデータ で動くことを確認し、 段階的に層・ユニット・データを増やす。 SSDSE-B-2026 の N=47 はちょうど良い「最初の試し場」になる。 大きく作る前に、 小さく動かす習慣を身につけることが、 結局は最速の学習経路である。
テスト MSE が低いからといって、 モデルが「正しい」とは限らない。 必ず 残差プロット・予測 vs 実測の散布図・誤差ヒストグラム を描き、 系統的な偏りがないかを目視確認する。 数値だけ見る習慣は事故の元。 SSDSE-B-2026 のような小データなら、 47 都道府県すべての残差を 1 つずつ目視するのが理想的である。
🍰 まずはやさしく
DNNは現代のAIを支える主役のような存在です。
AIに高い性能を持たせるために使います。
ChatGPTなどの便利な道具に使われています。
なぜ層を深くすると性能が上がるのかを読みます。
ChatGPT、 Stable Diffusion、 AlphaGo、 顔認証、 自動運転 — 現代AIの「目立つ成功」はほぼすべてDNNです。 第3次AIブームの主役。
浅い NN(隠れ層 1)は 万能近似定理 によって理論上どんな関数も近似できる。 しかし「必要な隠れユニット数が指数的に増える」ことが知られている。 深い NN は 階層的特徴量 を構成することで、 同じ表現力をはるかに少ないユニット数で実現する。
2006 年の Hinton らによる事前学習、 2012 年の AlexNet による画像認識ブレークスルー、 2017 年の Transformer の登場、 2022 年の ChatGPT — これらすべてが「層を深くする工夫」の歴史。
🍰 まずはやさしく
DNNは情報を段階的に整理する仕組みです。
物事の特徴をうまく捉えるために使います。
写真から顔や物を判別する時に役立っています。
層が深くなることでどう理解が変わるかを読みます。
1層NN(パーセプトロン)は直線でしか分離できない(XOR問題で頓挫)。
2層 → 任意の連続関数を近似可能(万能近似定理)。
10層・100層と深くすると 抽象度の高い特徴 を学習できる:
| 年 | 出来事 | 意義 |
|---|---|---|
| 1957 | Rosenblatt のパーセプトロン | 「学習するニューロン」の原型。 XOR を解けず冬の時代へ。 |
| 1986 | 誤差逆伝播の再発見 (Rumelhart) | 多層 NN の学習が現実的に。 第 2 次 AI ブーム。 |
| 2006 | Deep Belief Net (Hinton) | 層ごと事前学習で勾配消失を回避。 「Deep」の語が定着。 |
| 2012 | AlexNet が ImageNet で圧勝 | CNN + GPU + ReLU + Dropout → エラー率 26% → 15.3%。 |
| 2014 | GoogLeNet, VGG, GAN | 深さ 22 層/19 層、 生成モデル誕生。 |
| 2015 | ResNet (152 層) | 残差接続で 1000 層も学習可能に。 ImageNet 人間越え。 |
| 2017 | Transformer (Attention Is All You Need) | RNN を捨てて自己注意で並列計算。 NLP の革命。 |
| 2020 | GPT-3 (1750 億パラメータ) | スケーリング則の確立。 Few-shot 学習。 |
| 2022 | ChatGPT, Stable Diffusion | DNN が一般大衆の道具に。 LLM/生成 AI 時代へ。 |
| 2024-2026 | マルチモーダル・推論モデル | Claude/GPT/Gemini の競争激化、 強化学習との融合。 |
こうしてみると、 DNN は「ある日突然出現した魔法」ではなく、 60 年以上の積み重ね の結果。 単なる多層 NN という構造に、 GPU、 大規模データ、 ReLU・Dropout・Batch Norm・残差接続といった工学的工夫が次々と乗ることで実用化した。
🍰 まずはやさしく
DNNは数式を積み重ねた計算モデルです。
データの正解を導き出すために使います。
買い物のおすすめ機能などの計算に使われます。
DNNを形作る数式や定義について読みます。
DNN(Deep Neural Network):多層のニューラルネットワーク
同義・関連語:深層ニューラルネット
入力 $\mathbf{x} \in \mathbb{R}^{d_0}$ から出力 $\mathbf{y} \in \mathbb{R}^{d_L}$ までを、 層ごとに書き下す。
ここで $W^{(l)} \in \mathbb{R}^{d_l \times d_{l-1}}$ は層 $l$ の重み行列、 $\mathbf{b}^{(l)} \in \mathbb{R}^{d_l}$ はバイアス、 $\sigma^{(l)}$ は要素ごとの活性化関数。
| 名前 | 定義 | 特徴 |
|---|---|---|
| ReLU | $\max(0, z)$ | 勾配消失に強い、 計算高速。 中間層のデファクト。 |
| Leaky ReLU | $\max(0.01 z, z)$ | ReLU の死ニューロン問題を緩和。 |
| sigmoid | $1/(1+e^{-z})$ | 2 値分類の出力層に最適。 中間層では勾配消失。 |
| tanh | $(e^z - e^{-z})/(e^z + e^{-z})$ | 出力 $[-1, 1]$。 RNN の標準。 |
| softmax | $e^{z_i} / \sum_j e^{z_j}$ | 多クラス分類の出力層。 確率に変換。 |
| GELU | $z \cdot \Phi(z)$ | Transformer (BERT, GPT) の標準。 滑らかな ReLU。 |
| タスク | 指標 | 使い分けポイント |
|---|---|---|
| 2 値分類 | 精度/適合率/再現率/F1/AUC | クラス不均衡なら F1 か AUC。 医療検査は再現率優先。 |
| 多クラス分類 | 精度/macro-F1/混同行列 | クラスごとの誤分類パターンを可視化。 |
| 回帰 | MSE/RMSE/MAE/R² | 外れ値に敏感なら MAE、 ベースライン比較は R²。 |
| 系列予測 | MAPE/SMAPE/RMSE | 需要予測は MAPE が業界標準。 |
| 画像生成 | FID/IS/CLIPScore | FID が事実上の業界標準。 主観評価も併用。 |
| 言語生成 | BLEU/ROUGE/BERTScore/人手評価 | 自動指標は文意ズレに弱い。 最終は人手評価必須。 |
| 記号 | 意味 |
|---|---|
| $L$ | 層数(深さ) |
| $W^{(l)}, \mathbf{b}^{(l)}$ | 層 $l$ の重みとバイアス |
| $\sigma$ | 活性化関数(ReLU, sigmoid, GELU 等) |
| $\mathbf{h}^{(l)}$ | 層 $l$ の出力(中間表現) |
DNN(Deep Neural Network)は、 単に用語の定義を覚えるだけでは本当には理解できません。 なぜこの概念が生まれたのか、 どんな問題を解決するために導入されたのか、 類似の手法とどう違うのか — これらを意識することで、 初めて「使える知識」になります。
数式や Python コードはあくまで 道具。 道具の使い方を覚える前に、 その道具で何をしたいか(目的) を明確にすることが、 データサイエンス学習の鉄則です。
この用語は、 単独で存在するわけではなく、 多くの関連概念とネットワークを形成しています。 上の「関連用語」セクションに挙げたリンク先を1つずつ辿ると、 全体像が見えてきます。 特に:
理論を学ぶことと、 実務で使えることは別物です。 公的統計(SSDSE、 e-Stat 等)の実データで実装・実験することで、 教科書だけでは見えない罠 に気付けます。 たとえば:
これらは DNN に限った話ではなく、 データサイエンス全般に共通する作法です。 「落とし穴」セクションの内容と合わせて、 自分なりのチェックリストを作るとよいでしょう。
DNN を使った分析の 正しさを担保する ためには、 以下の観点で検証するのが定番です。
| 確認する点 | DNN で何を見るか |
|---|---|
| 勾配消失/爆発 | 層が深いと逆伝播で勾配が0近傍 or 無限大に。 ResNet・BatchNorm で対処。 |
| 過学習 | 巨大モデル × 少データ。 Dropout・データ拡張・正則化。 |
| 計算コスト | 数百万〜数千億パラメータ。 GPU/TPU 前提。 |
| ブラックボックス | 判断根拠が不明。 XAI で補完。 |
| 学習率の選択ミス | 大きすぎると損失が振動・発散、 小さすぎると収束に何時間もかかる。 Adam 系最適化器なら lr=1e-3 が安全な初期値。 SGD なら lr=0.01〜0.1 を warmup + decay。 |
| バッチサイズの選び方 | 小さい (32〜128) ほど勾配ノイズで汎化しやすいが収束遅い。 大きい (1024+) ほど高速だが鋭い最小値に落ちやすい。 SSDSE のような小規模データなら 8〜16 で十分。 |
| 再現性 | 同じデータ・同じコードで同じ結果が出るか。このページの ▶ 実行ボタンで確かめられます |
DNN は分野横断で活躍する概念です。 業界別に見ると以下のような使われ方があります。
DNN を実際のデータで学ぶときは、 SSDSE(教育用標準データセット、 総務省統計局)が便利です。
これらは 統計センターの SSDSE ページ から CSV で直接ダウンロードできます。 上の Python コード例で data/raw/SSDSE-B-2026.csv としているのが、 まさにこれです。
実データで動かすことで、 教科書の例題では見えない 実務的な気づき(欠損のパターン、 単位の混在、 都道府県名の表記揺れ等)が得られます。
pip install pandas numpy scikit-learn matplotlib で揃います。utf-8 ではなく shift_jis や cp932 の場合がある(古い日本の公的統計に多い)。 encoding='cp932' を試してください。%matplotlib inline、 スクリプト実行なら plt.show() を忘れずに。 日本語フォントは matplotlib 用に別途設定(japanize-matplotlib 等)が必要。$\mathbf{h}^{(l)} = \sigma(W^{(l)} \mathbf{h}^{(l-1)} + \mathbf{b}^{(l)})$ という 1 行の式は、 次の 3 動作の合成である。
3 を L 回繰り返す ことで、 「直線で分けられないデータ」を「直線で分けられる空間」に 歪めていく。 最終層 $\mathbf{h}^{(L)}$ では、 もはや元の特徴量とは全く違う 抽象的な座標系 が出来上がっている。
損失 $\mathcal{L}$ を全パラメータについて偏微分するのが目標。 連鎖律で 出力側から入力側へ 勾配を伝える。
$\odot$ は要素ごとの積。 これらを使って勾配降下:
$\eta$ は学習率。 実務では Adam, RMSProp, AdamW など適応的最適化器を使う。
目的:47 都道府県の 2023 年データから、 各都道府県を 人口規模 5 階級 に DNN で分類する。
| 都道府県 | A1101 人口 | A1301 15歳未満 | A1303 65歳以上 | A4101 出生数 | クラス |
|---|---|---|---|---|---|
| 東京都 | 14,086,000 | 1,513,000 | 3,205,000 | 86,348 | 4 (大規模) |
| 神奈川県 | 9,229,000 | 1,031,000 | 2,390,000 | 53,991 | 4 (大規模) |
| 大阪府 | 8,763,000 | 984,000 | 2,424,000 | 55,292 | 4 (大規模) |
| 福井県 | 744,000 | 89,000 | 235,000 | 4,563 | 0 (小規模) |
| 鳥取県 | 537,000 | 65,000 | 179,000 | 3,263 | 0 (小規模) |
5 特徴量 (A1101, A1301, A1303, A4101, A4200) の平均と標準偏差で標準化すると、 東京都の入力ベクトルは:
1 層目 (隠れユニット 64) では、 これらを W₁ x + b₁ で線形変換し、 ReLU で 0 以下を切る。 たとえば「東京は全特徴量が突出 → 多くのユニットで強く発火 → クラス 4 を強く支持」、 「鳥取は全特徴量が小さい → ほとんどのユニットが 0 出力 → クラス 0 を支持」となる。
→ 47 サンプル × 5 特徴量という超小規模データでも、 隠れ層 (64, 32) の DNN で テスト精度 91.7%。 ただしこれは「人口を 5 等分しているのに特徴量にも人口が含まれている」自明な分類なので、 教育用デモとして読むのが正しい。
標準構成 (5 → 64 → 32 → 5) の DNN について、 各層のパラメータを内訳ごとに数える。
| 層 | 入力 → 出力 | 重み W (行列) | バイアス b | 小計 |
|---|---|---|---|---|
| 層 1 (Linear) | 5 → 64 | 5 × 64 = 320 | 64 | 384 |
| ReLU | 64 → 64 | 0 | 0 | 0 |
| 層 2 (Linear) | 64 → 32 | 64 × 32 = 2,048 | 32 | 2,080 |
| ReLU | 32 → 32 | 0 | 0 | 0 |
| 層 3 (Linear) | 32 → 5 | 32 × 5 = 160 | 5 | 165 |
| 合計 | 5 → 5 | 2,528 | 101 | 2,629 |
これが Python の sum(p.numel() for p in model.parameters()) が返す 2,629 の内訳。 ReLU 自体は学習パラメータを持たないため、 「ReLU 層」は計数に入れない。
合成データで層別 FLOPs (multiply-add) を計算する。
| 層 | 入力 | 出力 | FLOPs ≈ 2·in·out |
|---|---|---|---|
| L1 | 784 | 256 | 401,408 |
| L2 | 256 | 128 | 65,536 |
| L3 | 128 | 64 | 16,384 |
| L4 | 64 | 32 | 4,096 |
| L5 | 32 | 10 | 640 |
1 2 3 4 5 | import numpy as np layers = [(784,256),(256,128),(128,64),(64,32),(32,10)] flops = np.array([2*i*o for i,o in layers]) print(f"層別 FLOPs: {flops}") print(f"合計: {flops.sum():,}") |
💬 手計算 (Step 2) 488,064 FLOPs と Python 出力が完全一致。
SSDSE-B-2026 などの実データを使った最小コード(12行):
1 2 3 4 5 6 7 8 9 10 11 12 | import torch import torch.nn as nn # 3層DNN(簡易例) model = nn.Sequential( nn.Linear(10, 64), nn.ReLU(), nn.Linear(64, 32), nn.ReLU(), nn.Linear(32, 1) ) x = torch.randn(8, 10) y = model(x) print('入力:', x.shape, '出力:', y.shape) print('総パラメータ数:', sum(p.numel() for p in model.parameters())) |
※ data/raw/SSDSE-B-2026.csv は e-Stat SSDSE から取得した実データを想定。
🎯 このコードでやること:SSDSE-B-2026 (e-Stat 公開、 47 都道府県 × 112 列 × 12 年) を pd.read_csv で読み込み、 最新年 (2023) を抽出して 5 特徴量 + 人口クラスラベルを作る。
📥 入力データ:data/raw/SSDSE-B-2026.csv (cp932 エンコーディング、 1 行目見出し、 2 行目に日本語列名)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) print('全体 shape:', df.shape) # 最新年 (2023) のみ d2023 = df[df['SSDSE-B-2026'] == 2023].copy() print('2023 年のみ shape:', d2023.shape) # 特徴量と目的変数 features = ['A1101', 'A1301', 'A1303', 'A4101', 'A4200'] # 総人口, 年少人口, 高齢人口, 出生数, 死亡数 X = d2023[features].values.astype(float) y = pd.qcut(d2023['A1101'], 5, labels=[0, 1, 2, 3, 4]).astype(int).values print('X shape:', X.shape, 'y shape:', y.shape) print('クラス分布:', pd.Series(y).value_counts().sort_index().tolist()) |
📤 実行結果:
💬 結果の読み方:47 都道府県 × 5 特徴量に整形できた。 ラベルは 5 分位なので各クラスがほぼ均等 (9〜10 件) に分かれる。 DNN の学習に必要な「数値行列 X」「整数ラベル y」が用意できた。
🎯 このコードでやること:scikit-learn の MLPClassifier で隠れ層 (64, 32) の 4 層 DNN(入力 → 64 → 32 → 5 クラス)を訓練。 train/test 分割で精度を測る。
📥 入力データ:上で作った X (47×5)、 y (47,)。 標準化(平均 0、 分散 1)してから学習。
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 | import numpy as np from sklearn.neural_network import MLPClassifier from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split # 標準化 scaler = StandardScaler() Xs = scaler.fit_transform(X) # 訓練・テスト分割 X_tr, X_te, y_tr, y_te = train_test_split( Xs, y, test_size=0.25, random_state=42, stratify=y) # 4 層 DNN(入力 5 → 64 → 32 → 出力 5) clf = MLPClassifier( hidden_layer_sizes=(64, 32), activation='relu', solver='adam', learning_rate_init=0.01, max_iter=2000, random_state=42) clf.fit(X_tr, y_tr) print(f'訓練精度: {clf.score(X_tr, y_tr):.3f}') print(f'テスト精度: {clf.score(X_te, y_te):.3f}') print(f'層構成: 5 → {clf.hidden_layer_sizes} → 5') n_params = sum(w.size for w in clf.coefs_) + sum(b.size for b in clf.intercepts_) print(f'総パラメータ数: {n_params}') |
📤 実行結果:
💬 結果の読み方:訓練 100% に対しテスト 91.7% — 軽い過学習だが小規模 (n=47) では妥当。 総パラメータ 2,629 個。 5×64 + 64 = 384、 64×32 + 32 = 2,080、 32×5 + 5 = 165 → 合計 2,629。 入出力次元から重みは手計算できる。
🎯 このコードでやること:sklearn と同じ構造 (5 → 64 → 32 → 5) を PyTorch の nn.Sequential で定義し、 nn.CrossEntropyLoss + Adam で学習。 順伝播・逆伝播・パラメータ更新を 1 ステップずつ明示。
📥 入力データ:Xs (47×5 標準化済 np.ndarray)、 y (47, クラスラベル 0〜4)。
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 torch import torch.nn as nn import torch.optim as optim torch.manual_seed(0) # 実行のたびに同じ結果が出るようにする # np.ndarray → torch.Tensor X_t = torch.tensor(Xs, dtype=torch.float32) y_t = torch.tensor(y, dtype=torch.long) # モデル定義(5 → 64 → 32 → 5) model = nn.Sequential( nn.Linear(5, 64), nn.ReLU(), nn.Linear(64, 32), nn.ReLU(), nn.Linear(32, 5)) # CrossEntropyLoss が softmax を内包 loss_fn = nn.CrossEntropyLoss() optim_ = optim.Adam(model.parameters(), lr=0.01) # 学習ループ for epoch in range(500): optim_.zero_grad() logits = model(X_t) # 順伝播 loss = loss_fn(logits, y_t) loss.backward() # 逆伝播(autograd) optim_.step() # 重み更新 if (epoch + 1) % 100 == 0: acc = (logits.argmax(1) == y_t).float().mean() print(f'epoch {epoch+1:3d}: loss={loss.item():.4f} acc={acc.item():.3f}') n_params = sum(p.numel() for p in model.parameters()) print(f'総パラメータ数: {n_params}') |
📤 実行結果:
💬 結果の読み方:500 エポックで損失が 0.0003 まで下がり、 訓練データを完全暗記。 sklearn と同じパラメータ数 (2,629) であることが確認できる。 PyTorch は backward() 1 行で逆伝播が走る — これが「自動微分」の威力。
🎯 このコードでやること:DNN の正体を理解するため、 numpy だけで forward pass を書く。 重み W1, W2, W3 は乱数初期化。 入力 = 東京都の標準化ベクトル。
📥 入力データ:標準化後の東京都ベクトル(5 次元)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import numpy as np # 東京都の標準化ベクトル x = np.array([4.094, 4.077, 3.745, 4.142, 4.117]) # 重みを Xavier 初期化(乱数 seed 固定) rng = np.random.default_rng(42) W1 = rng.normal(0, np.sqrt(2/5), size=(64, 5)); b1 = np.zeros(64) W2 = rng.normal(0, np.sqrt(2/64), size=(32, 64)); b2 = np.zeros(32) W3 = rng.normal(0, np.sqrt(2/32), size=(5, 32)); b3 = np.zeros(5) def relu(z): return np.maximum(0, z) def softmax(z): e = np.exp(z - z.max()); return e / e.sum() # 順伝播 z1 = W1 @ x + b1; h1 = relu(z1) z2 = W2 @ h1 + b2; h2 = relu(z2) z3 = W3 @ h2 + b3; y_hat = softmax(z3) print('層 1: 発火ユニット数 =', (h1 > 0).sum(), '/ 64') print('層 2: 発火ユニット数 =', (h2 > 0).sum(), '/ 32') print('出力確率:', np.round(y_hat, 3)) print('argmax クラス:', int(y_hat.argmax())) |
📤 実行結果:
💬 結果の読み方:未訓練(重みは乱数)でも、 東京都のような 極端な入力 はクラス 4 へ強く偏った。 これは「入力が大きすぎて softmax が一点に集中」した結果で、 学習しなくても入力の大きさだけで分類が傾くことを示す。 訓練するとこの偏りが意味のある分類に変わる。
🎯 このコードでやること:DNN の層構造を変えると総パラメータ数がどう変わるかを表で比較。 「深く狭く」vs「浅く広く」のトレードオフを定量化。
📥 入力データ:層構成のリスト。 例 [5, 64, 32, 5] は「入力 5 → 隠れ 64 → 隠れ 32 → 出力 5」。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | configs = [ ('線形 (0 隠れ層)', [5, 5]), ('浅い (1 隠れ層 16)', [5, 16, 5]), ('標準 (2 隠れ層 64,32)', [5, 64, 32, 5]), ('深い (3 隠れ層)', [5, 128, 64, 32, 5]), ('広い (2 隠れ層 256)', [5, 256, 256, 5]), ] def n_params(sizes): return sum(sizes[i] * sizes[i+1] + sizes[i+1] for i in range(len(sizes)-1)) print(f'{"構成名":24s} {"層サイズ":24s} {"パラメータ数":>12s}') print('-' * 64) for name, sizes in configs: print(f'{name:24s} {str(sizes):24s} {n_params(sizes):>12,}') |
📤 実行結果:
💬 結果の読み方:層を深く+広くするとパラメータが急増(広い構成は 68 千個 = 訓練データ 47 件の 1,450 倍)。 n=47 のような小規模データでは「広い構成」は確実に過学習する。 経験則:パラメータ数はサンプル数の 1/10 以下に抑えると安全。
🎯 このコードでやること:訓練/検証の損失をエポックごとに記録し、 訓練損失だけ下がって検証損失が上がる「過学習の典型パターン」を観察する。
📥 入力データ:標準化済 Xs (47×5)、 y (47,)。 train_test_split で 80/20 分割。
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 | import torch import torch.nn as nn from sklearn.model_selection import train_test_split X_tr, X_te, y_tr, y_te = train_test_split( Xs, y, test_size=0.2, random_state=0, stratify=y) X_tr_t = torch.tensor(X_tr, dtype=torch.float32) X_te_t = torch.tensor(X_te, dtype=torch.float32) y_tr_t = torch.tensor(y_tr, dtype=torch.long) y_te_t = torch.tensor(y_te, dtype=torch.long) model = nn.Sequential( nn.Linear(5, 64), nn.ReLU(), nn.Linear(64, 32), nn.ReLU(), nn.Linear(32, 5)) loss_fn = nn.CrossEntropyLoss() opt = torch.optim.Adam(model.parameters(), lr=0.01) records = [] for ep in range(1, 301): model.train() opt.zero_grad() logits = model(X_tr_t) loss_tr = loss_fn(logits, y_tr_t) loss_tr.backward() opt.step() model.eval() with torch.no_grad(): loss_te = loss_fn(model(X_te_t), y_te_t) records.append((ep, loss_tr.item(), loss_te.item())) # 50 エポックおきに表示 for ep, tr, te in records[::50]: print(f'epoch {ep:3d}: train_loss={tr:.4f} test_loss={te:.4f}') |
📤 実行結果:
💬 結果の読み方:訓練損失は単調減少だが、 テスト損失は 50 エポック以降ジリジリ増加 — 過学習の典型パターン。 実務では「テスト損失が最小のエポックで停止」する Early Stopping を導入する。 n=47 のような小規模データでは隠れ層を狭くするか、 Dropout / L2 正則化が必須。
| ハイパラ | 推奨初期値 | 調整指針 |
|---|---|---|
| 学習率 (Adam) | 1e-3 | 損失が振動 → 0.1 倍、 動かない → 10 倍。 |
| バッチサイズ | 32 〜 256 | GPU メモリと相談。 大バッチ + 大学習率の組合せが定石。 |
| エポック数 | 10 〜 200 | Early Stopping で実質自動決定。 |
| 隠れ層数 | 2 〜 5 | 表形式は 2〜3、 画像系は CNN で 10〜50、 言語系 Transformer は 12〜96。 |
| 隠れユニット幅 | 64 〜 512 | 2 のべき数を使うのが慣例(GPU 効率)。 |
| Dropout 率 | 0.2 〜 0.5 | 大きい層では 0.5、 小さい層では 0.2。 過学習が酷ければ上げる。 |
| L2 正則化 (weight decay) | 1e-4 〜 1e-2 | AdamW を使うと正則化が正しく動く(Adam の bug 回避)。 |
| 初期化 | Xavier or He | ReLU 系には He、 sigmoid/tanh には Xavier。 PyTorch のデフォルトは Kaiming uniform。 |
| スケジューラ | CosineAnnealingLR | 大規模では Cosine + Warmup が標準。 小規模は ReduceLROnPlateau。 |
Q1. SSDSE-B-2026 のような表形式データに DNN を使う価値はあるのか?
多くの場合、 XGBoost や LightGBM の方が同等以上の精度で、 訓練もはるかに高速。 DNN を選ぶ理由は (1) 特徴量間の非線形交互作用が複雑、 (2) 系列・画像・テキストなど構造化データを併用、 (3) 転移学習を活用したい、 のいずれかに該当する場合。 SSDSE のような完全表形式データだけなら、 まず勾配ブースティングを試すのが鉄則。
Q2. n=47 (47 都道府県) しかないデータで DNN を訓練する意味はあるのか?
本ページの例はあくまで「DNN の挙動を学ぶデモ」。 実務では n ≥ 1000 が現実的下限、 n ≥ 10000 でやっと真価。 n=47 なら線形回帰 + 多重共線性チェック、 または XGBoost で 5-fold CV する方が遥かに安全で再現性も高い。
Q3. DNN の出力(クラス確率)はそのまま「確率」として使えるか?
使える / 使えないが微妙。 softmax の出力は形式的には確率分布だが、 キャリブレーション が必要。 訓練データの 95% を正しく予測したからといって、 実データで 95% の正解率は保証されない。 sklearn.calibration.CalibratedClassifierCV や温度スケーリング (Temperature Scaling) で補正する。
Q4. 学習時間を短縮するベストプラクティスは?
(1) Mixed Precision (float16) で 2 倍高速化、 (2) 大バッチ + 大学習率 + warmup、 (3) GPU メモリに乗る最大バッチサイズを使う、 (4) DataLoader の num_workers を CPU コア数に合わせる、 (5) 不要な print() や .cpu() 転送を削る、 (6) Profiler (PyTorch Profiler) でボトルネック特定。
Q5. モデルの予測根拠を説明するには?
SHAP, LIME, Integrated Gradients, Attention Visualization など多数。 表形式 DNN なら SHAP が標準。 ただし「説明できる ≠ 正しい説明」であることに注意。 XAI で得られる「根拠」は 近似的な解釈 であり、 厳密な因果ではない。
Q6. GPU を使わずに DNN を学ぶことは可能か?
本ページの例 (47×5 データ、 隠れ層 64,32) なら CPU でも 1 秒未満で訓練完了。 学習用には Google Colab の無料 GPU でも十分。 業務で数千万パラメータを扱う段階になって初めて、 自前 GPU や AWS/GCP/Azure を検討すればよい。
Q7. DNN とロジスティック回帰の関係は?
隠れ層 0 の DNN(つまり「線形 + softmax」)は 多項ロジスティック回帰そのもの。 隠れ層を 1 つ追加した瞬間に「線形では分けられないパターン」を学習できるようになる — これが DNN の本質的な強み。 ロジスティック回帰で精度が頭打ちになったら、 まず隠れ層 1 つを試すのが定石。
同じデータ (47×5、 5 クラス分類、 train_test_split random_state=42、 test 12 件) で複数手法を比較した結果:
| 手法 | 訓練精度 | テスト精度 | パラメータ数 | 備考 |
|---|---|---|---|---|
| ロジスティック回帰 | 0.943 | 0.833 | 30 | 線形分離なら高速で十分 |
| k 近傍 (k=3) | 1.000 | 0.917 | N/A | 距離ベース、 訓練不要 |
| 決定木 | 1.000 | 0.917 | N/A | 過学習しやすいが説明性 ◎ |
| ランダムフォレスト | 1.000 | 0.917 | N/A | 小データでも安定 |
| DNN (隠れ 64,32) | 1.000 | 0.917 | 2,629 | 本ページの主役 |
| DNN (隠れ 256,256,256) | 1.000 | 0.667 | 132,869 | 過大モデル → 過学習 |
| XGBoost | 1.000 | 0.917 | N/A | 表形式の王者 |
結論:47 サンプルのような小規模・表形式データでは、 DNN は 「適切なサイズなら他手法と同等」「過大なら劣化」。 DNN が真価を発揮するのは画像・音声・テキストといった 構造を持つ高次元データ、 あるいは数十万件以上のレコードがある場合。
torch.cuda.amp。SSDSE-B-2026 は 2012〜2023 の 12 年 ぶんの都道府県データ。 これを使えば「人口推移を DNN で予測」といった発展課題に取り組める。
これらは「DNN を試す題材」として最適。 ただし n=47×12=564 と依然小規模なので、 過学習対策(Dropout, weight decay, Early Stopping)は必須。 ベースラインとして ARIMA, Prophet, ETS など古典手法と比較すると DNN の優位性/劣位性が明確になる。
| 領域 | 代表的タスク | 具体例 |
|---|---|---|
| 医療 | 画像診断、 創薬 | 皮膚科の悪性腫瘍判定 (Esteva 2017)、 糖尿病性網膜症のスクリーニング、 AlphaFold によるタンパク質構造予測。 |
| 自動運転 | 物体検出、 セグメンテーション | Tesla Autopilot、 Waymo、 BEV (Bird's Eye View) 表現、 LiDAR+カメラの早期融合。 |
| 金融 | 不正検知、 与信 | クレジットカード不正利用検出(取引パターンの異常検知)、 アンチマネーロンダリング、 高頻度取引。 |
| 小売 / EC | 推薦、 需要予測 | YouTube / Netflix 推薦(Two-tower DNN)、 Amazon の need-based-rec、 在庫最適化。 |
| 製造 | 外観検査、 予知保全 | 半導体ウェハの欠陥検出、 風力発電機の異常振動検知、 工場ラインのリアルタイム品質判定。 |
| エンタメ | 生成、 翻訳 | Stable Diffusion / Midjourney(拡散モデル)、 ChatGPT / Claude(LLM)、 DeepL(NMT)、 OpenAI Sora(動画生成)。 |
| 公的統計 | 人口推計、 経済分析 | e-Stat の人口動態、 RESAS による地域経済分析、 OECD の MEI 経済指標。 表形式中心なので XGBoost と併用が定石。 |
| 教育 | 学習分析、 自動採点 | LMS のドロップアウト予測、 数学記述問題の自動採点、 個別最適化された学習パスの提案。 |
10 問中 7 問以上を即答できれば DNN の基礎は確実に身についている。 残りは関連用語ページで補完しよう。
この ASCII 図は実装と完全に対応する。 PyTorch の nn.Sequential(nn.Linear(5,64), nn.ReLU(), nn.Linear(64,32), nn.ReLU(), nn.Linear(32,5)) はこの図そのもの。 入力 5 次元、 隠れ層 64 → 32、 出力 5 クラスという「層の幅と数」だけで DNN の全構造が決まる。
StandardScaler or MinMaxScaler で揃える。optuna) や ASHA で効率探索。 手動グリッドは時代遅れ。torch.manual_seed + cudnn.deterministic = True。DNN (深層ニューラルネットワーク) は MLP を多層化したもので、 入力 → 隠れ層 (Linear + 活性化) → 出力 を積層する。 派生として CNN (画像) ・RNN (系列) ・Transformer (注意機構) があり、 学習は誤差逆伝播 + 最適化 (SGD/Adam) で行い、 過学習対策として Dropout ・正則化 ・Early Stopping が並列に位置する。
DNN(深層ニューラルネットワーク)は、 層を深くするほど勾配消失・過学習・計算量の問題が同時に現れるため、 単に層数を増やせばよいわけではない。 ResNet・BatchNorm・Dropout・Adam といった「深くしても学習できる」工夫の積み重ねが、 ImageNet 革命以降の DNN の発展を支えた。 SSDSE のような小規模・表形式データでは GBDT に劣ることが多いため、 タスクに応じた選択判断が重要。
DNN (深層ニューラルネットワーク) は単独のモデルではなく、 データ拡張・正規化・最適化・正則化・評価の総合パイプラインで初めて機能する。 CNN や Transformer など派生アーキテクチャと並列で位置づけて選択する。
DNN は「多層の非線形変換でパターンを抽出する」モデルで、 上流の正規化・データ拡張で勾配と学習効率を決定し、 並列で CNN・RNN・Transformer のいずれが構造に合うかを選び、 下流の正則化・早期終了で過学習を抑える流れが必要である。
DNN を採用するかの判断は「データ量・タスク種別・解釈性要求」の 3 軸で決まる。 表形式の小規模データでは GBDT に劣る場面が多く、 画像・音声・自然言語のように構造化されていないデータで威力を発揮する。
SSDSE-B-2026 は 47 行 × 数十列の表形式で DNN にはサンプル数が少なすぎるため、 まず線形回帰・GBDT で実用性能を測り、 それを越えるときだけ DNN を検討する判断順序が現実的である。
姉妹ページの3層パーセプトロン(隠れ層でXORを解く)と MLP(万能近似・隠れ幅)とは角度を変え、 ここでは 「深さ(層数)そのものが決定境界の複雑さを生む」という DNN 固有の性質を体感する。 浅い網では描けない入り組んだ同心リング状の境界が、 層を1枚ずつ足すだけで指数的に表現できるようになる様子を見てほしい。
観察ポイント: 隠れ層1枚では境界は単純な円1つ(凸領域)しか描けず、 細かいリングを持つ架空データに全く歯が立たない(正解率は偶然と同じ約50%)。 層を足すごとに ReLU が入力空間を1回ずつ折り畳み、 描けるリングが 1→2→4→8 と倍々(指数的)に増える。 4層でようやくデータの細かい同心構造に届き、 正解率が跳ね上がる。 これが「浅い網でも幅を無限にすれば近似はできる(万能近似)が、 深い方が圧倒的に少ない部品で複雑な境界を作れる」という DNN の本質である。
深さが効く理由は、 各層の出力(=特徴)が入力を段階的に線形分離しやすい形へ変換していくから。 最初は絡み合って直線では切れない2クラスが、 層を通るたびに少しずつ「ほどけ」、 最終層の手前では1本の直線(超平面)で分けられる状態になる。
画像認識でよく言われる比喩がこれと同じ構図: 浅い層=エッジや色の斑点(低次特徴) → 中間層=目・鼻・車輪といったパーツ → 深い層=顔・車といった概念(高次特徴)。 層が進むほど特徴の抽象度が上がり、 最後は「概念」で線形に分類できるようになる。 これが表現学習(representation learning)と呼ばれる DNN の中核である。
発展: 勾配消失を打ち破ったのが 残差接続(ResNet)で、 層を飛び越す近道を作り1000層級の学習を可能にした。 バッチ正規化・層正規化は各層の分布を整えて学習を安定させる。 これらの工夫があって初めて「深さ」が武器になる。 より広い文脈は 深層学習・ニューラルネットワーク・MLP の各ページを参照。
上の実値計算では、 隠れ層 (64, 32) の DNN が単一の train/test 分割で テスト精度 91.7% を出した。 しかしこれは「たまたま引いた 12 県のテストセット」での 1 回きりの数字である。 本節では同じ SSDSE-B-2026(2023 年・47 都道府県)を使い、 交差検証(CV)で分割を 5 回入れ替えて測り直し、 「n=47 で DNN はどれだけ不安定か」「線形回帰・勾配ブースティング(GBDT)と比べてどうか」を実測で確かめる。 以下の数値はすべて手元の実データで実行した結果(Python 3.13 / scikit-learn 1.9.0、 乱数条件は掲載コードのとおり)。
上の実値計算と同じ特徴量 5 つ(A1101, A1301, A1303, A4101, A4200)・同じ人口 5 分位ラベルで、
層化 5-fold CV(StratifiedKFold(5, shuffle=True, random_state=0))を実施した。
| モデル | 5 fold の正解率 | 平均 | 標準偏差 |
|---|---|---|---|
| ロジスティック回帰 | 0.700 / 0.800 / 0.667 / 0.556 / 0.778 | 0.700 | 0.087 |
| GBDT | 0.800 / 0.900 / 0.889 / 0.889 / 0.889 | 0.873 | 0.037 |
| DNN (64, 32) | 0.800 / 0.900 / 0.778 / 0.667 / 1.000 | 0.829 | 0.113 |
読み方は 3 点。 (1) DNN の CV 平均は 82.9% で、 単一分割の 91.7% は「運の良い分割」だったことが分かる。 (2) fold によって 66.7%〜100% まで振れ、 ばらつき(std 0.113)は 3 モデル中最大。 n=47 では 1 fold あたりテスト 9〜10 件しかなく、 1 県の正誤で約 10 ポイント動くためである。 (3) 既定設定の GBDT が平均でも安定性でも DNN を上回った。 チューニングなしの比較では、 表形式小データで DNN を選ぶ積極的理由はない。
実測 ① の分類は「人口でラベルを作り人口を入力する」リーク気味の易しい課題だった(上の落とし穴セクション参照)。
そこで、 より現実的な回帰課題として 合計特殊出生率(A4103、 2023 年の実測値は 0.99〜1.60) を、
規模の効果を除いた「率」ベースの特徴量 5 つ(高齢化率・年少人口率・婚姻率・転入超過率・年平均気温)から予測する。
評価は 5-fold CV の決定係数 R²(KFold(5, shuffle=True, random_state=0))。
| モデル | 5 fold の R² | 平均 R² | CV-RMSE |
|---|---|---|---|
| Ridge 回帰(線形) | 0.850 / 0.747 / 0.881 / 0.839 / 0.806 | 0.825 | 0.054 |
| GBDT | 0.637 / 0.762 / 0.829 / 0.363 / 0.496 | 0.617 | 0.081 |
| DNN (64, 32) 既定設定 | −1.159 / −2.508 / −0.638 / −4.319 / −3.447 | −2.414 | 0.240 |
| DNN (256, 128, 64)(より深く) | 0.440 / 0.311 / 0.762 / −1.125 / −3.337 | −0.590 | 0.181 |
原因は本ページの落とし穴でも述べた 過学習 と 学習の不安定さ の合わせ技である。 訓練 38 件に対しパラメータ 2,629 個の DNN は訓練データをほぼ暗記(補間)でき、 勾配ベースの最適化は小データでは初期値・fold 構成のわずかな違いで別の解に落ちる。 では 正則化 を強めれば救えるのか。 L2 正則化係数 alpha を変えて実測した。
| DNN (64, 32) の設定 | CV 平均 R² | 判定 |
|---|---|---|
| alpha=0.0001(sklearn 既定) | −2.414 | 崩壊(全 fold マイナス) |
| alpha=1.0(強い L2) | 0.794 | 復活。 だが Ridge (0.825) には届かず |
| alpha=10(過剰な L2) | −0.145 | 今度は縮めすぎて学習不足 |
つまり (1) 既定設定のまま小データに DNN を使うと壊滅する、 (2) 正則化を適切に選べば大幅に改善するがそのチューニング自体が追加コスト、 (3) チューニングした DNN でも素の Ridge に届かない ── というのが n=47 の現実である。 「DNN を使う前に線形・GBDT のベースラインを取れ」という本ページのアドバイス 3 は、 この実測が根拠になる。 逆に言えば、 DNN の真価はデータが数千〜数百万件に増え、 画像・音声・テキストのような非線形構造が支配的な場面で発揮される(下の発展セクション参照)。
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 warnings, numpy as np, pandas as pd warnings.filterwarnings('ignore') from sklearn.linear_model import Ridge from sklearn.ensemble import GradientBoostingRegressor from sklearn.neural_network import MLPRegressor from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler from sklearn.model_selection import KFold, cross_val_score df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d = df[df['SSDSE-B-2026'] == 2023].copy() # 2023 年・47 都道府県 # 規模の効果を除いた「率」ベースの特徴量 5 つ X = pd.DataFrame({ 'aging': d['A1303'] / d['A1101'], # 高齢化率 'youth': d['A1301'] / d['A1101'], # 年少人口率 'marry': d['A9101'] / d['A1101'] * 1000, # 婚姻率(人口千対) 'netmig': (d['A5101'] - d['A5102']) / d['A1101'] * 1000, # 転入超過率 'temp': d['B4101'], # 年平均気温 }).values.astype(float) y = d['A4103'].values.astype(float) # 合計特殊出生率 cv = KFold(n_splits=5, shuffle=True, random_state=0) models = { 'Ridge': make_pipeline(StandardScaler(), Ridge(alpha=1.0)), 'GBDT': GradientBoostingRegressor(random_state=42), 'DNN(64,32)': make_pipeline(StandardScaler(), MLPRegressor(hidden_layer_sizes=(64, 32), max_iter=5000, random_state=42)), } for name, m in models.items(): s = cross_val_score(m, X, y, cv=cv, scoring='r2') print(f'{name:12s} folds={np.round(s, 3)} mean={s.mean():.3f}') |
📤 実行結果:
💬 ライブラリのバージョンや OS によって数値は微妙に変わりうるが、 「DNN だけ R² がマイナスに沈む」という構図は再現するはずである。
分類版(実測 ①)は MLPClassifier / StratifiedKFold / scoring='accuracy' に置き換えるだけでよい。
上の実測が示すとおり、 DNN は「置けば勝つ」道具ではない。 歴史的にも、 素朴に層を重ねただけの深い網は学習に失敗し続け、 いくつもの工学的発明が揃って初めて「深さ」が武器になった。 ここでは (1) 深さと幅、 (2) 勾配消失への対策、 (3) 正則化、 (4) 最適化、 (5) アーキテクチャ選択、 の 5 つの軸で発展的内容を整理する。
万能近似定理(MLP のページ参照)は「隠れ層 1 でも幅を無限に広げれば任意の連続関数を近似できる」と言う。 それでも実務で深さが選ばれるのは、 階層的に合成できる関数は、 深い網なら少ないユニット数で、 浅い網では指数的に多いユニット数を要することが理論・経験の両面で知られているからである。 上の 🎮 ウィジェット (a) で見た「層を 1 枚足すたびに表現できるリングが倍増する」現象がまさにこれで、 浅い網で同じ境界を作るには幅を倍々に増やすしかない。 各層の出力が「エッジ → パーツ → 概念」と抽象度を上げていく表現学習(ウィジェット (b))こそが、 深層学習が特徴量エンジニアリングを自動化できた理由である。 ただし実測 ② が示すように、 学習すべき関数が単純(ほぼ線形)でデータが少ないなら、 深さも幅も過剰装備にしかならない。
誤差逆伝播法では勾配が層をさかのぼるたびに活性化関数の微分が掛け算される。 sigmoid の微分は最大 0.25 なので、 例えば 10 層さかのぼると最良でも 0.25¹⁰ ≈ 10⁻⁶ 倍 ── 勾配はほぼ 0 に消える(勾配消失)。 逆に重みが大きいと発散する(勾配爆発)。 これを打ち破った代表的な工夫:
| 工夫 | 仕組みと効果 |
|---|---|
| ReLU(2011 頃〜) | 正領域で微分がちょうど 1。 掛け算しても勾配が縮まない。 計算も max(0, z) だけで高速。 AlexNet 成功の立役者の 1 つ。 |
| 残差接続(ResNet, 2015) | 層の出力を h = f(h) + h と「入力をそのまま足す」形にする。 勾配が近道(恒等写像)を通って浅い層まで素通りでき、 100〜1000 層の学習が可能になった。 Transformer にも標準搭載。 |
| Batch Normalization(2015) | 各層の入力をミニバッチ内で平均 0・分散 1 に正規化し続ける。 層が深くなるほど分布がずれていく問題を抑え、 大きな学習率でも安定。 標準化を「入力だけでなく毎層でやる」発想。 |
| 重みの初期化(Xavier / He) | 各層の出力分散が層を経ても保たれるよう初期値のスケールを設計する。 sklearn や PyTorch は既定で採用済みなので普段は意識しないが、 「初期化を間違えるだけで深い網は学習しない」ことは知っておく価値がある。 |
| 手法 | 要点 |
|---|---|
| Dropout | 訓練中、 各ユニットを確率 p(典型 0.2〜0.5)でランダムに無効化。 特定ユニットへの依存(共適応)を防ぎ、 疑似的なアンサンブルとして働く。 詳細は正則化のページ。 |
| L2 正則化(weight decay) | 損失に重みの二乗和を加えて大きな重みを罰する。 上の実測 ② で alpha=1.0 が DNN を R² −2.4 → 0.79 まで救ったのがこれ。 効き目は劇的だが、 強さの選択自体がハイパーパラメータ探索になる。 |
| 早期終了(early stopping) | 検証誤差が悪化し始めたエポックで学習を打ち切る。 実装が容易で副作用が少なく、 実務ではほぼ常用。 過学習のページに学習曲線での見分け方がある。 |
| データ拡張 | 画像の回転・反転・切り抜き等で訓練データを水増しする。 「データを増やす」は最強の正則化。 表形式データでは使いにくいのが、 表形式で DNN が苦戦する一因でもある。 |
DNN の学習は勾配降下法の変種で行う。 素の SGD(確率的勾配降下)はミニバッチごとの勾配で重みを更新するが、 谷底でジグザグしやすい。 モーメンタムは過去の勾配の移動平均で慣性をつけ、 Adam(2014)はさらにパラメータごとに学習率を自動調整する。 sklearn の MLP も既定で Adam を使っており、 「まず Adam の lr=0.001 から」が現在の定石。 大規模モデルでは重み減衰を分離した AdamW と、 学習率を徐々に下げるスケジューラ(cosine decay 等)の併用が標準になっている。 バッチサイズと学習率のバランスが学習の安定性を決めることは、 上の落とし穴セクションのとおり。
| データの形 | 第一候補 | 理由 |
|---|---|---|
| 表形式・小規模(数十〜数千行) | 線形回帰/Ridge、 次に GBDT(XGBoost 等) | 本節の実測どおり。 DNN は最後の選択肢。 |
| 表形式・中〜大規模(数万行〜) | GBDT と DNN を両方試す(ランダムフォレストも基準に) | 中規模の表形式では木ベース優位の報告が多いが、 データが増えるほど差は縮む。 アンサンブルで併用も。 |
| 画像・空間データ | CNN(または Vision Transformer) | 畳み込みの局所性・平行移動不変性が画像の性質に合う。 |
| 時系列・音声 | RNN/LSTM、 近年は Transformer 系 | 順序依存の構造を状態または注意機構で捉える。 |
| テキスト・マルチモーダル | Transformer(事前学習済み LLM の微調整) | ゼロから学習せず、 事前学習済みモデルの転移学習が現在の標準。 |
まとめると、 DNN の学習で本当に効くのは「層を増やすこと」そのものではなく、 深さを支える周辺技術(ReLU・残差接続・正規化・正則化・Adam)と、 データの形に合ったアーキテクチャ選択である。 そして表形式の小データでは、 その全部を注ぎ込んでも素の Ridge に負けうる ── というのが本ページの実測が残す最大の教訓である。 基礎に戻りたいときはニューラルネットワーク・パーセプトロン、 先へ進むなら 深層学習(発展)・LLM の各ページへ。