a0 β μμ CNN vs Residual CNN (MNIST)
κΉμ΄λ₯Ό λλ¦° μμ CNNμ νκ³(degradation λ¬Έμ )λ₯Ό νμΈνκ³ , residual connectionμ΄ μ΄λ₯Ό ν΄κ²°νλμ§ κ²μ¦ν μ€ν νλ‘μ νΈ. PyTorchλ‘ μ²μλΆν° ꡬν.
Model Description
- Task: MNIST μκΈμ¨ μ«μ λΆλ₯ (28Γ28, 10 classes)
- Architecture: μ±λ 64 κ³ μ μ conv μ€ν.
depth= λΈλ‘ μ(λΈλ‘λΉ conv 2κ°)PlainBlock: Conv β BN β ReLU β Conv β BN β ReLUResBlock: μ ꡬ쑰 + skip connection (out + x)
- νμ΅: Adam (lr=1e-3) + CosineAnnealingLR, batch=128, 15 epochs
- κ°μ€μΉλ
runs/depthN[_res][_nobn]/model.pt(PyTorch state_dict)μ μ μ₯
Results
BatchNorm μμ β best val accuracy
| depth (blocks) | plain CNN | + residual |
|---|---|---|
| 5 | 99.70% | β |
| 10 | 99.62% | 99.58% |
| 15 | 99.60% | 99.52% |
| 20 | 99.58% | 99.66% |
| 40 | 98.89% (λΆμμ ) | 99.56% |
BatchNorm μμ β best val accuracy
| depth (blocks) | plain CNN | + residual |
|---|---|---|
| 20 | 11.35% (λΆκ΄΄) | 99.39% |
| 40 | 11.35% (λΆκ΄΄) | 99.40% |
μμΈν λΆμμ RESULTS.md, λ°μ΄ν° μΆμ²λ DATA.md μ°Έμ‘°.
How to use
import torch
from src.model import CNN
model = CNN(depth=20, use_residual=True, bn=False)
model.load_state_dict(torch.load("runs/depth20_res_nobn/model.pt", weights_only=True))
model.eval()
Training details
# μ: depth20 plain CNN, BN μμ
python src/train.py --depth 20 --no-bn --epochs 15
# μ: depth20 residual CNN, BN μμ
python src/train.py --depth 20 --residual --no-bn --epochs 15
μ£Όμ μ΅μ
: --depth(λΈλ‘ μ), --residual, --no-bn, --channels, --epochs, --batch-size, --lr
ꡬ쑰
src/
model.py # PlainBlock / ResBlock / CNN λΉλ
train.py # MNIST νμ΅ μ€ν¬λ¦½νΈ
plot_results.py # runs/ μ history.json β λΉκ΅ κ·Έλν μμ±
runs/ # μ€νλ³ history.json + model.pt κ°μ€μΉ
results/ # μκ°ν PNG
data/ # MNIST (git μ μΈ, torchvision μλ λ€μ΄λ‘λ)
μ¬ν νκ²½
python -m venv .venv
.venv/Scripts/pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128
ν μ€νΈ νκ²½: PyTorch 2.11.0+cu128, NVIDIA RTX 5070 Ti (CUDA 12.8)