逆天了!用Numpy开发深度学习框架,透视神经网络训练过程


哈喽,大家好。

今天给大家分享一个非常牛逼的开源项目,用Numpy​开发了一个深度学习框架,语法与 Pytorch 基本一致。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

今天以一个简单的卷积神经网络为例,分析神经网络训练过程中,涉及的前向传播、反向传播、参数优化等核心步骤的源码。

使用的数据集和代码已经打包好,文末有获取方式。

1. 准备工作

先准备好数据和代码。

1.1 搭建网络

首先,下载框架源码,地址:https://github.com/duma-repo/PyDyNet

git clone https://github.com/duma-repo/PyDyNet.git

搭建LeNet卷积神经网络,训练三分类模型。

在PyDyNet目录直接创建代码文件即可。

from pydynet import nn

class LeNet(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 6, kernel_size=5, padding=2)
self.conv2 = nn.Conv2d(6, 16, kernel_size=5)
self.avg_pool = nn.AvgPool2d(kernel_size=2, stride=2, padding=0)
self.sigmoid = nn.Sigmoid()
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 3)

def forward(self, x):
x = self.conv1(x)
x = self.sigmoid(x)
x = self.avg_pool(x)

x = self.conv2(x)
x = self.sigmoid(x)
x = self.avg_pool(x)

x = x.reshape(x.shape[0], -1)

x = self.fc1(x)
x = self.sigmoid(x)
x = self.fc2(x)
x = self.sigmoid(x)
x = self.fc3(x)

return x

可以看到,网络的定义与Pytorch语法完全一样。

我提供的源代码里,提供了 summary 函数可以打印网络结构。

1.2 准备数据

训练数据使用Fanshion-MNIST数据集,它包含10个类别的图片,每个类别 6k 张。

为了加快训练,我只抽取了前3个类别,共1.8w张训练图片,做一个三分类模型。

1.3 模型训练

import pydynet
from pydynet import nn
from pydynet import optim

lr, num_epochs = 0.9, 10
optimizer = optim.SGD(net.parameters(),
lr=lr)
loss = nn.CrossEntropyLoss()

for epoch in range(num_epochs):
net.train()
for i, (X, y) in enumerate(train_iter):
optimizer.zero_grad()
y_hat = net(X)
l = loss(y_hat, y)
l.backward()
optimizer.step()

with pydynet.no_grad():
metric.add(l.numpy() * X.shape[0],
 accuracy(y_hat, y),
 X.shape[0])

训练代码也跟Pytorch一样。

下面重点要做的就是深入模型训练的源码,来学习模型训练的原理。

2. train、no_grad和eval

模型开始训练前,会调用net.train。

def train(self, mode: bool = True):
set_grad_enabled(mode)
self.set_module_state(mode)

可以看到,它会将grad​(梯度)设置成True​,之后创建的Tensor​是可以带梯度的。Tensor带上梯度后,便会将其放入计算图中,等待求导计算梯度。

而下面的with no_grad(): 代码

class no_grad:
def __enter__(self) -> None:
self.prev = is_grad_enable()
set_grad_enabled(False)

会将grad​(梯度)设置成False​,这样之后创建的Tensor不会放到计算图中,自然也不需要计算梯度,可以加快推理。

我们经常在Pytorch​中看到net.eval()的用法,我们也顺便看一下它的源码。

def eval(self):
return self.train(False)

可以看到,它直接调用train(False)​来关闭梯度,效果与no_grad()类似。

所以,一般在训练前调用train​打开梯度。训练后,调用eval关闭梯度,方便快速推理。

3. 前向传播

前向传播除了计算类别概率外,最最重要的一件事是按照前传顺序,将网络中的 tensor​ 组织成计算图,目的是为了反向传播时计算每个tensor的梯度。

tensor在神经网络中,不止用来存储数据,还用计算梯度、存储梯度。

以第一层卷积操作为例,来查看如何生成计算图。

def conv2d(x: tensor.Tensor,
 kernel: tensor.Tensor,
 padding: int = 0,
 stride: int = 1):
'''二维卷积函数
'''
N, _, _, _ = x.shape
out_channels, _, kernel_size, _ = kernel.shape
pad_x = __pad2d(x, padding)
col = __im2col2d(pad_x, kernel_size, stride)
out_h, out_w = col.shape[-2:]
col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N * out_h * out_w, -1)
col_filter = kernel.reshape(out_channels, -1).T
out = col @ col_filter
return out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)

x​是输入的图片,不需要记录梯度。kernel是卷积核的权重,需要计算梯度。

