百行代码实现mini版深度学习训练框架。该框架支持自动梯度求解:末端的tensor触发backward() 后自动完成计算图上所有tensor的梯度计算与更新。框架支持定义MLP模型,实现二分类训练:

这个目标看着有点难,但了解运算原理后会觉得自动梯度求解实现并不复杂。参考[1]的知识内容,用notebook实现一个简单的深度学习框架,并走通了MLP训练的全流程。
代码地址:mini_dl_framework.ipynb[2]
接下来,一步一步操作:
1 实现支持自动梯度的Tensor类
网络的基本要素:数据(tensor)、操作/公式(ops)、计算图(graph)。
看一个简单的线性神经网络的例子。如下图所示,所有神经元都在进行y=Wx运算,其中W为权重。权重由两个部分组成:数值(value, val)、梯度值(gradient, grad)。运算中:前向计算(forward)更新val,反向计算(backward)更新grad。

构建神经网络(模型)时,一般会显示定义forward过程,但对于backward计算则要借助训练框架完成。对于上例中如果调用y.backward(),如何触发所有层(layer)的权重梯度更新?
常用方法是计算图的递归遍历:每一层的神经元节点记录好自己的前向节点,然后逐层递归就能依次遍历出所有相关的节点,递归遍历时用拓扑图(topo)存储节点之间边(edges)的信息。

Tensor类的要素:数据包含val、grad、前向节点记录;ops包括forward算式、backward算式;同时具备求解topo图的函数、有链式法则的运算机制。
关键部分如下:
class Tensor:
""" stores a single scalar Tensor and its gradient """
def __init__(self, val, _children=(), _op=''):
self.val = val
self.grad = 0
self._backward = lambda: None # 反向运算公式
self._prev = set(_children) # 图关系中的上游节点
self._op = _op # 辅助变量,用于graphviz、debugging、etc
def backward(self):
# topological order all of the children in the graph
topo = []
visited = set()
def build_topo(v):
if v not in visited:
visited.add(v)
for child in v._prev:
build_topo(child)
topo.append(v)
build_topo(self)
# go one variable at a time and apply the chain rule to get its gradient
self.grad = 1
for v in reversed(topo):
v._backward()
# 示例:定义一个加法运算
def __add__(self, other):
other = other if isinstance(other, Tensor) else Tensor(other)
out = Tensor(self.val + other.val, (self, other), '+')
def _backward():
self.grad += out.grad
other.grad += out.grad
out._backward = _backward
return out
在此基础上,再给Tensor增加一些常见的ops(减法、乘法等)操作后,可完成如下运算程序:
x = Tensor(-2.0)
z = 2 * x
y1 = z + 5
y2 = (z * z).relu() + x + 3
loss = y1 - y2 + y2 * x
loss.backward()
打印每个tensor的val和grad:

用PyTorch校验计算是否正确:
import torch
x = torch.tensor([-2], dtype=torch.float32, requires_grad=True)
z = 2 * x
y1 = z + 5
y2 = (z * z).relu() + x + 3
loss = y1 - y2 + y2 * x
loss.backward()
打印对应的数值和梯度:

2 定义网络中的基本元素
在构建模型时,会用到一些基本的元素,神经元(Neuron)、层(Layer)、模块,其中神经元可以是线性的,也可以是非线性(Nonlinear)神经元。

class Module:
def zero_grad(self):
for p in self.parameters():
p.grad = 0
def parameters(self):
return []
class Neuron(Module):
def __init__(self, n_in, nonlinear=True):
self.w = [Tensor(random.uniform(-1,1)) for _ in range(n_in)]
self.b = Tensor(0)
self.nonlinear = nonlinear
def __call__(self, x):
act = sum((wi*xi for wi,xi in zip(self.w, x)), self.b)
return act.relu() if self.nonlinear else act
def parameters(self):
return self.w + [self.b]
def __repr__(self):
return f"{'ReLU' if self.nonlinear else 'Linear'}Neuron({len(self.w)})"
class Layer(Module):
def __init__(self, n_in, nout, **kwargs):
self.neurons = [Neuron(n_in, **kwargs) for _ in range(nout)]
def __call__(self, x):
out = [n(x) for n in self.neurons]
return out[0] if len(out) == 1 else out
def parameters(self):
return [p for n in self.neurons for p in n.parameters()]
def __repr__(self):
return f"Layer of [{', '.join(str(n) for n in self.neurons)}]"
定义MLP(Multi-Layer Perceptron)模块:

