引言

本着“凡我不能创造的,我就不能理解”的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导。

要深入理解深度学习,从零开始创建的经验非常重要,从自己可以理解的角度出发,尽量不适用外部完备的框架前提下,实现我们想要的模型。本系列文章的宗旨就是通过这样的过程,让大家切实掌握深度学习底层实现,而不是仅做一个调包侠。
本系列文章首发于微信公众号:JavaNLP

本文基于前面介绍的计算图知识,开始实现我们自己的深度学习框架。

就像PyTorch用Tensor来表示张量一样,我们也创建一个自己的Tensor

数据类型

由于我们自己的Tensor也需要进行矩阵运算,因此我们直接封装最常用的矩阵运算工具——NumPy。

首先,我们增加帮助函数来确保用到的数据类型为np.ndarray

# 默认数据类型
_type = np.float32# 可以转换为Numpy数组的类型
Arrayable = Union[float, list, np.ndarray]def ensure_array(arrayable: Arrayable) -> np.ndarray:""":param arrayable::return:"""if isinstance(arrayable, np.ndarray):# 如果本身是ndarrayreturn arrayable# 转换为Numpy数组return np.array(arrayable, dtype=_type)

Tensor初探

所有的代码都尽量添加类型提示(Typing),已增加代码的可读性。接下来,创建我们自己的Tensor实现:

class Tensor:def __init__(self, data: Arrayable, requires_grad: bool = False) -> None:'''初始化Tensor对象Args:data: 数据requires_grad: 是否需要计算梯度'''# data 是 np.ndarrayself._data = ensure_array(data)self.requires_grad = requires_grad# 保存该Tensor的梯度self._grad = Noneif self.requires_grad:# 初始化梯度self.zero_grad()# 用于计算图的内部变量self._ctx = None

调用ensure_array确保传过来的是一个Numpy数组。requires_grad表示是否需要计算梯度。

下面增加一些属性方法(属于上面Tensor类):

    @propertydef grad(self):return self._grad@propertydef data(self) -> np.ndarray:return self._data@data.setterdef data(self, new_data: np.ndarray) -> None:self._data = ensure_array(new_data)# 重新赋值后就没有梯度了self._grad = None

通过@property来确保梯度是只读的,同时让保存的数据data是可读可写的,当修改data时,需要清空梯度。因为绑定的数据已经发生了变化。

我们知道Tensor作为张量,它是有形状(shape)、维度(dimension)等相关属性的,下面我们就来实现:

    # ****一些常用属性****@propertydef shape(self) -> Tuple:'''返回Tensor各维度大小的元素'''return self.data.shape@propertydef ndim(self) -> int:'''返回Tensor的维度个数'''return self.data.ndim@propertydef dtype(self) -> np.dtype:'''返回Tensor中数据的类型'''return self.data.dtype@propertydef size(self) -> int:'''返回Tensor中元素的个数 等同于np.prod(a.shape)Returns:'''return self.data.size

Tensor的初始化方法中,有进行梯度初始化的方法,看一下是如何实现的:

    def zero_grad(self) -> None:'''将梯度初始化为0Returns:'''self._grad = Tensor(np.zeros_like(self.data, dtype=_type))

为了方便调试,我们实现了了__repr__方法。同时实现__len_魔法方法,返回数据的长度。

    def __repr__(self) -> str:return f"Tensor({self.data}, requires_grad={self.requires_grad})"def __len__(self) -> int:return len(self.data)

最后,实现两个比较有用的方法。

    def assign(self, x) -> "Tensor":'''将x的值赋予当前Tensor'''x = ensure_tensor(x)# 维度必须一致assert x.shape == self.shapeself.data = x.datareturn selfdef numpy(self) -> np.ndarray:"""转换为Numpy数组"""return self.data

assign用于给当前Tensor赋值,因为我们上面让data是只读了,所以需要额外提供这个方法。

numpy则是将当前Tensor对象转换为Numpy数组。

类似ensure_array,我们也提供了一个确保为Tensor的帮助方法。

Tensorable = Union["Tensor", float, np.ndarray]def ensure_tensor(tensoralbe: Tensorable) -> "Tensor":'''确保是Tensor对象'''if isinstance(tensoralbe, Tensor):return tensoralbereturn Tensor(tensoralbe)

测试

写完代码进行测试是一个好习惯,我们今天暂且在__main__里面测试:

if __name__ == '__main__':t = Tensor(range(10))print(t)print(t.shape)print(t.size)print(t.dtype)

输出:

Tensor([0. 1. 2. 3. 4. 5. 6. 7. 8. 9.], requires_grad=False)
(10,)
10
float32

完整代码

完整代码笔者上传到了程序员最大交友网站上去了,地址:

从零实现深度学习框架——实现自己的Tensor对象相关推荐

  1. python学习框架图-从零搭建深度学习框架(二)用Python实现计算图和自动微分

    我们在上一篇文章<从零搭建深度学习框架(一)用NumPy实现GAN>中用Python+NumPy实现了一个简单的GAN模型,并大致设想了一下深度学习框架需要实现的主要功能.其中,不确定性最 ...

  2. 从零实现深度学习框架——GloVe从理论到实战

    引言 本着"凡我不能创造的,我就不能理解"的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导.

  3. 从零实现深度学习框架——Seq2Seq从理论到实战【实战】

    引言 本着"凡我不能创造的,我就不能理解"的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导.

  4. 从零实现深度学习框架——RNN从理论到实战【理论】

    引言 本着"凡我不能创造的,我就不能理解"的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导.

  5. 从零实现深度学习框架——深入浅出Word2vec(下)

    引言 本着"凡我不能创造的,我就不能理解"的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导. 要深入理解深度学 ...

  6. 从零实现深度学习框架——从共现矩阵到点互信息

    引言 本着"凡我不能创造的,我就不能理解"的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导.

  7. 从零实现深度学习框架——LSTM从理论到实战【理论】

    引言 本着"凡我不能创造的,我就不能理解"的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导.

  8. 深度学习框架集成平台C++ Guide指南

    深度学习框架集成平台C++ Guide指南 这个指南详细地介绍了神经网络C++的API,并介绍了许多不同的方法来处理模型. 提示 所有框架运行时接口都是相同的,因此本指南适用于所有受支持框架(包括Te ...

  9. 实现AI技术自立自强,国产深度学习框架面临三大难题

    作为推动AI应用大规模落地的关键力量,深度学习框架的重要性日益凸显.它不仅关系国计民生的行业和领域广泛的应用,同样也对信息系统的科技安全有着决定性的意义. "深度学习框架在人工智能技术体系中 ...

  10. 漫画:我用深度学习框架画下女朋友最美的脸

    这不,又一个程序员为爱变身灵魂画手,看得我都想学画画了. 阿华是幸运的,因为他找到了对的方法,事半功倍,最终有情人终成眷属.这也得益于 PyTorch 的易学易用,大多数人第一次使用 PyTorch ...

最新文章

  1. Ansible — Inventory 清单文件
  2. 2014多校第四场1006 || HDU 4902 Nice boat (线段树 区间更新)
  3. 非常不错的sharepoint webpart工具集
  4. 10个步骤的筛选器模式
  5. 【2021.02.09更新】数字信号处理公式推导
  6. Vue3.0 Composition API与Vue2.x 使用的 Options API
  7. 【J2me3D系列学习文章之三】(立即模式)对立方体进行变换操作-旋转、缩放、平移...
  8. 30岁女IT工程师感叹:靠这工具,把报表做成养老工作,月薪快3W
  9. 华为机试HJ17:坐标移动
  10. 【Luogu1616】疯狂的采药
  11. 通过AT指令实现ESP8266模块和TCP服务器的数据传输
  12. 运动目标跟踪(四)--搜索算法优化搜索方向之Camshift
  13. 深度学习在NLP领域的发展(一)
  14. Github网站中文汉化浏览器插件
  15. mac book pro osX10.8.5无法创建可引导的usb驱动器格式化失败解决方案
  16. npm start报错的log文件在哪里
  17. 《漫画算法》终于出电子书了!
  18. PostgreSQL行级安全策略RLS和数据加密
  19. [知识点滴]HTML5元素垂直居中那些事?
  20. 最新WordPress二次元博客主题Sakurairo模板源码+多彩且实用

热门文章

  1. MaxtoCode问题说明汇总 (更新至 1.16 版)
  2. 有行统计项和列统计项的行列转换,以及EXCEL导入SQL的简单应用
  3. Spark SQL初始化和创建DataFrame的几种方式
  4. 两个对象值同样(x.equals(y) == true),但却可有不同的hash code,这句话对不正确?
  5. final、finally 和 finalize的区别
  6. Android雁翎刀之ImageView之定制头像
  7. .NET与SAP的来往(转)
  8. 禁用AutoCAD的命令
  9. (Sublime Text 3)完美替换 GAMS 难用的编辑器
  10. Java基础语法-方法的定义、调用以及static关键字的使用