PyTorch框架Tensor底层原理

神经网络,可以看做是一个非常复杂的公式的代码实现。计算机没法理解抽象的公式,需要我们翻译翻译。例如 y = 10 x + 3 y = 10x + 3 y=10x+3这个公式,我们想让计算机能用它来做计算,我们需要用编程语言做个转换,C++实现如下:

template<class T>
T linear(T x) {
   
  T a = 10;
  T b = 3;
  return a * x + b;
}

这个公式最终是平面中一系列的点所组成的一条直线。

当来到神经网络这个非常复杂的公式,最终你会在一个超空间里表现出一个我们无法想象的平面。我们每一条数据,都可以看成是一个超空间里面的点,所有数据在一起应该会组成一个超平面。神经网络的目的就是企图找到这个超平面。搭建模型的过程,就是提供一个有潜力拟合这个超平面的一部分的过程;训练的过程就是让这个公式尝试去拟合这个超平面的一部分的过程。通过训练,合适的模型最终会拟合一条曲线、平面、超平面一部分。为什么说是一部分呢,因为数据是有限的,我们所找到的这个公式也许最终也只是在我们所给出的数据范围内能够拟合这个超平面。超平面是固有的,公式是我们试图对这个超平面的复现。

神经网络经过学习,可以将一种信息转换成另信息的另一种描述。例如将一张猫的图片转换为“猫”这个文字。因为信息在神经网络中都是以浮点数来表现的,我们需要把我们的信息都转化到浮点数上来(定点也行,不过原理都一样)。这样我们的每一条数据就能表现为超平面上的一个点了。

信息转换成浮点数值之后,还需要有一个数据结构来存储,并且计算的中间结果也是一些浮点数,也需要一个数据结构来存储。

通常,经过转换的信息和计算的中间结果都会表现为一个多维数组,例如可以用一个三维数组表示图片、四维数组表示视频等。

虽然Python中的List可以表示多维数组,但是神经网络中一般不会使用List去存储数据,原因主要有以下几点:
首先,Python List是一个对象的集合,它可以存储任何对象,即便存储的是浮点数值,每一个浮点数值都经过对应Python对象的封装,添加了额外的空间去保存引用计数等信息,这会造成很多空间了浪费,并且离散的分布在内存中,不利于进行优化;
其次,Python List是没有定义有对其所表示的向量、矩阵等的点乘等操作,这些操作在神经网络中是基本的操作;
再有,对List的操作需要通过Python解析器来完成,相对于直接执行机器指令而言,这种方法速度是非常慢的。

这些缺点对于需要进行密集计算的神经网络来说,是无法忍受的。因此,需要一个便捷、高效的数据结构来存储计算过程中的中间数据等多维数组。不同的框架可能称呼不一样,例如在NumPy中称为ndarray。而在PyTorch中这个专门的数据结构称为Tensor。

Tensor(张量),可能在物理等其他领域表示的意义略有差别,但在计算机中的表现形式其实就是一个多维数组,就类似于一维数组称被称为向量、二维数组被称为矩阵一样。
Fig 1 Data reprecentation

Tensor的底层是用C/C++实现的,它不仅用于存储数据,还定义了对数据的操作。抛开这些不说,它与Python List最大的区别就是它使用一个连续的内存区域去存储数据,并且这些数据并未经过封装。Python List 和Tensor的区别如图2所示:

Fig 2

在图2中,左边表示Python List,可以看到每个数值类型都被封装成了一个PyObject对象,每个对象是独立分配内存、离散的存储在内存中;右边表示Tensor,Tensor中的数值统一的保存在一块连续的内存中,而且是不经过封装的。

你以为你已经看到Tensor的内部原理了?不,你没有。

真正管理存储这数据的内存区域的,是类Storage的实例,这个Storage的实例通过一个一维数组来存储数据。你没看错,是一维数组。不管外在表现为多少维的数组,都是存储在一个一维数组中。而怎么让这个一维数组看起来像多维数组,就是Tensor完成的。其内部实现关系如图3所示。
Fig 3 Tensor&Storage

Storage类中有一个指针指向存储数据的一位数组,而Tensor通过对Storage进行封装,使得在外部看来数据是多维的。
多个Tensor的实例可以指向同一个Storage,例如下面的代码:

import torch
a = torch.tensor([[4,1,5],[3,2,1]])
print(a.storage())
ar = a.reshape((3,2))
print(ar.storage())
at = a.transpose(1,0)
print(at.storage())

输出如下:

 4
 1
 5
 3
 2
 1
[torch.LongStorage of size 6]
 4
 1
 5
 3
 2
 1
[torch.LongStorage of size 6]
 4
 1
 5
 3
 2
 1
[torch.LongStorage of size 6]

他们看起来是不同的Tensor,但是指向的却是同一个Storage,如果你该表其中一个的内容,另一个Tensor也会随之改变,例如,我们将上面例子中ar的第二行第一个元素的值变成100,看看会发生什么:

ar[1,1] = 100
print(a.storage())
print(ar.storage())
print(at.storage(</
  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值