Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 61 additions & 27 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,15 @@ flowchart TD
START(["🚀 程序启动"]) --> PARSE["解析命令行参数<br/>--epochs, --batch-size,<br/>--lr, --optimizer"]
PARSE --> LOAD_DATA["加载 CSV 数据<br/>MNIST 784 维像素"]
LOAD_DATA --> SPLIT["分割训练集/测试集"]
SPLIT --> BUILD["构建网络模型<br/>Linear(784→64)→ReLU<br/>× 3 层<br/>→ Linear(64→10)"]
SPLIT --> BUILD["构建网络模型<br/>Linear(784→512)→LayerNorm→GeLU<br/>→ Linear(512→256)→LayerNorm→GeLU<br/>→ Linear(256→128)→LayerNorm→GeLU<br/>→ Linear(128→64)→LayerNorm→GeLU<br/>→ Linear(64→10)"]
BUILD --> LOAD_PREV{"有预训练模型?"}
LOAD_PREV -->|"是"| LOAD_M["加载预训练权重"]
LOAD_PREV -->|"否"| INIT["Xavier 初始化权重"]
LOAD_M --> TRAIN_LOOP
INIT --> TRAIN_LOOP

subgraph TRAIN_LOOP["🔁 训练循环 (per epoch)"]
BATCH["取一个 batch<br/>(默认 32 样本)"]
BATCH["取一个 batch<br/>(默认 64 样本)"]
BATCH --> FORWARD["⚡ 前向传播<br/>model.forward(X)"]
FORWARD --> LOSS["📊 计算损失<br/>CrossEntropyLoss"]
LOSS --> BACKWARD["📉 反向传播<br/>model.backward(grad)"]
Expand Down Expand Up @@ -217,8 +217,37 @@ classDiagram
+backward(grad_output) Matrix
}

class GeLU {
-Matrix input_cache_
-Matrix sigmoid_cache_
-constexpr double BETA = 1.702
+forward(input) Matrix
+backward(grad_output) Matrix
}

class LayerNorm {
-size_t normalized_shape_
-double epsilon_
-Matrix gamma_
-Matrix beta_
-Matrix grad_gamma_
-Matrix grad_beta_
+forward(input) Matrix
+backward(grad_output) Matrix
}

class PositionalEncoding {
-size_t max_len_
-size_t d_model_
-Matrix pe_
+forward(input) Matrix
}

Layer <|-- Linear
Layer <|-- ReLU
Layer <|-- GeLU
Layer <|-- LayerNorm
Layer <|-- PositionalEncoding
```

### Model — 网络容器
Expand Down Expand Up @@ -311,13 +340,15 @@ flowchart LR
end
```

参数写入顺序(以 3 层隐藏层为例):
1. W₁ (64×784), b₁ (64×1)
2. W₂ (64×64), b₂ (64×1)
3. W₃ (64×64), b₃ (64×1)
4. W₄ (10×64), b₄ (10×1)
参数写入顺序(默认 4 层隐藏层架构):
1. W₁ (512×784), b₁ (512×1)
2. W₂ (256×512), b₂ (256×1)
3. W₃ (128×256), b₃ (128×1)
4. W₄ (64×128), b₄ (64×1)
5. W₅ (10×64), b₅ (10×1)
6. γ₁~γ₄, β₁~β₄ (LayerNorm 参数)

共 **8 个矩阵参数**。
共 **10 个 Linear 参数矩阵 + 8 个 LayerNorm 参数矩阵**。

---

Expand Down Expand Up @@ -350,12 +381,9 @@ flowchart TD

