Tensor是Pytorch中最基本的一种数据抽象,它类似于C或numpy中的数组,可以有多个维度。张量也可以在GPU上使用以提高性能。
- 常用的创建张量的方法有:
- torch.empty():创建未初始化的张量。
>>> a = torch.empty(2,3)
>>> a
tensor([[1.0286e-38, 9.0919e-39, 8.9082e-39],
[9.2755e-39, 8.4490e-39, 9.6429e-39]])
>>> b = torch.empty(2,3)
>>> b
tensor([[1.0286e-38, 9.0919e-39, 8.9082e-39],
[9.2755e-39, 8.4490e-39, 9.6429e-39]])
>>> a[0][0] = 55. # 可以给元素赋值
>>> a
tensor([[5.5000e 01, 9.0919e-39, 8.9082e-39],
[9.2755e-39, 8.4490e-39, 9.6429e-39]])
>>> a[1] = 22. # 可以按某个维度统一赋值
>>> a
tensor([[5.5000e 01, 9.0919e-39, 8.9082e-39],
[2.2000e 01, 2.2000e 01, 2.2000e 01]])
>>> a[:,1] = 44. # 可以按某个维度统一赋值
>>> a
tensor([[5.5000e 01, 4.4000e 01, 8.9082e-39],
[2.2000e 01, 4.4000e 01, 2.2000e 01]])
- torch.zeros():创建元素值全为零的张量。
>>> a = torch.zeros((2,3,4))
>>> a
tensor([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
- torch.ones():创建元素值全为1的张量。
>>> b = torch.ones((3,4))
>>> b
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
>>> a = torch.empty((2,3))
>>> a
tensor([[-3.9696e-19, 4.5914e-41, -3.9696e-19],
[ 4.5914e-41, -3.9696e-19, 4.5914e-41]])
# out参数可以指定生成的tensor输出给其它变量
# empty(), ones(), zeros()等都有out参数
>>> torch.ones((2,3), out=a)
tensor([[1., 1., 1.],
[1., 1., 1.]])
>>> a
tensor([[1., 1., 1.],
[1., 1., 1.]])
- 线性填充创建张量
>>> torch.arange(1., 5.) # 和numpy中的用法基本一致
tensor([1., 2., 3., 4.])
>>> torch.arange(1., 10., 2)
tensor([1., 3., 5., 7., 9.])
>>> torch.linspace(0,1,11) # 和numpy中的用法基本一致
tensor([0.0000, 0.1000, 0.2000, 0.3000, 0.4000, 0.5000, 0.6000, 0.7000, 0.8000, 0.9000, 1.0000])
- 创建随机张量。深度学习中常用于初始化权重张量w。
>>> a = torch.rand(2,3) # [0, 1) 均匀分布
>>> a
tensor([[0.4202, 0.3845, 0.9435],
[0.8606, 0.9898, 0.7223]])
>>> b = torch.rand(2,3)
>>> b
tensor([[0.5876, 0.8672, 0.1454],
[0.8283, 0.6713, 0.1481]]
>>> torch.randn((2,6)) #标准正态分布(mean为0,std为1的normal分布)
tensor([[-0.6857, -0.5643, 1.1925, 1.9629, 0.7755, -0.0425],
[ 0.0553, 0.3286, 1.7301, -0.7192, 0.9045, -1.5953]])
>>>torch.randint(-1, 10, (1,20)) # low=-1, high=10 整数均匀分布
tensor([[4, 3, 3, 3, 6, 4, 4, 3, 1, 0, 1, 2, 1, 8, 3, 8, 8, 8, 1, 6]])
可以手动设置随机种子
代码语言:javascript复制>>> torch.manual_seed(317)
<torch._C.Generator object at 0x000001935EE0FE28>
>>> a = torch.rand(2,3)
>>> torch.manual_seed(317)
<torch._C.Generator object at 0x000001935EE0FE28>
>>> b = torch.rand(2,3)
>>> a
tensor([[0.9137, 0.1671, 0.9334],
[0.3699, 0.6616, 0.1785]])
>>> b
tensor([[0.9137, 0.1671, 0.9334],
[0.3699, 0.6616, 0.1785]])
>>> a == b
tensor([[True, True, True],
[True, True, True]])
- torch.eye() 创建单位矩阵式的二维张量,主对角线元素全为1,其它元素全为0。
>>> torch.eye(4)
tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
- torch.xxxx_like()根据其它张量的形状创建张量。
>>> a = torch.ones((3,2)) # shape参数也可以传入tuple或list
>>> a
tensor([[1., 1.],
[1., 1.],
[1., 1.]])
>>> torch.empty_like(a)
tensor([[1., 1.],
[1., 1.],
[1., 1.]])
>>> torch.zeros_like(a)
tensor([[0., 0.],
[0., 0.],
[0., 0.]])
>>> torch.ones_like(a)
tensor([[1., 1.],
[1., 1.],
[1., 1.]])
- pytorch.tensor() 给定元素手动创建张量
>>> torch.tensor(1) # 零维张量(标量)
tensor(1)
>>> torch.tensor((1,2)) # 1维张量
tensor([1, 2])
>>> torch.tensor([[1,2],[3,4]]) # 2维张量
tensor([[1, 2],
[3, 4]])
>>> torch.tensor(((1,2),[3,4])) # 2维张量, tuple 和 list 可以混用
tensor([[1, 2],
[3, 4]])
- tensor 的数据类型,常见的数据类型有 torch.bool torch.int8 torch.uint8 torch.int16 torch.int32 torch.int64 torch.half torch.float torch.double torch.bfloat
# 可以在创建时通过dtype参数指定数据类型
a = torch.ones((2, 3), dtype=torch.int16)
print(a)
b = torch.rand((2, 3), dtype=torch.float64) * 20.
print(b)
# 也可以转换
c = b.to(torch.int32)
- tensor 的 维度信息(size)
>>> x = torch.ones((1,2,3))
>>> x
tensor([[[1., 1., 1.],
[1., 1., 1.]]])
>>> x.shape
torch.Size([1, 2, 3])
>>> x.size()
torch.Size([1, 2, 3])
>>> x.shape == x.size()
True
>>> x.shape is x.size()
False
代码语言:javascript复制>>> x.shape[0]
1
>>> x.shape[1]
2
代码语言:javascript复制>>> x = torch.tensor(5.)
>>> x
tensor(5.)
>>> x.shape
torch.Size([]) # 零维度张量的shape
- tensor 的 reshape。同numpy一样,可以改变tensor的shape,新的tensor只是是原来tensor的视图,二者共享存储空间。
>>> a = torch.rand((3,4))
>>> b = a.reshape((4,3))
>>> b[0,0]=22.22
>>> a
tensor([[22.2200, 0.9620, 0.7581, 0.1273],
[ 0.5137, 0.9653, 0.1091, 0.3371],
[ 0.0306, 0.7359, 0.7835, 0.9451]])
# 也可以用view()
>>> c = a.view(2,-1) # 同numpy一样,最后一个维度可以设为-1,自动分配。
>>> c
tensor([[22.2200, 0.9620, 0.7581, 0.1273, 0.5137, 0.9653],
[ 0.1091, 0.3371, 0.0306, 0.7359, 0.7835, 0.9451]])
>>> c[0,1]=33.33
>>> a
tensor([[2.2220e 01, 3.3330e 01, 7.5810e-01, 1.2730e-01],
[5.1369e-01, 9.6526e-01, 1.0907e-01, 3.3712e-01],
[3.0613e-02, 7.3591e-01, 7.8346e-01, 9.4511e-01]])
零维tensor转为python数值
- tensor的切片操作,同numpy一样。
>>> x
tensor([[8, 4, 4, 0, 3],
[5, 4, 9, 3, 2],
[4, 6, 0, 2, 2],
[3, 8, 3, 9, 9],
[3, 6, 7, 9, 3]])
>>> x[1:3,2:-1]
tensor([[9, 3],
[0, 2]])
- tensors的拼接
>>> a = torch.randn(3,2)
>>> b = torch.randn(3,1)
>>> torch.cat((a,b),dim=1)
tensor([[-0.4081, -0.1116, 0.3356],
[-0.6456, 0.0837, 0.4141],
[ 0.7786, 1.0901, -0.6719]])
tensor 与 numpy数组 互相转化
代码语言:javascript复制>>> t2 = torch.from_numpy(n)
>>> t2
tensor([99., 1., 1., 1., 1.])
>>> n[2]=22.22
>>> n
array([99. , 1. , 22.22, 1. , 1. ], dtype=float32)
>>> t2 # tensor 和 array 共享存储空间
tensor([99.0000, 1.0000, 22.2200, 1.0000, 1.0000])
tensor的数学运算。
- size相同的tensors之间可以进行数学运算。除非可以进行broadcast,不同size的tensors之间不可以进行数学计算。
>>> a = torch.rand((2,3))
>>> a
tensor([[0.7301, 0.3747, 0.4656],
[0.9889, 0.8834, 0.7723]])
>>> b = torch.ones_like(a)
>>> b
tensor([[1., 1., 1.],
[1., 1., 1.]])
>>> a b
tensor([[1.7301, 1.3747, 1.4656],
[1.9889, 1.8834, 1.7723]])
>>> a*b # 等价于 torch.mul(a,b)
tensor([[0.7301, 0.3747, 0.4656],
[0.9889, 0.8834, 0.7723]])
>>> a *= b
>>> a
tensor([[0.7301, 0.3747, 0.4656],
[0.9889, 0.8834, 0.7723]])
>>> a -= b
>>> a
tensor([[-0.2699, -0.6253, -0.5344],
[-0.0111, -0.1166, -0.2277]])
- 和numpy一样,torch也自带许多数学函数,如
>>> torch.sin(a)
tensor([[-0.2667, -0.5853, -0.5093],
[-0.0111, -0.1163, -0.2257]])
>>> torch.cos(a)
tensor([[0.9638, 0.8108, 0.8606],
[0.9999, 0.9932, 0.9742]])
>>> torch.asin(a)
tensor([[-0.2733, -0.6755, -0.5637],
[-0.0111, -0.1168, -0.2297]])
>>> torch.sinh(a)
tensor([[-0.2732, -0.6669, -0.5601],
[-0.0111, -0.1168, -0.2297]])
>>> torch.max(a)
tensor(-0.0111)
>>> a.mean()
tensor(-0.2975)
>>> a.mean(dim=1) # 可以指定维度
tensor([-0.4765, -0.1185])
>>> b
tensor([[3., 3., 3.],
[3., 3., 3.]])
>>> torch.std_mean(b) # 计算b标准差和mean
(tensor(0.), tensor(3.))
>>> torch.svd(b) # SVD 分解
torch.return_types.svd(
U=tensor([[-0.7071, 0.7071],
[-0.7071, -0.7071]]),
S=tensor([7.3485e 00, 4.0850e-07]),
V=tensor([[-0.5774, -0.8165],
[-0.5774, 0.4082],
[-0.5774, 0.4082]]))
>>> a = torch.randn(4,4)
>>> torch.det(a) # 计算方阵的行列式
tensor(0.6460)
# 等等等等
- 矩阵乘法,torch.matmul()
>>> a = torch.randn(3,2)
>>> b=torch.randn(2,5)
>>> torch.matmul(a,b)
tensor([[-3.4743, -0.5266, 0.3270, -2.7448, -0.7288],
[-5.9377, -1.4233, 0.9677, -2.2013, -3.4487],
[-2.5309, -0.8615, 0.6115, 0.2738, -2.5426]])
- tensor 的广播(broadcast),与 numpy 的广播类似
a
tensor([[1., 1., 1.],
[1., 1., 1.]])
b = a 2
b
tensor([[3., 3., 3.],
[3., 3., 3.]])
b**2
tensor([[9., 9., 9.],
[9., 9., 9.]])
(torch.rand(2, 2) - 0.5) * 2
tensor([[-0.1330, -0.1400],
[-0.9692, -0.5754]])
- 不同shape的tensors之间广播的规则如下:
- 不能有空的tensor
- 从后往前比较两个tensors的维度(从右往左对齐观察), 每个维度的大小都相等,或者 其中一个维度的大小必须是1,或者 其中一个tensor的某个维度缺失。
a = torch.ones(4, 3, 2)
b = a * torch.rand( 3, 2) # 3rd & 2nd dims identical to a, dim 1 absent
print(b)
c = a * torch.rand( 3, 1) # 3rd dim = 1, 2nd dim identical to a
print(c)
d = a * torch.rand( 1, 2) # 3rd dim identical to a, 2nd dim = 1
print(d)
- tensor 可以转到 GPU 上进行计算
b = a.to("cuda")
b
tensor([[ 1.2982, -0.1432, -0.9152, 0.8028],
[-0.3701, 0.2217, 0.7523, 0.7443],
[-0.1457, 0.7082, -1.1346, 0.8564],
[-0.2956, 0.1779, 0.9134, -0.0069]], device='cuda:0')
b**2
tensor([[1.6853e 00, 2.0511e-02, 8.3754e-01, 6.4442e-01],
[1.3698e-01, 4.9144e-02, 5.6598e-01, 5.5392e-01],
[2.1235e-02, 5.0161e-01, 1.2873e 00, 7.3339e-01],
[8.7371e-02, 3.1664e-02, 8.3422e-01, 4.8006e-05]], device='cuda:0')
GPU上的 tensor 可以转回CPU.
代码语言:javascript复制c = b.to("cpu")
c
tensor([[ 1.2982, -0.1432, -0.9152, 0.8028],
[-0.3701, 0.2217, 0.7523, 0.7443],
[-0.1457, 0.7082, -1.1346, 0.8564],
[-0.2956, 0.1779, 0.9134, -0.0069]])
c.device
device(type='cpu')
不同设备上的tensors 之间不能进行计算。
代码语言:javascript复制a b
Traceback (most recent call last):
File "E:Python36libcode.py", line 91, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!