class MLP(Module):
def __init__(self, n_in, n_outs):
sz = [n_in] + n_outs
self.layers = [Layer(sz[i], sz[i+1], nonlinear= i!=len(n_outs)-1) for i in range(len(n_outs))]
def __call__(self, x):
for layer in self.layers:
x = layer(x)
return x
def parameters(self):
return [p for layer in self.layers for p in layer.parameters()]
def __repr__(self):
return f"MLP of [{', '.join(str(layer) for layer in self.layers)}]"
3 训练相关的函数定义
SGD优化器:
def SGD(model, learning_rate_decay):
learning_rate = 1.0 - 0.9*learning_rate_decay/100
for p in model.parameters():
p.val -= learning_rate * p.grad
用max-margin计算loss,并添加L2正则项,实现loss和acc的求解函数:
# loss and acc function
def loss_acc_func(parameters, scores, yb, batch_size=None):
# svm "max-margin" loss
losses = [(1 + -yi*scorei).relu() for yi, scorei in zip(yb, scores)]
data_loss = sum(losses) * (1.0 / len(losses))
# L2 regularization
alpha = 1e-4
reg_loss = alpha * sum((p*p for p in parameters))
total_loss = data_loss + reg_loss
# acc:
accuracy = [(yi > 0) == (scorei.val > 0) for yi, scorei in zip(yb, scores)]
return total_loss, sum(accuracy) / len(accuracy)
定义训练函数:
from tqdm import tqdm
def train(X, y, model, step=50, batch_size=None):
"""
训练模型:
:param X: 输入值
:param y: 真值
:param model: 训练模型
:param step: 训练步数
:param batch_size: 分批的尺寸
:return:
"""
bar = tqdm(range(step), colour="red", desc=f"Training", ncols=100)
for k in bar:
if batch_size is None:
Xb, yb = X, y
else:
ri = np.random.permutation(X.shape[0])[:batch_size]
Xb, yb = X[ri], y[ri]
inputs = [list(map(Tensor, xrow)) for xrow in Xb]
# forward the model to get scores
scores = list(map(model, inputs))
total_loss, acc = loss_acc_func(model.parameters(), scores, yb)
# backward
model.zero_grad()
total_loss.backward()
# optimizer update
SGD(model, k)
bar.set_postfix(loss=total_loss.val, acc=f"{acc*100}%")
4 训练与验证
用sklearn.datasets的blobs、circles数据训练MLP,观测二分类的训练结果。
4.1
blobs数据的训练
step1:定义两层的MLP模型
# 创建一个两层的网络, 参数361
model = MLP(2, [90, 1])
step2:获取训练数据集
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=100, n_features=2, centers=2, cluster_std=0.8, )
# 将标签数据y 从0,1 转换为 -1,1:
y = y*2 - 1

显示数据的分布图
step3:调用train函数,训练模型
# 训练6个epoch,每个epoch设置40step:
for i in range(6):
train(X, y, model, step=40)

loss打印输出
随着训练的进行loss在逐步下降,用plt渲染输出结果如下:

4.2
circles数据的训练
step1:定义三层的MLP模型
# 创建一个三层的网络
model = MLP(2, [15, 20, 1])
step2:获取训练数据
from sklearn.datasets import make_circles
X, y = make_circles(n_samples=100, noise=0.06)
# 将标签数据y 从0,1 转换为 -1,1:
y = y*2 - 1

显示数据的分布图
step3: 训练
# 训练并观测结果
for i in range(6):
train(X, y, model, step=30)

这个例子loss收敛得更快,用plt渲染输出结果如下:

5 网络可视化
通过graphviz库将网络显示出来。先将网络图的节点和边都遍历出来:
from graphviz import Digraph
# 将所有节点都遍历出来
def trace(root):
nodes, edges = set(), set()
def build(v):
if v not in nodes:
nodes.add(v)
for child in v._prev:
edges.add((child, v))
build(child)
build(root)
return nodes, edges
然后构造显示图:
def draw_dot(root, format='svg', rankdir='TB'):
"""
format: png | svg | ...
rankdir: TB (top to bottom graph) | LR (left to right) 显示方向
"""
nodes, edges = trace(root)
dot = Digraph(format=format, graph_attr={'rankdir': rankdir})
for n in nodes:
dot.node(name=str(id(n)), label = "{ data %.2f |grad %.2f }" % (n.val, n.grad), shape='record')
if n._op:
dot.node(name=str(id(n)) + n._op, label=n._op)
dot.edge(str(id(n)) + n._op, str(id(n)))
for n1, n2 in edges:
dot.edge(str(id(n1)), str(id(n2)) + n2._op)
return dot
测试:
x = Tensor(-2.0)
z = 2 * x
y = z.relu()
y.backward()
draw_dot(y, rankdir='TB')

总结:本文提供案例中的简易训练框架,从tensor、网络构建、训练函数定义,到支持MLP二分类,基本涵盖了训练关键要素,适合用于理解深度学习框架原理。读者可以切换数据集尝试,只要是一维数据都能训练,观测输出结果是否收敛,若不收敛可以调节MLP的深度或宽度。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~
这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费】

8869



被折叠的 条评论
为什么被折叠?