```mermaid
flowchart TD
CMAKE["CMakeLists.txt"] --> OPT1["benchmark_naive<br/>朴素矩阵乘法基准"]
CMAKE --> OPT2["benchmark_b32<br/>32 线程矩阵乘法基准"]
CMAKE --> OPT3["benchmark_b64<br/>64 线程矩阵乘法基准"]
CMAKE --> TARGET1["mnist_train<br/>训练可执行文件"]
CMAKE["CMakeLists.txt<br/>C++26, Clang++"] --> TARGET1["mnist_train<br/>训练可执行文件"]
CMAKE --> TARGET2["mnist_infer<br/>推理可执行文件"]
CMAKE --> DEPS["依赖: OpenMP (可选)<br/>C++26 标准"]
CMAKE --> DEPS["编译选项: -O3 -ffast-math<br/>-fexperimental-library<br/>-Wall -Wextra -Wpedantic -Werror"]
```

---
Expand Down Expand Up @@ -388,23 +416,29 @@ flowchart LR

## 🎯 网络结构总结

默认 MNIST 架构(定义在 `mnist_common.hpp` 的 `MNIST_LAYER_DIMS`):

```
┌─────────────────────────────────────────────┐
│ MNIST 手写数字识别网络 │
├─────────────────────────────────────────────┤
│ Input: 784 (28×28 像素展平) │
│ ───────────────────────────────────────── │
│ Layer 1: Linear(784 → 64) + ReLU │
│ Layer 2: Linear(64 → 64) + ReLU │
│ Layer 3: Linear(64 → 64) + ReLU │
│ Layer 4: Linear(64 → 10) │
│ ───────────────────────────────────────── │
│ Loss: CrossEntropy (含 Softmax) │
│ Optimizer: Adam / SGD / SGD+Momentum │
│ 输出: 10 维向量 → argmax → 数字 0-9 │
└─────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ MNIST 手写数字识别网络 │
├──────────────────────────────────────────────────────────┤
│ Input: 784 (28×28 像素展平) │
│ ────────────────────────────────────────────────────── │
│ Layer 1: Linear(784 → 512) + LayerNorm + GeLU │
│ Layer 2: Linear(512 → 256) + LayerNorm + GeLU │
│ Layer 3: Linear(256 → 128) + LayerNorm + GeLU │
│ Layer 4: Linear(128 → 64) + LayerNorm + GeLU │
│ Layer 5: Linear(64 → 10) │
│ ────────────────────────────────────────────────────── │
│ Loss: CrossEntropy (含数值稳定 Softmax) │
│ Optimizer: Adam / SGD / SGD+Momentum │
│ 输出: 10 维向量 → argmax → 数字 0-9 │
└──────────────────────────────────────────────────────────┘
```

> 📝 网络架构由 `MNIST_LAYER_DIMS = {784, 512, 256, 128, 64, 10}` 驱动,
> 自动在隐藏层之间插入 LayerNorm + GeLU 激活。

---

*Generated by GitHub Copilot — MiMo V2.5*
50 changes: 25 additions & 25 deletions DEVELOPMENT_STANDARDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,22 @@ void process(std::span<const double> data);
void process(const double* data, std::size_t size);
```

#### 2.4 预分配缓冲区模式
#### 2.4 使用 std::span 访问矩阵数据
```cpp
// ✅ 推荐:使用 span() 访问矩阵数据(C++20 零开销抽象)
auto data = matrix.span(); // std::span<double>
auto cdata = const_matrix.span(); // std::span<const double>

// 在 lambda 中捕获 span(类型安全,编译期大小检查)
auto func = [data](std::size_t i) noexcept {
return data[i] * 2.0;
};

