Skip to content

About

纯 Python 标准库实现的神经网络工具箱,零第三方依赖:全栈组件(全连接/CNN/RNN/LSTM/GRU/Transformer)与 sklearn 风格 API。

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

34 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Python-standard-library-only-AI

纯 Python 标准库实现的神经网络工具箱,零第三方依赖。

特性

  • 零第三方依赖: 仅依赖 math、random、json 等标准库
  • 全栈组件: 从全连接层到 CNN、RNN/LSTM/GRU、Transformer 一应俱全
  • 双模式 API: 底层精细控制 + 高层 sklearn 风格封装
  • 完整的训练管线: Early Stopping、梯度裁剪、学习率调度、模型保存/加载
  • 反向传播有数值梯度测试守着: Layer / MultiHeadAttention / Conv2d / BatchNorm1d 的解析梯度都与数值梯度逐项比对

快速开始

import random
from AI import *

random.seed(42)   # 示例固定随机种子,输出可复现

# ── 分类:一行训练,零配置 ────────────────────
x = [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9],
     [0.15, 0.25, 0.35], [0.45, 0.55, 0.65], [0.75, 0.85, 0.95]]
y = [0, 1, 2, 0, 1, 2]

model = quick_train(x, y, task='classification', epochs=300, verbose=False)
print(model.score(x, y))          # 准确率 → 1.0

# ── 回归:目标 y = [x0², x0·x1] ───────────────
vals = [0.2 + 1.1 * i / 19 for i in range(20)]        # 0.2 ~ 1.3
x_reg = [[v, v * 1.5] for v in vals]
y_reg = [[v * v, v * v * 1.5] for v in vals]

random.seed(42)
model_reg = make_regressor(input_dim=2, output_dim=2, hidden_layers=(32, 32), lr=0.03)
model_reg.fit(x_reg, y_reg, epochs=1500, patience=100, verbose=False)
print(model_reg.predict([0.6, 0.9]))   # → [0.3605, 0.5393](真值 [0.36, 0.54],R² ≈ 0.9999)

高层 API

Model 类(sklearn 风格)

# 手动构建(5 维输入 → 2 维输出)
x_train = [[0.1, 0.2, 0.3, 0.4, 0.5], [0.2, 0.3, 0.4, 0.5, 0.6],
           [0.3, 0.4, 0.5, 0.6, 0.7], [0.4, 0.5, 0.6, 0.7, 0.8]]
y_train = [[0.5, 1.0], [0.7, 1.4], [0.9, 1.8], [1.1, 2.2]]

model = Model(MLP([5, 16, 8, 2]), loss_fn='mse', optimizer='adam', lr=0.01)
model.summary()          # 打印模型结构
history = model.fit(x_train, y_train, epochs=300, batch_size=2, patience=30,
                    lr_scheduler=StepLR(model.optimizer, step_size=50, gamma=0.5),
                    grad_clip=1.0)
pred = model.predict(x_train)
score = model.score(x_train, y_train)   # 分类=准确率 / 回归=R²(多输出时对各输出维度取平均)

# 保存 & 加载
model.save("model.json")
model2 = Model.load("model.json")

模型瘦身与蒸馏

方法 / 函数 说明
MLP.param_count() 可训练参数总数
MLP.sparsity() 权重中为 0 的比例
MLP.prune_magnitude(threshold) 幅度剪枝:|w| < 阈值置 0,返回剪掉个数
MLP.quantize_weights(bits) 全局 min/max 均匀分档定点量化,返回步长
MLP.merge_weights(other, w1, w2) 权重线性合并(K 折权重平均用,各折需同初值)
distill(teacher, student, x, y) 蒸馏:用教师输出当软目标训练学生,返回一致率

it() 新增 early_stop_metric='val'|'train':默认盯验证损失; 选 'train' 时盯训练损失,且不依赖验证集(原来没有验证集时 patience 完全不生效)。

工厂函数

函数 说明
make_classifier(input_dim, num_classes, ...) 创建分类模型(Softmax + CrossEntropy)
make_regressor(input_dim, output_dim, ...) 创建回归模型(Linear + MSE)
quick_train(x, y, task, ...) 一行代码自动创建并训练

fit() 参数

参数 说明
epochs 训练轮数
batch_size 批次大小(-1 = 全批量)
val_split / val_data 验证集比例或自定义验证集(见下方说明)
patience Early Stopping 耐心值(0 = 关闭)
lr_scheduler StepLR / ExponentialLR / CosineAnnealingLR
grad_clip 梯度范数裁剪阈值