所以,pad_x = __pad2d(x, padding)​ 生成的新的tensor也是不带梯度的,因此也不需要加入计算图中。

而kernel.reshape(out_channels, -1)​产生的tensor则是需要计算梯度,也需要加入计算图中。

下面看看加入的过程:

def reshape(self, *new_shape):
return reshape(self, new_shape)

class reshape(UnaryOperator):
'''
张量形状变换算子,在Tensor中进行重载

Parameters
----------
new_shape : tuple
变换后的形状,用法同NumPy
'''
def __init__(self, x: Tensor, new_shape: tuple) -> None:
self.new_shape = new_shape
super().__init__(x)

def forward(self, x: Tensor)
return x.data.reshape(self.new_shape)

def grad_fn(self, x: Tensor, grad: np.ndarray)
return grad.reshape(x.shape)

reshape​函数会返回一个reshape​类对象,reshape​类继承了UnaryOperator​类,并在__init__函数中,调用了父类初始化函数。

class UnaryOperator(Tensor):
def __init__(self, x: Tensor) -> None:
if not isinstance(x, Tensor):
x = Tensor(x)
self.device = x.device
super().__init__(
data=self.forward(x),
device=x.device,
# 这里 requires_grad 为 True
requires_grad=is_grad_enable() and x.requires_grad,
)

UnaryOperator​类继承了Tensor​类,所以reshape​对象也是一个tensor。

在UnaryOperator的__init__​函数中,调用Tensor​的初始化函数,并且传入的requires_grad​参数是True,代表需要计算梯度。

requires_grad​的计算代码为is_grad_enable() and x.requires_grad,is_grad_enable()​已经被train​设置为True​,而x​是卷积核,它的requires_grad​也是True。

class Tensor:
def __init__(
self,
data: Any,
dtype=None,
device: Union[Device, int, str, None] = None,
requires_grad: bool = False,
) -> None:
if self.requires_grad:
# 不需要求梯度的节点不出现在动态计算图中
Graph.add_node(self)

最终在Tensor​类的初始化方法中,调用Graph.add_node(self)​将当前tensor加入到计算图中。

同理,下面使用requires_grad=True的tensor​常见出来的新tensor都会放到计算图中。

经过一次卷积操作,计算图中会增加 6 个节点。

4. 反向传播

一次前向传播完成后,从计算图中最后一个节点开始,从后往前进行反向传播。

l = loss(y_hat, y)
l.backward()

经过前向网络一层层传播,最终传到了损失张量l。

以l​为起点,从前向后传播,就可计算计算图中每个节点的梯度。

backward的核心代码如下:

def backward(self, retain_graph: bool = False):

for node in Graph.node_list[y_id::-1]:
grad = node.grad
for last in [l for l in node.last if l.requires_grad]:
add_grad = node.grad_fn(last, grad)

last.grad += add_grad

Graph.node_list[y_id::-1]将计算图倒序排。

node​是前向传播时放入计算图​中的每个tensor。

node.last​ 是生成当前tensor的直接父节点。

调用node.grad_fn计算梯度,并反向传给它的父节点。

grad_fn​其实就是Tensor的求导公式,如:

class pow(BinaryOperator):
'''
幂运算算子,在Tensor类中进行重载

See also
--------
add : 加法算子
'''
def grad_fn(self, node: Tensor, grad: np.ndarray)
if node is self.last[0]:
return (self.data * self.last[1].data / node.data) * grad

return​后的代码其实就是幂函数求导公式。

假设y=x^2,x​的导数为2x。

5. 更新参数

反向传播计算梯度后,便可以调用优化器,更新模型参数。

l.backward()
optimizer.step()

本次训练我们用梯度下降SGD算法优化参数,更新过程如下:

def step(self):
for i in range(len(self.params)):
grad = self.params[i].grad + self.weight_decay * self.params[i].data
self.v[i] *= self.momentum
self.v[i] += self.lr * grad
self.params[i].data -= self.v[i]
if self.nesterov:
self.params[i].data -= self.lr * grad

self.params​是整个网络的权重,初始化SGD时传进去的。

step​函数最核心的两行代码,self.v[i] += self.lr * grad​ 和 self.params[i].data -= self.v[i]​,用当前参数 - 学习速率 * 梯度​更新当前参数。

这是机器学习的基础内容了,我们应该很熟悉了。

一次模型训练的完整过程大致就串完了,大家可以设置打印语句,或者通过DEBUG的方式跟踪每一行代码的执行过程,这样可以更了解模型的训练过程。