// ❌ 避免:使用已废弃的 data_ptr()
double* ptr = matrix.data_ptr(); // [[deprecated]]
```

#### 2.5 预分配缓冲区模式
```cpp
// ✅ 推荐:预分配并在就地操作
void multiply_to(Matrix& result, const Matrix& other) const {
Expand All @@ -123,7 +138,7 @@ void multiply_to(Matrix& result, const Matrix& other) const {
- [ ] 是否有 `new` / `delete` 操作?
- [ ] 是否使用 `std::vector` 替代动态数组?
- [ ] 是否使用 `std::unique_ptr` 管理多态对象?
- [ ] 是否使用 `std::span` 传递只读连续数据?
- [ ] 是否使用 `std::span` 替代裸指针访问连续数据?
- [ ] 热路径中是否预分配缓冲区?

---
Expand Down Expand Up @@ -378,32 +393,17 @@ set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
```

### 2. 必须使用的 C++26 特性

| 特性 | 用途 | 示例 |
|------|------|------|
| `std::generator` | 协程生成器 | 数据加载器 |
| `std::print` / `std::println` | 格式化输出 | 调试信息 |
| `std::expected` | 错误处理 | 返回值类型 |
| `std::flat_map` | 高性能映射 | 配置管理 |
| `std::mdspan` | 多维数组视图 | 矩阵操作 |
| `std::stacktrace` | 调试堆栈跟踪 | 错误报告 |

### 3. 积极使用的 C++23/20 特性
### 2. 积极使用的 C++20/23 特性

| 特性 | 标准 | 用途 |
|------|------|------|
| `std::ranges` | C++20 | 数据处理管道 |
| `std::views` | C++20 | 延迟求值 |
| `std::format` | C++20 | 字符串格式化 |
| `std::span` | C++20 | 非拥有视图 |
| `std::jthread` | C++20 | 自动连接线程 |
| `std::source_location` | C++20 | 错误定位 |
| `std::print` | C++23 | 格式化输出 |
| `std::generator` | C++23 | 协程生成器 |
| `std::mdspan` | C++23 | 多维数组 |

### 4. 标准跟进检查清单
| `std::span` | C++20 | 非拥有型连续内存视图,替代裸指针 |
| `std::ranges` | C++20 | 数据处理管道(如 `ranges::generate` Xavier 初始化) |
| `std::views::iota` | C++20 | 延迟整数序列(并行索引生成) |
| `std::views::zip` | C++20 | 多范围并行迭代(优化器参数更新) |
| `std::execution::par_unseq` | C++17 | 并行执行策略(矩阵运算) |

### 3. 标准跟进检查清单

- [ ] 是否使用最新的 C++ 标准(C++26)?
- [ ] 是否积极使用 C++20/23/26 新特性?
Expand Down
81 changes: 56 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,40 @@
neuralnet.cpp/
├── .gitignore
├── CMakeLists.txt
├── ARCHITECTURE.md ← 架构文档
├── DEVELOPMENT_STANDARDS.md ← 开发规范
├── README.md
├── gui.py ← 图形化操作界面
├── csv_png.py
├── extract_digits.py
├── save_dataset.py
├── build/
│ ├── mnist_infer.exe
├── gui.py ← 图形化操作界面 (Tkinter)
├── csv_png.py ← CSV 转 PNG 图像
├── extract_digits.py ← 从 MNIST CSV 提取单个数字
├── save_dataset.py ← 下载 MNIST 数据集
├── build/ ← CMake 构建输出
│ ├── mnist_train.exe
│ └── mnist_data/
│ ├── test.csv
│ └── train.csv
│ └── mnist_infer.exe
├── include/
│ └── neuralnet.cpp/
│ ├── layer.hpp
│ ├── loss.hpp
│ ├── matrix.hpp
│ └── optimizer.hpp
└── src/
├── infer.cpp
└── train.cpp
│ ├── nn.hpp ← 统一入口头文件
│ ├── nn_config.hpp ← SmartPolicy、BLOCK_SIZE 等配置
│ ├── thread_pool.hpp ← 全局线程池
│ ├── matrix.hpp ← Matrix 类(列主序)
│ ├── layer.hpp ← Layer 基类 + Linear/ReLU/GeLU/LayerNorm/PositionalEncoding
│ ├── loss.hpp ← Loss 基类 + MSELoss/CrossEntropyLoss
│ ├── optimizer.hpp ← SGD / SGD_w_Momentum / Adam
│ ├── model.hpp ← Model 容器(链式 add<>)
│ ├── model_io.hpp ← 二进制模型序列化
│ └── mnist_common.hpp ← MNIST 常量与 build_mnist_model()
├── src/
│ ├── train.cpp
│ └── infer.cpp
├── datasets/
│ ├── mnist_data/ ← MNIST CSV 数据
│ └── test/ ← 按数字分类的测试图片
└── pretrained/
└── mnist_model.bin ← 预训练模型
```

[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/EthanPeng-2048/neuralnet.cpp)

## 依赖

- **编译器**: LLVM Clang++ 22.1+(`C:/Program Files/LLVM/bin/clang++.exe`)
Expand All @@ -56,14 +68,17 @@ python save_dataset.py
### 运行训练

```bash
# 从头开始训练
# 从头开始训练(默认: 10轮, 学习率0.001, 批大小64, Adam优化器)
./build/mnist_train

# 从已有模型恢复训练
./build/mnist_train --load mnist_model.bin
./build/mnist_train --resume pretrained/mnist_model.bin

# 自定义参数
./build/mnist_train --epochs 20 --lr 0.001 --batch-size 32 --optimizer adam --save my_model.bin

# 指定保存路径
./build/mnist_train --save my_model.bin
# 支持的优化器: sgd / sgd_w_momentum / adam
./build/mnist_train --optimizer sgd_w_momentum
```

### 🖥️ 图形化界面 (GUI)
Expand All @@ -87,21 +102,37 @@ python gui.py

## 网络结构

默认 MNIST 架构(定义在 `mnist_common.hpp`):

```
输入 (784) → Linear(64) → ReLU → Linear(64) → ReLU → Linear(64) → ReLU → Linear(10)
输入 (784)
→ Linear(784 → 512) + LayerNorm + GeLU
→ Linear(512 → 256) + LayerNorm + GeLU
→ Linear(256 → 128) + LayerNorm + GeLU
→ Linear(128 → 64) + LayerNorm + GeLU
→ Linear(64 → 10)
→ CrossEntropy Loss (含 Softmax)
```

## 提供的组件

| 组件 | 说明 |
|------|------|
| `nn::Matrix` | 列主序矩阵,支持并行加/减/乘/转置 |
| `nn::Linear` | 全连接层(含 Xavier 初始化) |
| `nn::Matrix` | 列主序矩阵,支持并行加/减/乘/转置、预分配缓冲区 |
| `nn::Model` | 网络容器,支持链式 `add<LayerType>()` 构建 |
| `nn::Linear` | 全连接层(含 Xavier 均匀初始化、融合 bias 计算) |
| `nn::ReLU` | ReLU 激活函数 |
| `nn::GeLU` | QuickGeLU 激活函数(`x · σ(1.702x)`) |
| `nn::LayerNorm` | 层归一化(含可学习 γ/β 参数) |
| `nn::PositionalEncoding` | 正弦/余弦位置编码(Transformer 用) |
| `nn::MSELoss` | 均方误差损失 |
| `CrossEntropyLoss` | 交叉熵损失(含数值稳定 Softmax,在 `train.cpp` 中定义) |
| `nn::CrossEntropyLoss` | 交叉熵损失(含数值稳定 Softmax,`loss.hpp` 中定义) |
| `nn::SGD` | 随机梯度下降优化器 |
| `save_model` / `load_model` | 二进制模型序列化 |
| `nn::SGD_w_Momentum` | 动量 SGD 优化器 |
| `nn::Adam` | Adam 优化器(一阶/二阶矩估计) |
| `nn::SmartPolicy` | 自适应并行策略:小矩阵串行,大矩阵线程池并行 |
| `nn::ThreadPool` | 全局单例线程池(懒初始化) |
| `nn::save_model` / `nn::load_model` | 二进制模型序列化 |

## 📐 开发规范

Expand Down
Loading
Loading