val_data 支持三种写法(会校验维度,维度不符直接报错):

model = make_regressor(2, 1, hidden_layers=(8,))
x_train = [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6], [0.7, 0.8]]
y_train = [[0.3], [0.7], [1.1], [1.5]]
x_val, y_val = [[0.15, 0.25], [0.35, 0.45]], [[0.4], [0.8]]

model.fit(x_train, y_train, val_data={'x': x_val, 'y': y_val})   # 显式并行数组(推荐,无歧义)
model.fit(x_train, y_train, val_data=(x_val, y_val))             # 并行数组
model.fit(x_train, y_train, val_data=[([0.15, 0.25], [0.4]), ([0.35, 0.45], [0.8])])  # 样本对列表

说明:恰好 2 个元素且结构上无法区分时,list 按「样本对」解释、tuple 按「并行数组」解释;拿不准就用 dict 写法。

底层组件

层 (Layers)

组件 说明
Layer 全连接层 + 激活函数(He 初始化)
MLP 多层感知机容器
Conv2d 二维卷积层
MaxPool2d 二维最大池化
Flatten 展平(CNN → MLP)
Dropout Dropout 正则化
BatchNorm1d 批归一化(训练用 forward_batch(batch),推理用 forward(x))
LayerNorm 层归一化
Embedding 嵌入层
ResidualBlock 残差块
Sequential 层序列容器

循环神经网络

组件 说明
RNNCell / RNN 基础 RNN(含 BPTT)
LSTMCell / LSTM 长短期记忆网络
GRUCell / GRU 门控循环单元

Transformer

组件 说明
MultiHeadAttention 多头注意力机制
FeedForward 前馈网络
TransformerEncoderLayer 单层 Encoder
TransformerEncoder 多层 Encoder 堆叠
PositionalEncoding 位置编码

优化器

优化器 说明
Adam Adam(默认)
SGD 随机梯度下降
SGDMomentum 带动量的 SGD
RMSprop RMSprop

损失函数

函数 说明
mse_loss(pred, target) 均方误差(长度不一致会报错,不再静默截断)
cross_entropy_loss(pred, target_idx) 交叉熵

搭配约束:softmax 输出层的反向使用的是 softmax + cross_entropy 的联合梯度, 因此只能与 cross_entropy 搭配。Model(loss_fn='mse') + softmax 输出层会直接报错, 而不是静默用错误梯度训练;需要 MSE 时请把输出层激活设为 linear。

Model 的 CE 路径会自动规范化 target:类别索引、[0.0, 1.0] 这类浮点标签、 one-hot / 概率分布、长度为 1 的列表都可以直接传。

工具函数

函数 说明
split_data(data, val_ratio, test_ratio) 数据集拆分
DataLoader 批量迭代器
train(model, loss_fn, optimizer, data, ...) 底层训练循环(Early Stopping + 验证集)
evaluate(model, loss_fn, data) 计算平均损失
save_model(model, path) / load_model(path) MLP 的 JSON 持久化
save_conv_model(conv, fc, path) / load_conv_model(path) CNN + MLP 的 JSON 持久化
clip_grad_by_norm(grads, max_norm) 梯度范数裁剪
clip_grad_by_value(grads, clip_val) 梯度值裁剪
compare_with_pytorch() 与 PyTorch 逐层数值对齐(可选,装了 torch 才跑)

学习率调度器

调度器 说明
StepLR(optimizer, step_size, gamma) 阶梯衰减
ExponentialLR(optimizer, gamma) 指数衰减
CosineAnnealingLR(optimizer, T_max) 余弦退火

文本处理

组件 说明
TextProcessor 字符级词表、one-hot 编码、滑动窗口
generate_text(network, tp, start, length) 自回归文本生成(generate_text_with_mlp 的别名,保留以兼容旧调用)
generate_text_with_mlp(model, tp, start, length, window_size, temp) 自回归文本生成(滑动窗口上下文,只需 forward)
_softmax_with_temp(logits, temperature) 带温度的 Softmax
sample_index(probs) 随机采样

底层 API 示例

CNN

conv = Conv2d(in_channels=1, out_channels=2, kernel_size=2, stride=1)
pool = MaxPool2d(kernel_size=2)
flatten = Flatten()
fc = MLP([2, 4, 2], activations=["leaky_relu", "softmax"])

# 前向: img (1, 4, 4) → conv → pool → flatten → fc
x = conv.forward(img)
x = pool.forward(x)
x = flatten.forward(x)
probs = fc.forward(x)

Transformer

