逆天了!用Numpy开发深度学习框架,透视神经网络训练过程
学习知识要善于思考,思考,再思考!今天golang学习网小编就给大家带来《逆天了!用Numpy开发深度学习框架,透视神经网络训练过程》,以下内容主要包含等知识点,如果你正在学习或准备学习科技周边,就都不要错过本文啦~让我们一起来看看吧,能帮助到你就更好了!
哈喽,大家好。
今天给大家分享一个非常牛逼的开源项目,用Numpy开发了一个深度学习框架,语法与 Pytorch 基本一致。
今天以一个简单的卷积神经网络为例,分析神经网络训练过程中,涉及的前向传播、反向传播、参数优化等核心步骤的源码。
使用的数据集和代码已经打包好,文末有获取方式。
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的方式跟踪每一行代码的执行过程,这样可以更了解模型的训练过程。
终于介绍完啦!小伙伴们,这篇关于《逆天了!用Numpy开发深度学习框架,透视神经网络训练过程》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布科技周边相关知识,快来关注吧!

- 上一篇
- ChatGPT背后真正的英雄:OpenAI首席科学家Ilya Sutskever的信仰之跃

- 下一篇
- 坚持了16年,这次百度秀了什么?
-
- 舒服的裙子
- 这篇文章内容真及时,作者加油!
- 2023-06-07 18:12:25
-
- 故意的中心
- 很好,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢up主分享技术贴!
- 2023-05-24 15:28:21
-
- 天真的柚子
- 太详细了,已加入收藏夹了,感谢楼主的这篇技术文章,我会继续支持!
- 2023-05-18 07:22:06
-
- 友好的导师
- 这篇技术贴出现的刚刚好,太细致了,赞 👍👍,码住,关注楼主了!希望楼主能多写科技周边相关的文章。
- 2023-05-08 21:36:56
-
- 着急的酸奶
- 这篇技术贴真是及时雨啊,太全面了,写的不错,已收藏,关注师傅了!希望师傅能多写科技周边相关的文章。
- 2023-04-21 16:08:48
-
- 小巧的丝袜
- 很有用,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢作者分享技术文章!
- 2023-04-21 03:38:41
-
- 科技周边 · 人工智能 | 2小时前 |
- Linux服务器时间校对命令详解及应用
- 420浏览 收藏
-
- 科技周边 · 人工智能 | 3小时前 | 量子计算 营收 skywater 第一季度 ThermaView
- SkyWaterQ1营收6130万,强势新平台吸睛
- 293浏览 收藏
-
- 科技周边 · 人工智能 | 4小时前 |
- 问界新M7牧野青发布颜值爆表24.98万起
- 416浏览 收藏
-
- 科技周边 · 人工智能 | 4小时前 |
- 2024财年车企净利润榜:丰田居首,小米排15
- 426浏览 收藏
-
- 科技周边 · 人工智能 | 4小时前 | 开源 国产品牌 5G手机 电子信息制造业 软件及信息技术服务业
- 工信部数据:1-2月5G手机出货4161.9万,国产占85%
- 289浏览 收藏
-
- 科技周边 · 人工智能 | 9小时前 | 面板 lge
- LG东南亚工厂暂停,北美成新重心
- 487浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 毕业宝AIGC检测
- 毕业宝AIGC检测是“毕业宝”平台的AI生成内容检测工具,专为学术场景设计,帮助用户初步判断文本的原创性和AI参与度。通过与知网、维普数据库联动,提供全面检测结果,适用于学生、研究者、教育工作者及内容创作者。
- 23次使用
-
- AI Make Song
- AI Make Song是一款革命性的AI音乐生成平台,提供文本和歌词转音乐的双模式输入,支持多语言及商业友好版权体系。无论你是音乐爱好者、内容创作者还是广告从业者,都能在这里实现“用文字创造音乐”的梦想。平台已生成超百万首原创音乐,覆盖全球20个国家,用户满意度高达95%。
- 33次使用
-
- SongGenerator
- 探索SongGenerator.io,零门槛、全免费的AI音乐生成器。无需注册,通过简单文本输入即可生成多风格音乐,适用于内容创作者、音乐爱好者和教育工作者。日均生成量超10万次,全球50国家用户信赖。
- 30次使用
-
- BeArt AI换脸
- 探索BeArt AI换脸工具,免费在线使用,无需下载软件,即可对照片、视频和GIF进行高质量换脸。体验快速、流畅、无水印的换脸效果,适用于娱乐创作、影视制作、广告营销等多种场景。
- 33次使用
-
- 协启动
- SEO摘要协启动(XieQiDong Chatbot)是由深圳协启动传媒有限公司运营的AI智能服务平台,提供多模型支持的对话服务、文档处理和图像生成工具,旨在提升用户内容创作与信息处理效率。平台支持订阅制付费,适合个人及企业用户,满足日常聊天、文案生成、学习辅助等需求。
- 36次使用
-
- GPT-4王者加冕!读图做题性能炸天,凭自己就能考上斯坦福
- 2023-04-25 501浏览
-
- 单块V100训练模型提速72倍!尤洋团队新成果获AAAI 2023杰出论文奖
- 2023-04-24 501浏览
-
- ChatGPT 真的会接管世界吗?
- 2023-04-13 501浏览
-
- VR的终极形态是「假眼」?Neuralink前联合创始人掏出新产品:科学之眼!
- 2023-04-30 501浏览
-
- 实现实时制造可视性优势有哪些?
- 2023-04-15 501浏览