张量(tensor)作为深度学习网络中用来存储网络层数据的主要数据类型,能够最大程度的使用GPU资源进行矩阵运算。可以将tensor认为是我们熟悉的numpy
库中的ndarrays
类型,它们在运算和矩阵创建上也有很多相似之处,所不同的是tensor是专门针对GPU进行优化的矩阵,其可以充分利用GPU进行加速运算。
Pytorch中tensor类型:class torch.Tensor
;
官方参考文档:https://pytorch.org/docs/1.4.0/tensors.html
本博客所有代码都可以在我的Github上下载测试。
1、创建指定尺寸的tensor
import torch
a=torch.Tensor(2,3)
print(a, a.shape)
结果:
tensor([[-2.6068e-11, 4.5785e-41, 2.5850e-37],
[ 0.0000e+00, 0.0000e+00, 0.0000e+00]]) torch.Size([2, 3])
2、创建随机张量
指定张量尺寸,可以用元组指定,也可以直接指定
pred = torch.randn((4, 5))
input = torch.rand(8, 1024, 3)
3、创建指定元素的张量
可以通过list、tuple或numpy矩阵来创建指定元素的张量
通过Tensor
类创建:
x = torch.Tensor([[1], [2], [3]])
print(x, x.shape)
结果:
tensor([[1.],
[2.],
[3.]]) torch.Size([3, 1])
通过torch.tensor()
函数创建:
x = torch.tensor([1, 2, 3])
x = torch.tensor(3.14159) # Create a scalar (zero-dimensional tensor) tensor(3.1416)
x = torch.tensor([]) # Create an empty tensor (of size (0,))
几点注意:
1、可以通过dtype=double
等类型来指定tensor中每个元素的数值类型,如果不指定,默认是float32
类型;
2、torch.tensor()
总是会复制数据,即用来创建用的数据和创建后的张量数据不共享,要想不复制数据,可以参考torch.as_tensor
;
x = torch.tensor([[1], [2], [3]], dtype=torch.double)
print(x, x.shape, x.dtype)
x = x.long()
print(x, x.dtype)
正是由于张量与numpy中矩阵有很多相似之处,因此Pytorch中也提供了两者之间的各种转换方法。
1、从numpy矩阵转换为tensor
## 方法1
a = np.ones(5)
b = torch.from_numpy(a).clone()
np.add(a, 1, out=a)
print(a)
print(b)
结果:
[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
注意这种转换是共享内存的,修改任一元素都会影响转换前后的矩阵,如果想要避免影响,可以加上复制操作:
a = np.ones(5)
b = torch.from_numpy(a).clone()
2、从tensor转换为numpy矩阵
a = torch.ones(5)
print(a, type(a))
b = a.numpy()
print(b, type(b))
结果:
tensor([1., 1., 1., 1., 1.]) <class 'torch.Tensor'>
[1. 1. 1. 1. 1.] <class 'numpy.ndarray'>
同样地,这种转换也是共享内存的,修改任一元素都会影响转换前后的矩阵,如果想要避免影响,可以加上复制操作:
a = torch.ones(5)
b = a.numpy().copy()
Pytorch中提供了多种语法来对张量进行运算,此处以加法运算为例,演示几种常用语法:
def operate_tensor():
print("===============operate_tensor=================")
x = torch.randn(5, 3)
print(x)
y = torch.randn(5, 3)
print(y)
## 语法1,直接用+运算符
print(x + y)
## 语法2, 调用torch.*函数
print(torch.add(x, y))
## 语法3, 提供一个输出张量作为参数
result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(result)
## 语法4, in-place运算,即运算结果直接修改张量,带有_下划线结尾的函数都是in-place运算
y.add_(x) # adds x to y
print(y)
获取张量的尺寸,类似numpy中的shape用法
返回类型是torch.Size
,;
除了shape
成员变量,也可以使用size()
成员函数同样获取张量的尺寸;
torch.Size
其实是一个tuple
类型,可以使用元组的所有操作。
只写常用的,其他的可以去官方参考文档网站查阅。
torch.cat
函数:
用来深度复制张量矩阵元素。
如非必须,尽量不要对张量元素进行深度复制,因为张量的元素一般比较多,复制元素会消耗一定的时间;
维度扩展函数:
x = torch.Tensor([[[1, 2, 3]]])
print(x, x.shape)
x = x.expand(2, 2, 3)
print(x, x.shape)
对维度为1的元素进行复制扩展,一般会用在unsqueeze增加了一个维度之后对该维度进行扩展。
https://blog.csdn.net/edogawachia/article/details/80515038
对输入张量求范数。
类似numpy的transpose函数,
https://blog.csdn.net/ZT0518/article/details/86440338
https://blog.csdn.net/qian1996/article/details/81265974
squeeze()用来降低张量的维度,去掉指定维度上数量为1的维度;
unsqueeze()用来增加张量维度
按指定维度求和,会发生维度缩减;
如果没有指定维度,则默认是将所有元素求和
文档
import torch
x = torch.randn(4, 5)
print(x)
print(x.sum(0)) #按列求和,维度变为(1,5)
print(x.sum(1)) #按行求和
print(torch.sum(x)) #所有元素求和
print(torch.sum(x, 0))#按列求和
print(torch.sum(x, 1))#按行求和
运行结果:
tensor([[ 0.2210, 1.8035, 0.7671, -0.1836, -0.2794],
[-0.7922, -1.0881, -2.0180, 1.0981, 0.2320],
[-0.4681, 0.1820, 0.0502, 0.0067, 1.3218],
[ 0.4785, 1.0799, 1.6197, 0.6642, 0.6915]])
tensor([-0.5608, 1.9773, 0.4190, 1.5854, 1.9660])
tensor([ 2.3287, -2.5682, 1.0926, 4.5338])
tensor(5.3868)
tensor([-0.5608, 1.9773, 0.4190, 1.5854, 1.9660])
tensor([ 2.3287, -2.5682, 1.0926, 4.5338])
维度置换
类似numpy的reshape函数,用来调整张量矩阵的尺寸:
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) # the size -1 is inferred from other dimensions
print(x.size(), y.size(), z.size())
x[0, :] = torch.tensor([1, 2, 3, 4]) # 修改x张量,会同时影响y和z
print(x)
print(y)
print(z)
结果:
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
tensor([[ 1.0000, 2.0000, 3.0000, 4.0000],
[ 0.4023, -1.4241, -0.9553, 0.1555],
[ 0.1595, -0.3018, -0.6200, 0.8011],
[-0.7002, 0.8418, 0.0914, -0.5116]])
tensor([ 1.0000, 2.0000, 3.0000, 4.0000, 0.4023, -1.4241, -0.9553, 0.1555,
0.1595, -0.3018, -0.6200, 0.8011, -0.7002, 0.8418, 0.0914, -0.5116])
tensor([[ 1.0000, 2.0000, 3.0000, 4.0000, 0.4023, -1.4241, -0.9553, 0.1555],
[ 0.1595, -0.3018, -0.6200, 0.8011, -0.7002, 0.8418, 0.0914, -0.5116]])
注:view
函数只是调整了观察矩阵的尺寸,并没有改变数据,使用的都是同一份内存的数据,因此上述例子中的x,y,z
其实都是使用的数据,修改任一张量都会影响其他张量结果。