居然用 Numpy 实现了一个深度学习框架

韩瑶
• 阅读 1187

今天跟大家分享一个牛逼的开源项目,该项目只用Numpy就实现了一个深度学习框架。

它不是一个demo, 而是一个实实在在能应用的深度学习框架,它的语法与PyTorch一致,用它可以实现CNNRNNDNN等经典的神经网络。

该框架对正在学习深度学习的朋友非常友好,因为它的代码量不到 2000 行,大家完全可以通过阅读源码来深入了解神经网络内部的细节。

如果大家读完源码自己也能做一个类似的深度学习框架,就更完美了。

1. 与 PyTorch 对比

接下来,我用该框架搭建一个简单的神经网络,并与PyTorch对比。

我们用这个神经网络来实现线性回归:

用下面的函数来生成训练样本

def synthetic_data(w, b, num_examples): 
    """生成y=w1*x1+w2*x2+b训练样本"""
    X = np.random.normal(0, 1, (num_examples, len(w)))
    y = np.dot(X, w) + b
    y += np.random.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))

w = np.array([2, -3.4])
b = 4.2
features, labels = synthetic_data(w, b, 1000)

这里我们令w1=2w2=-3.4b=4.2,随机生成1000个训练样本,x1x2存放在features变量中,y存放在labels变量中。

下面我们要做的是将这些样本输入神经网络中,训练出参数w1w2b,我们希望模型训练出来的参数跟实际的w1w2b越接近越好。

先用PyTorch来搭建神经网络,并训练模型。

from torch import nn, Tensor
import torch

# 只有一个神经元,并且是线性神经元
# 2代表有2个特征(x1、x2),1代表输出1个特征(y)
net = nn.Linear(2, 1)

print(f'初始w:{net.weight.data}')
print(f'初始b:{net.bias.data}')

# 用均方误差作为线性回归损失函数
loss = nn.MSELoss()
# 采用梯度下降算法优化参数,lr是学习速率
trainer = torch.optim.SGD(net.parameters(), lr=0.03)

# 转 Tensor
X = Tensor(features)
y = Tensor(labels)

# 迭代次数
num_epochs = 300
for epoch in range(num_epochs):
    l = loss(net(X), y)  # 计算损失
    trainer.zero_grad()
    l.backward()  # 反向传播,求导
    trainer.step()  # 更新参数
    l = loss(net(X), y) # 参数更新后,再次计算损失
    print(f'epoch {epoch + 1}, loss {round(float(l.data), 8)}')

print(f'模型训练后的w:{net.weight.data}')
print(f'模型训练后的b:{net.bias.data}')

这里我们用的是最简单的神经网络,只有一个神经元。

代码也比较简单,每行都做了注释。

输出的结果也是符合我们的预期,输出的损失如下:

epoch 1, loss 33.65092468
epoch 2, loss 29.78330231
epoch 3, loss 26.36030769
...
epoch 298, loss 0.0001022
epoch 299, loss 0.0001022
epoch 300, loss 0.0001022

前几轮损失比较大,等迭代300次后,损失已经非常小了。再看训练出来的参数:

初始w:tensor([[0.5753, 0.6624]])
初始b:tensor([-0.5713])
...
模型训练后的w:tensor([[ 1.9995, -3.4001]])
模型训练后的b:tensor([4.1998])

可以看到,经过训练后,模型的参数与设定的参数也是非常接近的。

下面,我们再用今天介绍的框架再来实现一遍。

from pydynet import nn, Tensor
from pydynet.optimizer import SGD

net = nn.Linear(2, 1)

print(f'初始w:{net.weight.data}')
print(f'初始b:{net.bias.data}')


loss = nn.MSELoss()
trainer = SGD(net.parameters(), lr=0.03)

X = Tensor(features)
y = Tensor(labels)

num_epochs = 300
for epoch in range(num_epochs):
    l = loss(net(X), y)  # 计算损失
    trainer.zero_grad()
    l.backward()  # 反向传播,求导
    trainer.step()  # 更新参数
    l = loss(net(X), y)  # 参数更新后,再次计算损失
    print(f'epoch {epoch + 1}, loss {round(float(l.data), 8)}')
    
print(f'模型训练后的w:{net.weight.data}')
print(f'模型训练后的b:{net.bias.data}')

代码从pydynet目录引入的,可以看到,用法跟PyTorch几乎是一模一样,输出参数如下:

初始w:[[-0.25983338]
 [-0.29252936]]
初始b:[-0.65241649]

...

模型训练后的w:[[ 2.00030734]
 [-3.39951581]]
模型训练后的b:[4.20060585]

训练出来的结果也是符合预期的。

2. 项目结构

pydynet项目架构如下:

居然用 Numpy 实现了一个深度学习框架

目前只有 5 个 Python源文件,不到 2000 行代码。

第一小节我们只实现最简单的神经网络,其他经典的神经网络,也有源码,大家可以自行查阅

居然用 Numpy 实现了一个深度学习框架

项目地址:https://github.com/Kaslanaria...

我非常喜欢这个项目,佩服这个项目的作者。如果你也正好在学习人工智能,强烈建议学习学习这个项目。

以上就是本次分享的所有内容,如果你觉得文章还不错,欢迎关注公众号:Python编程学习圈,每日干货分享,发送“J”还可领取大量学习资料,内容覆盖Python电子书、教程、数据库编程、Django,爬虫,云计算等等。或是前往编程学习网,了解更多编程技术知识。

点赞
收藏
评论区
推荐文章
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
PPDB:今晚老齐直播
【今晚老齐直播】今晚(本周三晚)20:0021:00小白开始“用”飞桨(https://www.oschina.net/action/visit/ad?id1185)由PPDE(飞桨(https://www.oschina.net/action/visit/ad?id1185)开发者专家计划)成员老齐,为深度学习小白指点迷津。
Stella981 Stella981
3年前
Python实现深度学习系列之【正向传播和反向传播】
前言在了解深度学习框架之前,我们需要自己去理解甚至去实现一个网络学习和调参的过程,进而理解深度学习的机理;为此,博主这里提供了一个自己编写的一个例子,带领大家理解一下网络学习的正向传播和反向传播的过程;除此之外,为了实现batch读取,我还设计并提供了一个简单的DataLoader类去模拟深度学习中数据迭代器的取样;并且
Stella981 Stella981
3年前
CPU推理性能提高数十倍,旷视天元计算图、MatMul优化深度解读
  机器之心发布  机器之心编辑部  !(http://dingyue.ws.126.net/2020/0806/6a6e4896j00qemtzy001ad000p000aop.jpg)本文针对旷视天元深度学习框架在推理优化过程中所涉及的计算图优化与MatMul优化进行深度解读。  背景及引言  在深度学
晴雯 晴雯
2年前
PyCharm CE 的安装与使用
是一个python库,也是一个基于python的深度学习框架。它由清华大学计算机系教授、博士生导师胡浩老师开发。它支持多线程,采用了并行计算的技术,实现了深度学习算法的加速。另外,它支持基于图的模型,并在此基础上提供了多种模型库和数据集。首先,我们需要准备
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(