\quad \quad PyTorch更新基本函数~ \quad \quad
张量 tensor
torch.is_tensor()
如果obj是一个tensor,则返回True
。
torch.is_tensor(obj)
torch.is_storage()
如果obj是一个storage对象,则返回True
torch.is_storage(obj)
那么什么是Storage?Storage类型是pytorch中的一个类型,它与tensor是对应的。。
- 主要存储在信息区tensor的
形状 、步长 、数据类型 等信息,其真正的数据保存为连续数组,存储在存储区中。 - 一般来说pytorch中tensor数据非常大,可能成千上万,所以我们的信息区一般占用的内存相对较少,主要内存的占用取决于tensor中元素的数量,即存储区的大小。
其实流行的一点是,我们的Tensor相当于一组描述符,可以类比于操作系统中的描述符PCB,而Storage是我们真正存储过程数据的位置。
一般来说,一个tensor对应一个storage,storage是在data上面的封装接口,方便我们使用。tensor头部信息一般不同,但它们使用Storage也许是一样的(即
举个例子:
>>> a = torch.rand(3, 5) >>> a tensor([[0.4575, 0.4711, 0.7367, 0.3744, 0.2197], [0.3335, 0.5182, 0.4853, 0.5433, 0.9604], [0.5801, 0.3798, 0.5403, 0.0130, 0.3634]]) >>> a.storage()
0.45748573541641235
0.4711431860923767
0.7366769313812256
0.37439149618148804
0.21970176696777344
0.3335157632827759
0.5181728005409241
0.4852680563926697
0.5433450937271118
0.960439920425415
0.580078125
0.3797873854637146
0.540315568447113
0.013004720211029053
0.36340975761413574
[torch.FloatStorage of size 15]
可以看到Storge只是一连串的数据,并没有别的信息。而上面是tensor,至于为什么print(a)
会显示数据,而不是显示头部信息,这是因为pytorch为了方便查看进行的操作,使得显示的时候会显示数据,不然查看一个变量会很麻烦。
如果加上一句a.requires_grad = True
,即如下代码:
>>> a = torch.rand(3, 5)
>>> a.requires_grad = True
>>> a
tensor([[0.4575, 0.4711, 0.7367, 0.3744, 0.2197],
[0.3335, 0.5182, 0.4853, 0.5433, 0.9604],
[0.5801, 0.3798, 0.5403, 0.0130, 0.3634]], requires_grad=True)
>>> a.storage()
0.45748573541641235
0.4711431860923767
0.7366769313812256
0.37439149618148804
0.21970176696777344
0.3335157632827759
0.5181728005409241
0.4852680563926697
0.5433450937271118
0.960439920425415
0.580078125
0.3797873854637146
0.540315568447113
0.013004720211029053
0.36340975761413574
[torch.FloatStorage of size 15]
可以发现Storage并没有改变,它只有数据,没有别的东西。只是我们的Tensor中增加了描述符,描述了我们这个tensor是有梯度的。
torch.numel()
返回input张量中的tensor.size()
乘起来。
torch.numel(input)
这个函数在统计模型中所含参数个数时比较有用。
创建操作
torch.eye()
返回一个2维张量,对角线为1,其它位置为0。
- n (int) 行数
- m (int, optional) 列数,如果为None,则默认为n
- out (Tensor, optional)
torch.eye(n, m=None, out=None)
torch.Tensor()
首先明确一点,这是python类,是默认张量类型torch.FloatTensor()
的别名,我们每次调用torch.Tensor([1, 2, 3, 4, 5])
来构造一个tensor的时候,会调用Tensor类的构造函数,生成一个单精度浮点类型的张量。
>>> a = torch.Tensor([1, 2, 3, 4, 5])
>>> print(a.dtype)
torch.float32
>>> print(a.type())
torch.FloatTensor
它不能指定数据类型,除非转成一个已知数据类型的张量,使用type_as(tesnor)
将张量转换为给定类型的张量
torch.tensor()
torch.tensor()
仅仅是python的函数,函数原型为:
torch.tensor(data, dtype=None, device=None, requires_grad=False)
其中data
可以是:list
,tuple
,NumPy
,ndarray
等其他类型,torch.tensor
会从data
中的数据部分做拷贝(而不是直接引用),根据原始数据类型生成torch.LongTensor
,torch.FloatTensor
和torch.DoubleTensor
。
>>> a = torch.tensor([0, 1, 2, 3, 4])
>>> b = torch.tensor([0., 1., 2., 3., 4.])
>>> a.type()
'torch.LongTensor'
>>> b.type()
'torch.FloatTensor'
此外根据函数定义,可以生成指定dtype
的tensor。
>>> torch.tensor([0, 1, 2, 3, 4], dtype=torch.long)
tensor([0, 1, 2, 3, 4])
>>> torch.tensor([0., 1., 2., 3., 4.], dtype=torch.double)
tensor([0., 1., 2., 3., 4.], dtype=torch.float64)
torch.from_numpy()
将numpy.ndarray
转换为Tensor
。
torch.from_numpy(ndarray)
例子:
>>> a = np.array([1, 2, 3])
>>> t = torch.from_numpy(a)
>>> t[0] = -1
>>> a
array([-1, 2, 3])
>>> t
tensor([-1, 2, 3], dtype=torch.int32)
可以看到a
和t
都变了,这一点在使用中一定要注意!
torch.linspace()
返回一个1维张量,包含在start
和end
上均匀间隔的steps
个点。
- start (float) -序列起点
- end (float) - 序列终点
- steps (int) - 在start与end间生成的样本数
- out (Tensor, optional) - 结果张量
torch.linspace(start, end, steps=100, out=None)
例子:
>>> a = torch.linspace(0, 10, 2)
tensor([0.0000, 2.0000, 4.0000, 6.0000, 8.0000, 10.0000])
torch.logspace()
创建对数均分的1维张量。返回一个1维张量,包含在区间 b a s e s t a r t base^{start} basestart和 b a s e e n d base^{end} baseend上以对数刻度均匀间隔的steps
个点。 注意事项:长度为steps
,底为base
- start: 数列起始值
- end: 数列结束值
- steps: 数列长度
- base: 对数函数的底,默认为10
torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
官方例子:
>>> torch.logspace(start=-10, end=10, steps=5)
tensor([ 1.0000e-10, 1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])
>>> torch.logspace(start=0.1, end=1.0, steps=5)
tensor([ 1.2589, 2.1135, 3.5481, 5.9566, 10.0000])
>>> torch.logspace(start=0.1, end=1.0, steps=1)
tensor([1.2589])
>>> torch.logspace(start=2, end=2, steps=1, base=2)
tensor([4.0])
torch.ones()
返回一个全为1的张量,形状由可变参数sizes
定义。
torch.ones(*sizes, out=None)
torch.ones_like()
返回一个填充了标量值1的张量,其大小与input
相同 。torch.ones_like(input)
相当于:
torch.ones(input.size(), dtype=input.dtype, layout=input.layout, device=input.device)
torch.rand()
返回一个张量,包含了从区间(0, 1)的
torch.rand(*sizes, out=None)
torch.randn()
返回一个张量,包含了从
torch.randn(*sizes, out=None)
torch.randperm()
给定参数n
,返回一个从0到n-1
的
- n (int) - 上边界(
不包含 )
torch.randperm(n, out=None)
官方例子:
>>> torch.randperm(4)
tensor([2, 1, 0, 3])
torch.arange()
返回一个1维张量,长度为floor((end-start)/step)
,以step
为步长的一组序列值。
- start (float) - 起点
- end (float) - 终点
- step (float) - 相邻点的间隔大小
- out (Tensor, optional)
注意:不包含end。
torch.arange(start, end, step=1, out=None)
例子:
>>> torch.arange(5)
tensor([ 0, 1, 2, 3, 4])
torch.range()
和torch.arange()
大致一样。但是torch.range()
的结果包含end。
torch.range(start, end, step=1, out=None)
PS:推荐使用torch.arange()
,因为torch.arange()
兼容更多种类的参数。
torch.zeros()
返回一个全为标量0的张量,形状由可变参数sizes定义。
torch.zeros(*sizes, out=None)
torch.zeros_like()
根据torch.ones_like()
类似。
torch.empty()
用来返回一个没有初始化的tensor。
>>> torch.empty(2,3)
tensor([[1.1692e-19, 1.5637e-01, 5.0783e+31],
[4.2964e+24, 2.6908e+20, 2.7490e+20]])
torch.empty_like()
创建一个与input形状一样的使用未初始化的tensor。与torch.ones_like()
类似。相当于:
torch.empty(input.size(), dtype=input.dtype, layout=input.layout, device=input.device)
torch.as_strided()
此方法根据现有tensor以及给定的步长来创建一个
torch.as_strided(input, size, stride, storage_offset=0)—>Tensor
视图是指创建一个方便查看的东西,
>>> torch.manual_seed(0) # 设定随机种子
>>> a = torch.rand(4, 4)
>>> b = torch.as_strided(a, (3, 3), (1, 1))
>>> a
tensor([[0.4963, 0.7682, 0.0885, 0.1320],
[0.3074, 0.6341, 0.4901, 0.8964],
[0.4556, 0.6323, 0.3489, 0.4017],
[0.0223, 0.1689, 0.2939, 0.5185]])
>>> b
tensor([[0.4963, 0.7682, 0.0885],
[0.7682, 0.0885, 0.1320],
[0.0885, 0.1320, 0.3074]])
这样创建出来的b
就是a
的一个视图,可以发现,b
中的元素都是a
中的元素,**b**
**a**
a
中的数据的话,b
中的数据也会改变,反之亦然。
torch.as_strided()
参数:
input
:此参数指定了在哪个数据上创建视图,input
需为tensor。size
:指定了生成的视图的大小,需要为一个矩阵(当然此矩阵大小可以大于原矩阵,但是也有限制),可以是tensor或者list等等。stride
:输出tensor的步长,根据原矩阵和步长生成了新矩阵。storage_offset
:输出张量的基础存储中的偏移量。
继续使用上面的例子,将步长改为(0, 0)
:
>>> a
tensor([[0.4963, 0.7682, 0.0885, 0.1320],
[0.3074, 0.6341, 0.4901, 0.8964],
[0.4556, 0.6323, 0.3489, 0.4017],
[0.0223, 0.1689, 0.2939, 0.5185]])
>>> b = torch.as_strided(a, (3, 3), (0, 0))
>>> b
tensor([[0.4963, 0.4963, 0.4963],
[0.4963, 0.4963, 0.4963],
[0.4963, 0.4963, 0.4963]])
可以看到在没有偏移的情况下,b
的数据都是a
中的第一个数据,说明了(0, 0)
不进行偏移,这很好理解。现在将(0, 0)
改为(0, 1)
:
>>> a
tensor([[0.4963, 0.7682, 0.0885, 0.1320],
[0.3074, 0.6341, 0.4901, 0.8964],
[0.4556, 0.6323, 0.3489, 0.4017],
[0.0223, 0.1689, 0.2939, 0.5185]])
>>> b = torch.as_strided(a, (3, 3), (0, 1))
>>> b
tensor([[0.4963, 0.7682, 0.0885],
[0.4963, 0.7682, 0.0885],
[0.4963, 0.7682, 0.0885]])
第一行与第二行的元素相等,而每列的元素不同,并且在tensor上从0,1,2开始一次增加一个,这说明(1, 0)
得到如下结果:
>>> a
tensor([[0.4963, 0.7682, 0.0885, 0.1320],
[0.3074, 0.6341, 0.4901, 0.8964],
[0.4556, 0.6323, 0.3489, 0.4017],
[0.0223, 0.1689, 0.2939, 0.5185]])
>>> b = torch.as_strided(a, (3, 3), (1, 0))
>>> b
tensor([[0.4963, 0.4963, 0.4963],
[0.7682, 0.7682, 0.7682],
[0.0885, 0.0885, 0.0885]])
这次是每列元素相等,而行不等,说明(1, 1)
:
>>> a
tensor([[0.4963, 0.7682, 0.0885, 0.1320],
[0.3074, 0.6341, 0.4901, 0.8964],
[0.4556, 0.6323, 0.3489, 0.4017],
[0.0223, 0.1689, 0.2939, 0.5185]])
>>> b = torch.as_strided(a, (3, 3), (1, 1))
>>> b
tensor([[0.4963, 0.7682, 0.0885]