Files
task-3-2-2-text-classification/README.md
2026-05-19 11:29:43 +08:00

172 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 手写数字识别 - 纯NumPy MLP实现
## 项目简介
使用纯NumPy实现的两层全连接神经网络MLP在MNIST数据集上进行手写数字识别。
**零深度学习框架依赖**,只需 `numpy`
## 网络结构
```
输入层(784) → 隐藏层(128) + ReLU → 输出层(10) + Softmax
```
- **输入**: 28×28=784 像素值,归一化到 [0, 1]
- **隐藏层**: 128 神经元ReLU激活函数
- **输出层**: 10 神经元数字0-9Softmax输出概率
## 文件结构
```
digit_mlp_class/
├── main.py # 主程序(训练/评估/对比实验)
├── model_numpy.py # MLP模型纯NumPy实现
├── dataset.py # MNIST数据集加载
├── config.py # 超参数配置
├── data/ # MNIST数据文件
│ ├── train-images-idx3-ubyte.gz
│ ├── train-labels-idx1-ubyte.gz
│ ├── t10k-images-idx3-ubyte.gz
│ └── t10k-labels-idx1-ubyte.gz
└── README.md
```
## 依赖
```
numpy
```
## 使用方法
### 1. 下载MNIST数据集
如果 `data/` 目录下没有数据文件,运行:
```bash
python dataset.py
```
或手动下载:
```bash
cd data/
curl -LO https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
curl -LO https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
curl -LO https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
curl -LO https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
```
### 2. 训练模型
```bash
python main.py
```
### 3. 运行对比实验
```bash
python main.py --compare
```
## 代码设计
### model_numpy.py - MLP模型
核心实现:
- **前向传播**: 矩阵乘法 + ReLU + Softmax
- **反向传播**: 手动梯度计算 + 梯度下降
- **权重初始化**: Xavier初始化适合ReLU
```python
class MLP:
def __init__(self, input_size=784, hidden_size=128, num_classes=10)
def forward(self, X): # 前向传播
def backward(self, X, y): # 反向传播
def fit(self, X, y): # 训练
def predict(self, X): # 预测
```
### dataset.py - 数据加载
- 自动检测 `data/` 目录下的MNIST文件
- 解析IDX格式MNIST标准格式
- 归一化像素值到 [0, 1]
- 支持One-Hot编码标签
### main.py - 主程序
两种运行模式:
1. **默认模式**: 训练一个模型并评估
2. **对比模式** (`--compare`): 对比不同超参数的效果
## 数学原理
### 前向传播
```
z1 = X @ W1 + b1 # 第一层线性变换
a1 = ReLU(z1) # 第一层激活
z2 = a1 @ W2 + b2 # 第二层线性变换
probs = softmax(z2) # 输出概率
```
### 反向传播
```
d_z2 = probs - y # 输出层梯度
d_W2 = a1.T @ d_z2 # 第二层权重梯度
d_z1 = d_z2 @ W2.T * relu_derivative(z1) # 隐藏层梯度
d_W1 = X.T @ d_z1 # 第一层权重梯度
W1 -= lr * d_W1 / batch_size # 梯度下降更新
W2 -= lr * d_W2 / batch_size
```
### 激活函数
**ReLU**:
```
ReLU(x) = max(0, x)
ReLU'(x) = 1 if x > 0 else 0
```
**Softmax**:
```
softmax(x_i) = exp(x_i) / sum(exp(x_j))
```
## 超参数
| 参数 | 默认值 | 说明 |
|------|--------|------|
| hidden_size | 128 | 隐藏层神经元数量 |
| learning_rate | 0.1 | 学习率 |
| epochs | 50 | 训练轮数 |
| batch_size | 64 | 批大小 |
| seed | 42 | 随机种子 |
## 预期结果
- 训练准确率: ~98%
- 测试准确率: ~95-97%
训练时间: 约 5-10 分钟(取决于硬件)
## 扩展实验
1. **改变隐藏层大小**: 32 / 64 / 128 / 256
2. **改变学习率**: 0.01 / 0.1 / 0.5
3. **添加Dropout**: 防止过拟合
4. **增加隐藏层数**: 784 → 256 → 128 → 10
## 教学用途
本项目适合用于讲解:
- 神经网络基本结构
- 前向传播与反向传播原理
- 梯度下降优化
- NumPy矩阵操作
- MNIST数据集处理