d_model = 4
pos_enc = PositionalEncoding(d_model=d_model)
encoder = TransformerEncoder(d_model=d_model, num_heads=2, d_ff=8, num_layers=1)

x = pos_enc.forward(seq)          # 加位置编码
x = encoder.forward(x)            # 经过 Transformer
pooled = [sum(t[j] for t in x) / len(x) for j in range(d_model)]   # 全局平均池化
head = MLP([d_model, 8, 2], activations=["leaky_relu", "linear"])  # 分类头
logits = head.forward(pooled)

RNN / LSTM / GRU

rnn = RNN(input_size=1, hidden_size=4, num_layers=1)
lstm = LSTM(input_size=1, hidden_size=4, num_layers=1)
gru = GRU(input_size=1, hidden_size=4, num_layers=1)

outputs, _ = rnn.forward(seq)     # outputs: 每个时间步的隐藏状态
last_h = outputs[-1]              # 取最后一步做预测

BPTT 写法:forward 会把每一步、每一层的 cell 缓存存进 step_cache, 反向时用 restore_cache 直接恢复即可,不需要再 forward 一次来"重建"缓存:

rnn = RNN(input_size=1, hidden_size=4, num_layers=1)   # 承接上例
seq = [[0.1], [0.2], [0.3], [0.4]]

outputs, _ = rnn.forward(seq)
rnn.cells[0].zero_grad()          # 整个 BPTT 只清一次
dh = [0.1] * rnn.hidden_size
for t in reversed(range(len(seq))):
    rnn.cells[0].restore_cache(rnn.step_cache[t][0])   # 复用前向缓存
    _, dh = rnn.cells[0].backward(dh)

grad_W_ih, grad_W_hh, grad_b_ih, grad_b_hh = rnn.cells[0].get_grads()

两个容易踩的点:

  1. backward() 会把梯度原地累加到 cell 自己的缓冲区,所以整个 BPTT 只需 zero_grad() 一次;
  2. get_grads() 返回的就是这些缓冲区本身(不是副本),因此不要再对它做手工求和/累加—— 那等于把缓冲区加到它自己身上,梯度会按 2 的幂被放大(T=10 时实测放大 264 倍)。

文本生成

tp = TextProcessor(text)
dataset = tp.prepare_data(text, window_size=3)

# 训练字符级语言模型...
model = MLP([tp.vocab_size * window_size, 64, tp.vocab_size],
            activations=["leaky_relu", "softmax"])

# 自回归生成
generated = generate_text(model, tp, "君不见", length=15, temp=0.8)

运行示例

python AI.py

依次运行 12 段演示:回归(Model.fit)→ 分类(make_classifier + Softmax/CE)→ CNN(卷积→池化→展平→MLP)→ RNN & LSTM 序列预测 → 模型保存/加载 → GRU 序列预测 → Dropout + LayerNorm → 梯度裁剪 + StepLR → quick_train 一行训练 → Transformer 序列分类 → 字符级文本生成 → PyTorch 数值对齐。

测试

python test_ai.py     # 等价于 pytest test_ai.py

189 个测试覆盖所有组件,其中这几类是数值校验而不是只查形状:

测试类 校验内容
TestLayerNumericalGradients Layer / MLP 的 grad_w / grad_b、反向传播链(dL/dx)vs 数值梯度;含 softmax+CE 联合梯度约定
TestTransformerEncoderGradients TransformerEncoderLayer / TransformerEncoder 的 d_x 与 LayerNorm 参数梯度 vs 数值梯度(seq_len>1 必须测,见下方实现说明)
TestAttentionGradients MultiHeadAttention 的 W_q/W_k/W_v/W_o 解析梯度 vs 数值梯度
TestConv2dGradients Conv2d 的 grad_w / grad_b / dx vs 数值梯度(含 padding 与 stride=2)
TestBatchNormTraining BatchNorm1d 训练路径的 dx / gamma / beta vs 数值梯度,并与朴素实现逐位一致
TestStepCache / TestCellGradSemantics restore_cache 与「重新前向」逐位一致;一次 zero_grad + 逐步 backward == 各步梯度之和
TestValDataFormats / TestCrossEntropyTargets val_data 三种写法、CE 的 target 规范化

CI(GitHub Actions)执行 flake8 + pytest。

文件结构

.
├── AI.py            # 神经网络工具箱(Python 实现,所有代码)
├── test_ai.py       # 177 个单元测试
└── README.md

About

纯 Python 标准库实现的神经网络工具箱,零第三方依赖:全栈组件(全连接/CNN/RNN/LSTM/GRU/Transformer)与 sklearn 风格 API。

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages