Machine Learning: PyTorchによるディープラーニング:ニューロンから多層パーセプトロンへ
最終更新:2026-08-26
ディープラーニングを使えば、機械が特徴を自動的に発見できます。手作業での設計は不要です。ネットワークがデータの中のパターンを自ら見つけ出します。
1. 学習内容
- ディープラーニングと従来の機械学習の違い:深いネットワークが必要な場面、計算量やデータ量に関する考慮点
- PyTorchの基礎:テンソル演算、autogradによる自動微分、nn.Moduleによるモデル定義
- 多層パーセプトロン(MLP):順伝播、損失の計算、誤差逆伝播法、パラメータの更新
- 学習のテクニック:DataLoaderによるバッチ化、学習率スケジューリング、早期終了、GPU学習
- BobのMLP売上予測器:第7回の線形回帰と比較し、ニューラルネットワークで改善が得られるかを確認する
2. MLエンジニアの実体験
(1) 悩み:線形モデルでは特徴量の相互作用を捉えられない
Bobは線形回帰で売上を予測していましたが、R²は0.78にとどまっていました。彼は「広告費×プロモーション」の相互作用が売上に大きな影響を与えることに気づいていましたが、すべての相互作用項を手作業で追加する(20個の特徴量→190個の相互作用)のは面倒で、ミスも起こりがちでした。線形モデルの仮定(y = wx + b)は単純すぎます。現実世界の特徴量の相互作用は、手作業で設計できるものよりはるかに複雑です。
(2) ディープラーニングによる解決策
ニューラルネットワークは、隠れ層を通じて特徴量の相互作用や非線形変換を自動的に学習します。手作業による特徴量設計は不要です。
PYTHON
import torch.nn as nn
model = nn.Sequential(
nn.Linear(20, 64),
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 1),
)
(3) 成果:MLPが相互作用を自動発見し、R²は0.86に向上
Bobは線形回帰を3層のMLPに置き換えました。ネットワークは「広告費が高い+プロモーション実施=売上の急増」というパターンを自動的に学習し、相互作用項を1つも手作業で設計することなく、R²を0.78から0.86へ引き上げました。
3. ディープラーニングと従来の機械学習
(1) ディープラーニングを選ぶべき場面
| 基準 | 従来の機械学習(例:XGBoost) | ディープラーニング(例:MLP/CNN) |
|---|---|---|
| データの種類 | 表形式データ | 画像/テキスト/音声/複雑な表形式データ |
| データ量 | 10万件未満 | 10万件超 |
| 特徴量設計 | 手作業での設計が必要 | 特徴量を自動学習 |
| 学習時間 | 数分から数時間 | 数時間から数日 |
| ハードウェア | CPUで十分 | GPU推奨 |
| 解釈性 | 高い(係数/重要度) | 低い(ブラックボックス) |
| 表形式データでの性能 | 通常は優れる | 必ずしも優れるとは限らない |
▶ サンプル:PyTorchのインストールと動作確認
PYTHON
import torch
print(f"PyTorch version: {torch.__version__}")
print(f"CUDA available: {torch.cuda.is_available()}")
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
# Basic tensor operations
a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])
print(f"a + b = {a + b}")
print(f"a * b = {a * b}")
print(f"Mean of a: {a.mean()}")
出力:
TEXT
📖 参照専用
# Executed successfully
4. PyTorchの主要コンセプト
(1) テンソル演算
▶ サンプル:テンソルの作成と操作
PYTHON
import torch
# Create tensors
a = torch.zeros(3, 4)
b = torch.ones(2, 3)
c = torch.randn(3, 3) # Normal distribution
d = torch.arange(0, 10, 2)
# From NumPy
import numpy as np
arr = np.array([1, 2, 3])
t = torch.from_numpy(arr)
# Tensor to NumPy
back = t.numpy()
# GPU tensor
if torch.cuda.is_available():
gpu_tensor = torch.randn(3, 3).cuda()
cpu_back = gpu_tensor.cpu()
# Reshape
x = torch.arange(12)
matrix = x.reshape(3, 4)
print(f"Shape: {matrix.shape}")
# Broadcasting
a = torch.ones(3, 1)
b = torch.ones(1, 4)
c = a + b # (3,4)
print(f"Broadcast result shape: {c.shape}")
出力:
TEXT
📖 参照専用
# Executed successfully
(2) Autograd:自動微分
▶ サンプル:自動微分
PYTHON
import torch
# Auto-differentiation example
x = torch.tensor([2.0], requires_grad=True)
y = x ** 2 + 3 * x + 1 # y = x² + 3x + 1
y.backward() # dy/dx = 2x + 3
print(f"x = {x.item()}")
print(f"y = {y.item()}")
print(f"dy/dx = {x.grad.item()}") # Should be 2*2+3 = 7
print(f"Manual check: 2*2 + 3 = {2*2+3}")
出力:
TEXT
📖 参照専用
# Executed successfully
(3) nn.Moduleによるモデル定義
▶ サンプル:カスタムMLPモデル
PYTHON
import torch
import torch.nn as nn
class SalesPredictMLP(nn.Module):
def __init__(self, input_dim, hidden_dims, output_dim=1):
super().__init__()
layers = []
prev_dim = input_dim
for hidden_dim in hidden_dims:
layers.append(nn.Linear(prev_dim, hidden_dim))
layers.append(nn.BatchNorm1d(hidden_dim))
layers.append(nn.ReLU())
layers.append(nn.Dropout(0.2))
prev_dim = hidden_dim
layers.append(nn.Linear(prev_dim, output_dim))
self.network = nn.Sequential(*layers)
def forward(self, x):
return self.network(x)
model = SalesPredictMLP(input_dim=20, hidden_dims=[64, 32], output_dim=1)
print(model)
print(f"Total parameters: {sum(p.numel() for p in model.parameters()):,}")
出力:
TEXT
📖 参照専用
# Functions defined successfully
5. MLPの完全な学習パイプライン
(1) 学習ループ
sequenceDiagram
participant Data as DataLoader
participant Fwd as Forward Pass
participant Loss as Loss Compute
participant Zero as Zero Gradients
participant Bwd as Backward Pass
participant Step as Optimizer Step
loop Each Epoch
Data->>Fwd: Batch of (X, y)
Fwd->>Loss: y_pred = model(X)
Loss->>Zero: loss = criterion(y_pred, y)
Zero->>Bwd: optimizer.zero_grad()
Bwd->>Step: loss.backward()
Step->>Data: optimizer.step()
end
▶ サンプル:MLPの完全な学習パイプライン
PYTHON
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import r2_score, mean_absolute_error
import numpy as np
# Generate data
rng = np.random.default_rng(42)
n = 5000
X = rng.uniform(0, 100, (n, 20))
y = (50 + X[:, :5] @ [0.8, 1.2, -0.5, 0.3, 0.1]
+ 0.5 * X[:, 0] * X[:, 1] # Interaction
+ np.sin(X[:, 2]) * 5 # Non-linear
+ rng.normal(0, 5, n))
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
# Create DataLoaders
train_ds = TensorDataset(torch.FloatTensor(X_train_s), torch.FloatTensor(y_train))
test_ds = TensorDataset(torch.FloatTensor(X_test_s), torch.FloatTensor(y_test))
train_loader = DataLoader(train_ds, batch_size=64, shuffle=True)
test_loader = DataLoader(test_ds, batch_size=256)
# Model, loss, optimizer
model = SalesPredictMLP(input_dim=20, hidden_dims=[128, 64, 32])
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=10, factor=0.5)
# Training loop
train_losses, val_losses = [], []
best_val_loss = float("inf")
for epoch in range(100):
model.train()
epoch_loss = 0
for X_batch, y_batch in train_loader:
y_pred = model(X_batch).squeeze()
loss = criterion(y_pred, y_batch)
optimizer.zero_grad()
loss.backward()
optimizer.step()
epoch_loss += loss.item()
avg_train_loss = epoch_loss / len(train_loader)
train_losses.append(avg_train_loss)
# Validation
model.eval()
val_loss = 0
with torch.no_grad():
for X_batch, y_batch in test_loader:
y_pred = model(X_batch).squeeze()
val_loss += criterion(y_pred, y_batch).item()
avg_val_loss = val_loss / len(test_loader)
val_losses.append(avg_val_loss)
scheduler.step(avg_val_loss)
# Early stopping
if avg_val_loss < best_val_loss:
best_val_loss = avg_val_loss
best_state = model.state_dict().copy()
if epoch % 20 == 0:
print(f"Epoch {epoch:3d}: train_loss={avg_train_loss:.4f}, val_loss={avg_val_loss:.4f}")
# Load best model and evaluate
model.load_state_dict(best_state)
model.eval()
with torch.no_grad():
y_pred = model(torch.FloatTensor(X_test_s)).squeeze().numpy()
print(f"\nMLP R²: {r2_score(y_test, y_pred):.4f}")
print(f"MLP MAE: {mean_absolute_error(y_test, y_pred):.2f}")
出力:
TEXT
📖 参照専用
# Executed successfully
6. BobのMLP vs. 線形回帰 対決
▶ サンプル:同じデータセットでの直接比較
PYTHON
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_absolute_error
# Linear Regression baseline
lr = LinearRegression()
lr.fit(X_train_s, y_train)
lr_pred = lr.predict(X_test_s)
print("=" * 50)
print("MODEL COMPARISON")
print("=" * 50)
print(f"Linear Regression: R²={r2_score(y_test, lr_pred):.4f}, MAE={mean_absolute_error(y_test, lr_pred):.2f}")
print(f"MLP (3-layer): R²={r2_score(y_test, y_pred):.4f}, MAE={mean_absolute_error(y_test, y_pred):.2f}")
出力:
TEXT
📖 参照専用
=
MODEL COMPARISON
=
| 観点 | LinearRegression | MLP(3層) |
|---|---|---|
| R² | 0.78 | 0.86 |
| MAE | 12.5 | 9.3 |
| 特徴量の相互作用 | 手作業で追加 | 自動学習 |
| 学習時間 | 1秒未満 | 約30秒 |
| 解釈性 | 高い(係数) | 低い(ブラックボックス) |
| 過学習のリスク | 低い | 中程度 |
⚠️ 注意: 表形式データでは、通常XGBoost/LightGBMがMLPを上回る性能を出し、学習も高速です。MLPの強みは、特徴量の相互作用や非線形変換を自動的に学習できる点にあります。実務では、まずGBDTを試してください。それで十分な性能が出ない場合に、MLPを試すのがよいでしょう。
❓ よくある質問
Q PyTorchとTensorFlow、どちらを学ぶべきですか?
A 研究や学習目的ならPyTorchがおすすめです。よりPython的で、デバッグもしやすいからです。本番環境へのデプロイについては、チームの技術スタック次第です。両者の性能は同等ですが、学術分野ではPyTorchが主流です。
Q MLPの隠れ層の数とニューロン数はどれくらいにすべきですか?
A よくある目安として、隠れ層は1〜2層から始め、ニューロン数はinput_dim → 64 → 32のように減らしていきます。深すぎたり広すぎたりすると過学習になり、浅すぎたり狭すぎたりすると学習不足になります。検証セットを使って調整してください。
Q AdamとSGD、どちらが良いですか?
A ほとんどの場合、Adamが勝ちます(適応的な学習率で収束が速い)。SGD + Momentumは特定のタスクで汎化性能が高くなることがあります。まずはAdamから始め、微調整の段階でSGDに切り替えるのがよいでしょう。
Q BatchNormとDropoutとは何ですか?
A BatchNormは各層の出力を正規化するもので、学習の高速化と安定化に貢献します。Dropoutはニューロンをランダムにゼロにするもので、過学習を防ぎます。どちらも標準的な学習テクニックです。
Q 学習率はどのように選べばよいですか?
A まずは0.001(Adam)または0.01(SGD)から始めます。スケジューラと組み合わせて自動的に減衰させましょう(ReduceLROnPlateau)。学習が不安定なら学習率を下げ、収束が遅すぎるなら上げてください。
Q 表形式データにはMLPとXGBoost、どちらを使うべきですか?
A XGBoostを優先してください。表形式データでは通常、性能も速度も優れています。MLPの強みは特徴量の相互作用の自動学習です。GBDTで十分な性能が出ているなら、MLPは必要ありません。
📖 まとめ
- ディープラーニングは特徴表現を自動的に学習する。従来の機械学習では手作業による特徴量設計が必要
- PyTorchの基礎:テンソル(多次元配列)、autograd(自動微分)、nn.Module(モデル定義)
- MLPの学習ループは5ステップ:順伝播 → 損失 → zero_grad → 誤差逆伝播 → step
- DataLoaderでバッチ化、スケジューラで学習率を減衰、早期終了で過学習を防止
- MLP vs. 線形回帰:相互作用を自動学習しR²は高いが、解釈性は低い
- 表形式データでは通常GBDTがMLPを上回る。MLPが真価を発揮するのは、特徴量の相互作用が複雑な場合や非構造化データの場合
📝 練習問題
- 基礎(難易度 ⭐): PyTorchで2層のMLPを作成してください(入力4次元 → 16 → 8 → 出力1)。モデルの構造と総パラメータ数を出力しましょう。ヒント:nn.Sequential +
sum(p.numel()...)。 - 応用(難易度 ⭐⭐): MLPを使ってCalifornia Housingの住宅価格を予測してください。完全な学習ループ(検証と早期終了を含む)を実装し、R²をLinearRegressionと比較しましょう。ヒント:第5節の完全な学習パイプラインを参照してください。
- 挑戦(難易度 ⭐⭐⭐): 異なるMLPアーキテクチャ(1/2/3層、さまざまな隠れ層サイズ)を実験してください。「隠れ層の数 vs. R²」の曲線を描画し、最適なアーキテクチャを見つけましょう。ヒント:異なるhidden_dimsの設定でループを回し、検証R²を記録してください。