# 图中  # 这是  # 设置成  # 会将  # 时计  # 为例  # 也不  # 可以看到  # 求导  # 前向  # 深度学习  # https  # pytorch  # 算法  # github  # padding  # 对象  # 继承  # 父类  # numpy 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化91478 】 【 技术知识72672 】 【 云计算0 】 【 GEO优化84317 】 【 优选文章0 】 【 营销推广36048 】 【 网络运营41350 】 【 案例网站102563 】 【 AI智能45237


相关推荐: AI周报生成工具有哪些_一键生成工作总结的AI工具推荐  百度AI对话助手入口 智能聊天机器人入口  宝可梦化石精灵大揭秘:晶灿钻石视角下的精灵演化  使用AI简化多机位播客视频编辑:Eddie AI全面指南  GoHighLevel AI Agent:终极指南,释放你的CRM潜力  AI问卷调查生成工具有哪些_一键生成调研表单的AI工具推荐  Miaoaotalk 猫语翻译器测评:宠物沟通新体验?  秀米AI智能排版怎样生成节日专题模板_秀米AI智能排版节日模板调用【技巧】  微信AI数字人能否识别语音消息_微信AI数字人语音识别与回复设置【教程】  OpenAI ChatGPT Agent:AI自主任务的未来  AI驱动的合同审查:Adobe Acrobat AI助手提升效率与准确性  教你用AI把照片变成动漫风格,3个简单步骤刷爆朋友圈  怎么用AI制作数字人短视频?3步教你创建虚拟主播  ClaudePC端怎么设主题色_ClaudePC端主题设置步骤【教程】  通义千问怎样优化提示词效果_通义千问提示词优化技巧【攻略】  N8N 自动化教程:HR 简历智能分析系统搭建指南  AI驱动营销:如何利用人工智能构建高效营销漏斗  去哪旅行ai抢票助手怎样提升抢票速度_去哪旅行ai抢票助手加速包与多通道使用【技巧】  千问怎么用提示词生成演讲稿_千问演讲稿提示词框架与开场【教程】  Lovart AI设计助手:AI驱动设计,零成本开启创意新纪元  美图秀秀AI抠图如何修复抠图误差_美图秀秀AI误差修复与手动涂抹【指南】  AI猫咪视频创作指南:轻松打造百万级YouTube Shorts  AI UGC生成器深度测评:四大工具横向对比分析  Depseek怎样写产品描述提示词_Depseek产品文案提示词技巧【技巧】  泰米尔电影猜谜游戏:挑战你的电影知识极限!  2025年AI图像生成指南:Google Gemini Nano Banana教程  利用 ChatGPT 进行复杂数学公式的推导教程  利用 ChatGPT 进行高质量代码重构与优化  精明小鱼:儿童动画寓言故事及启示  提升企业效率:QR Platform管理后台功能全面解析  通义万相AI绘画怎么用_通义万相AI绘画使用方法详细指南【教程】  AI 编码助手大比拼:Gemini、Tabnine 和 Cline 的深度测评  通义万相做小红书配图怎么用_通义万相做小红书配图使用方法详细指南【教程】  feelin聊天官方网站入口 feelinAl官方网站  2025年度AMD处理器终极评选:年度最佳CPU推荐  千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  YOU.com AI搜索引擎:Python代码示例及使用指南  腾讯混元图像3.0上线LiblibAI,80B参数助力创作者高效出图  AI驱动KDP封面设计:NURIE CREATOR教程  打破平庸:激发你的内在动力,重塑卓越人生  Claude怎么用新功能会议纪要_Claude纪要生成使用【步骤】  E-LabVine:AI赋能的数字化学习平台,提升高中学业表现  怎么用AI帮你进行头脑风暴并分类?5分钟输出结构化创意清单  Depseek如何让提示词包含上下文_Depseek上下文补充提示词写法【步骤】  如何利用豆包 AI 快速查询当地生活服务资讯  FeelinAI聊天网页版 Feelin官方网站地址  AI面试助手:提升招聘效率的终极工具  百度AI搜索如何开启无痕搜索_百度AI搜索无痕模式设置与隐私保护【攻略】  AI驱动音频优化:提升音质的终极指南  VideoInu AI 动画制作:教程、功能与Pro账户赠送 

 2023-04-12

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

南京市珐之弘网络技术有限公司


南京市珐之弘网络技术有限公司

南京市珐之弘网络技术有限公司专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 87067657

 13565296790

 87067657@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.