1 张量
# 1 张量
pytorch的数据类型,类似pandas里的Dateframe。是基于标量、向量和矩阵概率的延伸。
# 导包
import torch
import numpy as np
1
2
3
2
3
# 1.1 数据类型
# 1.1.1 创建张量
arr = np.array([[1,2,3],[4,5,6]])
x = torch.Tensor(arr) # # 将 NumPy 数组转换为一个 PyTorch 张量
print(x)
1
2
3
4
2
3
4
tensor([[1., 2., 3.],
[4., 5., 6.]])
# 1.1.2 创建张量随机数方法
# torch.rand
服从[0,1)的均匀分布
tensor1 = torch.rand(3,4)
tensor1
1
2
2
tensor([[0.5067, 0.0992, 0.2738, 0.5640],
[0.8371, 0.4079, 0.1452, 0.8652],
[0.8629, 0.9054, 0.6144, 0.2549]])
# torch.randn()
服从均值0,方差1的标准正态分布
tensor1 = torch.randn(3,4)
tensor1
1
2
2
tensor([[-2.3690, -0.6055, -0.5592, -1.6116],
[ 0.4369, 0.2237, -0.7167, -0.1619],
[ 1.4463, 1.3810, -0.3767, -2.4971]])
# torch.normal(means, std, out=None)
- 指定均值方差
tensor1 = torch.normal(mean=torch.arange(1.,11.), std=torch.arange(0, 1, 0.1))
tensor1
1
2
2
tensor([ 1.0000, 1.8565, 3.0861, 3.9785, 4.5556, 5.7291, 8.1138, 7.8268,
8.4596, 10.6865])
- 共享均值方差
tensor1 = torch.normal(mean=10, std=torch.arange(0,1,0.1))
tensor1
tensor2 = torch.normal(1,2,size=(10,3))
tensor2
1
2
3
4
5
2
3
4
5
tensor([[ 0.1712, -1.1595, 0.5119],
[-1.4520, 3.6885, 0.8588],
[ 0.2594, 0.7861, 1.2009],
[ 0.8792, 0.4400, 3.5033],
[ 0.8518, -0.6514, 0.8435],
[-4.5127, 1.6560, 1.8358],
[ 1.0980, -0.0322, 4.6615],
[ 0.2322, -3.3426, 5.0285],
[-0.7733, -2.5316, 1.9540],
[ 0.6214, 1.1227, 3.3353]])
# torch.linspace(start,end,steps)
注意:steps是产生的数量,不是步长!!!
tensor1 = torch.linspace(1,10,steps=3)
tensor1
1
2
2
tensor([ 1.0000, 5.5000, 10.0000])
# torch.arange(start=0, end, step=1)
tensor1 = torch.arange(start=0, end=10, step=3)
tensor1
1
2
2
tensor([0, 3, 6, 9])
# torch.manual_seed()
固定随机种子,仅用于最接近的随机数产生语句。
torch.manual_seed(3)
num1 = torch.rand(2)
print(num1)
torch.manual_seed(3)
num2 = torch.rand(2)
print(num2)
1
2
3
4
5
6
7
2
3
4
5
6
7
tensor([0.0043, 0.1056])
tensor([0.0043, 0.1056])
# ones()
全1数组
# zeros()
全0数组
# eye()
对角线全1
tensor1 = torch.eye(4,3)
tensor1
1
2
3
2
3
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 0., 0.]])
# 1.1.3 数据类型的转换
- 创建时指定
tensor1 = torch.ones((3,1,6), dtype=torch.int64)
tensor1
1
2
2
tensor([[[1, 1, 1, 1, 1, 1]],
[[1, 1, 1, 1, 1, 1]],
[[1, 1, 1, 1, 1, 1]]])
- 创建完再指定
tensor1 = torch.ones((3,1,6))
tensor1.type(torch.float64)
tensor1
1
2
3
2
3
tensor([[[1., 1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1., 1.]]])
# 1.2 基本操作
# 1.2.1 改变形状 view
x = torch.rand(3,2)
print(x)
y = x.view(2,3)
print(y)
1
2
3
4
5
2
3
4
5
tensor([[0.6483, 0.2148],
[0.9493, 0.0121],
[0.1809, 0.1877]])
tensor([[0.6483, 0.2148, 0.9493],
[0.0121, 0.1809, 0.1877]])
# 1.2.2 增加删除维度
- 增加维度 unsqueeze
它是按索引位添加维度,比如0即是在第0位添加一个维度。
a = torch.rand(3,4)
b = torch.unsqueeze(a,0)
c = b.unsqueeze(0)
print(a.shape)
print(b.shape)
print(c.shape)
1
2
3
4
5
6
2
3
4
5
6
torch.Size([3, 4])
torch.Size([1, 3, 4])
torch.Size([1, 1, 3, 4])
删除维度 squeeze(input, dim)
只 在 tensor.shape[dim] == 1 时,才会删除那个维度。
a = torch.rand(1,2,3,4)
b = torch.squeeze(a,0)
c = b.squeeze()
print(a.shape)
print(b.shape)
print(c.shape)
1
2
3
4
5
6
2
3
4
5
6
torch.Size([1, 2, 3, 4])
torch.Size([2, 3, 4])
torch.Size([2, 3, 4])
- 拉平成一维
view(-1)
1
# 1.2.3 交换维度 permute
或者transpose()
tensor1 = torch.rand(2,3,2)
print(tensor1)
tensor2 = tensor1.permute(1,0,2)
print(tensor2)
1
2
3
4
5
2
3
4
5
tensor([[[0.8536, 0.0303],
[0.7106, 0.5128],
[0.9775, 0.8324]],
[[0.2388, 0.3827],
[0.8727, 0.2676],
[0.6810, 0.0939]]])
tensor([[[0.8536, 0.0303],
[0.2388, 0.3827]],
[[0.7106, 0.5128],
[0.8727, 0.2676]],
[[0.9775, 0.8324],
[0.6810, 0.0939]]])
# 1.2.4 拼接、分割
拼接
不会增加维度
a = torch.rand(1,2,1)
b = torch.rand(1,2,1)
c = torch.rand(1,2,1)
print(a)
res1 = torch.cat([a,b,c],dim = 0)
res2 = torch.cat([a,b,c],dim = 1)
print(f'res1:{res1}\n, res2:{res2}')
1
2
3
4
5
6
7
2
3
4
5
6
7
tensor([[[0.7706],
[0.6560]]])
res1:tensor([[[0.7706],
[0.6560]],
[[0.0419],
[0.5257]],
[[0.7046],
[0.1369]]])
, res2:tensor([[[0.7706],
[0.6560],
[0.0419],
[0.5257],
[0.7046],
[0.1369]]])
- 分割 split
分割是分成num块,按dim=0
tensor1 = torch.rand(3,4)
res1 = torch.split(tensor1, 2)
print(tensor1)
print(res1)
1
2
3
4
5
6
2
3
4
5
6
tensor([[0.8660, 0.0405, 0.9147, 0.8523],
[0.9055, 0.3671, 0.6700, 0.6978],
[0.3117, 0.5756, 0.7466, 0.8590]])
(tensor([[0.8660, 0.0405, 0.9147, 0.8523],
[0.9055, 0.3671, 0.6700, 0.6978]]), tensor([[0.3117, 0.5756, 0.7466, 0.8590]]))
# 1.2.5 堆叠和分解
堆叠 stack()
会增加维度
a = torch.rand(1,2)
b = torch.rand(1,2)
c = torch.rand(1,2)
res1 = torch.stack([a,b,c], dim=0)
1
2
3
4
5
2
3
4
5
tensor([[[0.9387, 0.2398]],
[[0.4198, 0.6112]],
[[0.5861, 0.3208]]])
- 分解 chunk()
a = torch.rand(3,4)
res1 = torch.chunk(a, 2, dim=0)
res1
1
2
3
2
3
(tensor([[0.6000, 0.4391, 0.8994, 0.0217],
[0.6418, 0.5846, 0.6675, 0.0933]]),
tensor([[0.3516, 0.1336, 0.7224, 0.6623]]))
# 1.2.6 索引和切片
a = torch.rand(2,3,4)
x = a[:,:2,:]
print(x.shape)
1
2
3
4
2
3
4
torch.Size([2, 2, 4])
# 1.2.7 基本数学运算
# 求和 sum
- 所有元素加起来
a = torch.rand(2,3)
res = torch.sum(a)
res
1
2
3
2
3
tensor(3.6691)
指定维度 torch.sum(input,dim,keepdim=True)
keepdim:保证维度不变
a = torch.rand(2,3)
print(a)
res = torch.sum(a,dim=1,keepdim=True)
print(res)
1
2
3
4
2
3
4
tensor([[0.6204, 0.4698, 0.9045],
[0.9678, 0.6092, 0.5209]])
tensor([[1.9946],
[2.0979]])
按索引求和
torch.Tensor.index_add(dim,index,tensor)
arr1 = torch.Tensor([[1,2],[3,4]])
arr2 = torch.Tensor([[0,1],[2,3]])
index = torch.LongTensor([0,1])
res = arr1.index_add(0,index,arr2)
print(res)
1
2
3
4
5
6
7
2
3
4
5
6
7
tensor([[1., 3.],
[5., 7.]])
# 乘积 prod
torch.prod(input,dim,keepdim=True)()
# 平均数 mean
方法同求和
# 方差 var
方法同求和
# 最值 max、min
方法同求和
# 1.2.8 向量运算
# 点乘 dot
a = torch.Tensor([1,2,3])
b = torch.Tensor([1,1,1])
res = torch.dot(a,b)
print(res) # 等价于 1*1+2*1+3*1
1
2
3
4
5
2
3
4
5
tensor(6.)
# 叉乘 multiply
逐元素乘法
a = torch.Tensor([1,2,3])
b = torch.Tensor([1,1,1])
res = torch.multiply(a,b)
print(res) # 等价于 1*1 2*1 3*1
1
2
3
4
5
2
3
4
5
tensor([1., 2., 3.])
# 1.2.9 矩阵运算
# 内积 inner
对两个张量的“最后一维”做内积
a = torch.ones(2,2)
b = torch.Tensor([[2,3],[4,5]])
print(a)
print(b)
res = torch.inner(a,b)
print(res)
# res[i, j] 就是对 a[i, :] 和 b[j, :] 做内积
1
2
3
4
5
6
7
2
3
4
5
6
7
tensor([[1., 1.],
[1., 1.]])
tensor([[2., 3.],
[4., 5.]])
tensor([[5., 9.],
[5., 9.]])
# 外积 matmul
线代的矩阵乘积
a = torch.ones(2,2)
b = torch.Tensor([[2,3],[4,5]])
print(a)
print(b)
res = torch.matmul(a,b)
print(res)
# res[i, j] 就是对 a[i, :] 和 b[j, :] 做内积
1
2
3
4
5
6
7
2
3
4
5
6
7
tensor([[1., 1.],
[1., 1.]])
tensor([[2., 3.],
[4., 5.]])
tensor([[6., 8.],
[6., 8.]])
# 1.3 张量与Numpy
# 1.3.1 张量转Numpy
numpy() 二者会共享内存
tensor1 = torch.ones(3,3)
arr = tensor1.numpy()
print(arr)
1
2
3
4
2
3
4
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
# 1.3.2 Numpy转张量
torch.Tensor(arr)
会 复制 一份数据,创建新的张量,和原 NumPy 数组无关。
torch.from_numpy(arr)
不会复制,新建的张量和原 NumPy 数组 共享内存,修改其中一个,另一个也跟着变。
# 1.4 Cuda张量与CPU张量
- 转为CPU
tensor1 = torch.rand(2,3)
tensor = tensor1.cpu() # 默认是cpu,如果是Cuda可以转
print(tensor.device)
1
2
3
4
2
3
4
cpu
- 转为Cuda
方法1:
tensor1 = torch.rand(2,3)
tensor = tensor1.cuda()
print(tensor.device)
1
2
3
4
2
3
4
cuda:0
方法2:
x = torch.rand(3,3)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
if torch.cuda.is_available():
x = x.to(device)
print(device)
1
2
3
4
5
2
3
4
5
cuda