1
2
#二话不说,先把包导入进来~
import torch

tensor初始化

1
2
3
#定义一个tensor
my_tensor=torch.tensor([[1,2,3],[4,5,6]])
print(my_tensor)
tensor([[1, 2, 3],
        [4, 5, 6]])
1
2
3
#指定tensor的数据类型
my_tensor=torch.tensor([[1,2,3],[4,5,6]],dtype=torch.float32)
print(my_tensor)
tensor([[1., 2., 3.],
        [4., 5., 6.]])
1
2
3
#指定device
my_tensor=torch.tensor([[1,2,3],[4,5,6]],dtype=torch.float32,device='cuda')
print(my_tensor)
tensor([[1., 2., 3.],
        [4., 5., 6.]], device='cuda:0')
1
2
3
#如果有gpu则使用gpu,此时device='cuda',否则使用cpu
device="cuda" if torch.cuda.is_available() else "cpu"
print(device)
cuda
1
2
3
4
#requires_grad:是否可被求导
#一般来说,神经网络学习的权重是可导的(requires_grad=True)
my_tensor=torch.tensor([[1,2,3],[4,5,6]],dtype=torch.float32,device='cuda',requires_grad=True)
print(my_tensor)
tensor([[1., 2., 3.],
        [4., 5., 6.]], device='cuda:0', requires_grad=True)
1
2
3
4
print(my_tensor.device)
print(my_tensor.requires_grad)
print(my_tensor.dtype)
print(my_tensor.shape)
cuda:0
True
torch.float32
torch.Size([2, 3])
1
2
x=torch.empty(size=(3,3))
print(x)
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
1
2
3
#全0张量
x=torch.zeros((3,3))
print(x)
1
2
3
#全1张良
x=torch.ones((3,3))
print(x)
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
1
2
3
#元素为随机数的张量
x=torch.rand((3,3))
print(x)
tensor([[0.4704, 0.6278, 0.2294],
        [0.1838, 0.4951, 0.8452],
        [0.7331, 0.8264, 0.9475]])
1
2
3
#从0到9之间随机采样整数组成张量的元素
x=torch.randint(10, (2, 2))#等价于torch.randint(0,10, (2, 2))
print(x)
tensor([[7, 8],
        [9, 3]])
1
2
3
#从标准正态分布中采样随机数
x = torch.randn(2, 3)
print(x)
tensor([[ 0.7711, -1.2354, -0.6476],
        [ 1.2426, -0.8406, -1.1450]])
1
2
3
#单位阵
x=torch.eye(5,5)
print(x)
tensor([[1., 0., 0., 0., 0.],
        [0., 1., 0., 0., 0.],
        [0., 0., 1., 0., 0.],
        [0., 0., 0., 1., 0.],
        [0., 0., 0., 0., 1.]])
1
2
3
#整数序列
x=torch.arange(start=0,end=5,step=1)
print(x)
tensor([0, 1, 2, 3, 4])
1
2
3
#将从start到end之间的steps个数字作为张量x的元素
x=torch.linspace(start=0.1,end=1,steps=10)
print(x)
tensor([0.1000, 0.2000, 0.3000, 0.4000, 0.5000, 0.6000, 0.7000, 0.8000, 0.9000,
        1.0000])
1
2
3
#从标准正态分布中随机采样
x=torch.empty(size=(1,5)).normal_(mean=0,std=1)
print(x)
tensor([[ 0.3601, -1.2583, -0.1399,  0.9521,  1.1094]])
1
2
3
#从均匀分布中随机采样
x=torch.empty(size=(1,5)).uniform_(0,1)
print(x)
tensor([[0.7726, 0.3465, 0.3890, 0.4156, 0.4586]])
1
2
3
4
5
6
7
#输入是一个向量,返回一个以输入向量为对角线元素的对角阵
x=torch.diag(torch.ones(3))
print(x)

#或者输入一个矩阵,返回一个向量
xx=torch.diag(torch.ones(3,6))
print(xx)
tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])
tensor([1., 1., 1.])

tensor数据类型转换

1
2
3
4
5
6
7
8
9
10
11
#tensor数据类型转换
tensor=torch.arange(4)
print('tensor:',tensor)
print('tensor.bool:',tensor.bool())
print('tensor.short():',tensor.short())
print('tensor.long():',tensor.long())
print('tensor.long().dtype:',tensor.long().dtype)
print('tensor.half():',tensor.half())
print('tensor.float():',tensor.float())
print('tensor.float().dtype:',tensor.float().dtype)
print('tensor.double():',tensor.double())
tensor: tensor([0, 1, 2, 3])
tensor.bool: tensor([False,  True,  True,  True])
tensor.short(): tensor([0, 1, 2, 3], dtype=torch.int16)
tensor.long(): tensor([0, 1, 2, 3])
tensor.long().dtype: torch.int64
tensor.half(): tensor([0., 1., 2., 3.], dtype=torch.float16)
tensor.float(): tensor([0., 1., 2., 3.])
tensor.float().dtype: torch.float32
tensor.double(): tensor([0., 1., 2., 3.], dtype=torch.float64)

tensor与np array 互转

1
2
import numpy as np
np_array=np.zeros((5,5))
1
2
3
#从np.array转tensor
tensor=torch.from_numpy(np_array)
print(tensor)
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., 0.]], dtype=torch.float64)
1
2
3
#tensor转np.array
np_array_back=tensor.numpy()
print(np_array_back)
[[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]

tensor的数学运算

1
2
x=torch.tensor([1,2,3])
y=torch.tensor([9,8,7])
1
2
3
4
5
6
7
8
9
10
11
12
z1=torch.empty(3)
#tensor加法
z1=torch.add(x,y,out=z1)
print(z1)

#也可以这样做加法
z2=torch.add(x,y)
print(z2)

#更常用的加法操作是这个
z=x+y
print(z)
tensor([10., 10., 10.])
tensor([10, 10, 10])
tensor([10, 10, 10])
1
2
3
#tensor减法
z=x-y
print(z)
tensor([-8, -6, -4])
1
2
3
#逐点除法
z=torch.true_divide(x,y)
print(z)
tensor([0.1111, 0.2500, 0.4286])
1
2
3
4
5
#inplace operations
#直接在原位置修改(inplace:原地修改),无需开副本
t=torch.zeros(3)
t.add_(x)
print(t)
tensor([1., 2., 3.])
1
2
3
4
5
6
7
8
#高阶运算
x=torch.tensor([1,2,3])
z=x.pow(2)
print(z)

#也可以这样,和Python一样操作
z=x**2
print(z)
tensor([1, 4, 9])
tensor([1, 4, 9])
1
2
3
4
#比较
x=torch.tensor([1,0,3])
z=x>0
print(z)
tensor([ True, False,  True])
1
2
3
4
5
#矩阵乘法
x1=torch.rand((2,5))
x2=torch.rand((5,3))
x3=torch.mm(x1,x2) #shape:2*3,等价于x3=x1.mm(x2)
print(x3.shape)
torch.Size([2, 3])
1
2
3
4
5
6
7
#高阶矩阵操作
#matrix_exp=torch.rand((5,5))
matrix_exp=torch.tensor([[1,2],[3,4]],dtype=torch.float)
print(matrix_exp.matrix_power(3))

#上面等价于矩阵做3次自身乘法
torch.mm(matrix_exp,matrix_exp).mm(matrix_exp)
tensor([[ 37.,  54.],
        [ 81., 118.]])


tensor([[ 37.,  54.],
        [ 81., 118.]])
1
2
3
4
5
# 向量点乘(相当于把其中一个向量转置,然后两个向量做矩阵乘法)
x=torch.tensor([1,2,3])
y=torch.tensor([9,8,7])
z=torch.dot(x,y)
print(z)
tensor(46)
1
2
3
4
5
#点对点矩阵乘法
x=torch.tensor([1,2,3])
y=torch.tensor([9,8,7])
z=x*y
print(z)
tensor([ 9, 16, 21])
1
2
3
4
5
6
7
8
9
10
# 批量矩阵乘法
batch=32
n=10
m=20
p=30

tensor1=torch.rand((batch,n,m))
tensor2=torch.rand(batch,m,n)
out_bmm=torch.bmm(tensor1,tensor2)
print(out_bmm.shape)#(batch,n,n)
torch.Size([32, 10, 10])
1
2
3
4
5
6
7
8
9
10
11
#广播
x1=torch.tensor([[1,2,3],[4,5,6]])
x2=torch.tensor([2,3,1])

#自动复制x2作为新的一行

z=x1-x2
print(z)

zz=x1**x2
print(zz)
tensor([[-1, -1,  2],
        [ 2,  2,  5]])
tensor([[  1,   8,   3],
        [ 16, 125,   6]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#Other  useful tensor operations
x=torch.tensor([[5,2,3],[4,5,-1]])
y=torch.tensor([[5,2,3],[4,7,6]])

#按照dim0对tensor求和
su_x=torch.sum(x,dim=0)
print('su_x:',su_x)

#求tensor中最大值及其索引
values,indices=torch.max(x,dim=0)
print('values:{},indices:{}'.format(values,indices))

#求tensor的绝对值
abs_x=torch.abs(x)
print('abs_x:',abs_x)

#最大值索引
argmax=torch.argmax(x,dim=0)
print('argmax:',argmax)

#最小值索引
argmin=torch.argmin(x,dim=0)
print('argmin:',argmin)

#按照dim0求均值
mean_x=torch.mean(x.float(),dim=0)#必须是float
print('mean_x:',mean_x)

#比较两个tensor元素值是否相等,返回布尔值
eq=torch.eq(x,y)
print('eq:',eq)

#按dim0对y进行排序,在处理目标检测框时常用
print('sort:',torch.sort(y,dim=0,descending=False))

#超出[0,10]的全部改成0或10,小于0-->0,大于0-->10
print('x after clamp:',torch.clamp(x,min=0,max=10))
su_x: tensor([9, 7, 2])
values:tensor([5, 5, 3]),indices:tensor([0, 1, 0])
abs_x: tensor([[5, 2, 3],
        [4, 5, 1]])
argmax: tensor([0, 1, 0])
argmin: tensor([1, 0, 1])
mean_x: tensor([4.5000, 3.5000, 1.0000])
eq: tensor([[ True,  True,  True],
        [ True, False, False]])
sort: torch.return_types.sort(
values=tensor([[4, 2, 3],
        [5, 7, 6]]),
indices=tensor([[1, 0, 0],
        [0, 1, 1]]))
x after clamp: tensor([[5, 2, 3],
        [4, 5, 0]])
1
2
3
4
5
6
7
8
9
x=torch.tensor([1,0,1,1,1],dtype=torch.bool)

#x中只要有一个为True,z就是True
z=torch.any(x)
print(z)

#x中全部为True才返回True
zz=torch.all(x)
print(zz)
tensor(True)
tensor(False)

tensor索引

1
2
3
batch_size=10
features=25
x=torch.rand((batch_size,features))
1
2
print(x.shape)
print(x[0].shape)
torch.Size([10, 25])
torch.Size([25])
1
print(x[:,0].shape)
torch.Size([10])
1
print(x[2,0:10].shape)
torch.Size([10])
1
2
x[0,0]=10
print(x[0,0])
tensor(10.)
1
2
3
4
5
6
7
#fancy indexing
x=torch.arange(10)
print(x)

#取下标为2,5,8位置处的元素
indices=[2,5,8]
print(x[indices])
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
tensor([2, 5, 8])
1
2
3
4
5
x=torch.tensor([[1,2,3,4],[5,6,7,8],[9,8,7,6]])
rows=torch.tensor([1,0])
cols=torch.tensor([2,0])
#取(1,2),(0,0)索引对应元素,注意下标从0开始
print(x[rows,cols])
tensor([7, 1])
1
2
3
4
x=torch.arange(10)
print(x[(x<2)|(x>8)])
print(x[(x<2)&(x>8)])#没有满足这个条件的元素
print(x[x.remainder(2)==0])#取模2得0的元素
tensor([0, 1, 9])
tensor([], dtype=torch.int64)
tensor([0, 2, 4, 6, 8])
1
2
3
4
#uselful operations
x=torch.arange(10)
#对于x中的每个元素,大于5的不变,其余乘以2
print(torch.where(x>5,x,x*2))
tensor([ 0,  2,  4,  6,  8, 10,  6,  7,  8,  9])
1
2
#去重
print(torch.tensor([0,0,1,2,2,3]).unique())
tensor([0, 1, 2, 3])
1
2
3
x=torch.rand((4,5,3))
print(x.ndimension())#总共有几维
print(x.numel())#计算元素总个数:4*5*3=60
3
60

tesnor reshape

1
2
3
4
5
6
7
x=torch.arange(9)
#view只能改变类型为contiguous的张量
#如果tensor使用过transpose, permute等操作,会使得tensor变得在内存中不连续
#而reshape没有这个限制
x2=x.reshape(3,3)
print(x1)
print(x2)
tensor([[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]])
tensor([[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]])
1
2
3
4
5
6
x=torch.arange(9)
y=x1.t()#转置
print(y)

yy=x1.t()
print(yy)
tensor([[0, 3, 6],
        [1, 4, 7],
        [2, 5, 8]])
tensor([[0, 3, 6],
        [1, 4, 7],
        [2, 5, 8]])
1
2
3
4
5
x1=torch.rand(2,5)
x2=torch.rand(2,5)
#在特定axis上做拼接
print(torch.cat((x1,x2),dim=0).shape)
print(torch.cat((x1,x2),dim=1).shape)
torch.Size([4, 5])
torch.Size([2, 10])
1
2
3
#相当于flatten
z=x1.view(-1)
print(z.shape)
torch.Size([10])
1
2
3
4
5
#相当于做批量flatten
batch=64
x=torch.rand((batch,2,5))
z=x.view(batch,-1)
print(z.shape)
torch.Size([64, 10])
1
2
3
#改变维度所在axis,类似于二维的转置
z=x.permute(0,2,1)
print(z.shape)
torch.Size([64, 5, 2])
1
2
3
4
5
#维度压缩
x=torch.arange(10)
print(x.unsqueeze(0).shape)
print(x.unsqueeze(1).shape)
print(x.shape)
torch.Size([1, 10])
torch.Size([10, 1])
torch.Size([10])
1
2
3
4
5
#维度扩增
x=torch.arange(10).unsqueeze(0).unsqueeze(1)
print(x.shape)
z=x.squeeze(1)#去掉axis1
print(z.shape)
torch.Size([1, 1, 10])
torch.Size([1, 10])

以上内容大部分总结自一个Youtube小哥的视频,大家可以去看一下:
https://www.youtube.com/watch?v=x9JiIFvlUwk

当然,为了照顾无法科学上网的小伙伴,我已经将其搬运到了万能的B站:
https://www.bilibili.com/video/BV19v411j7Xd/

多年以后,
在一个风和日丽的午后,
一个老人躺在摇椅上晒着太阳,
有一个小孩大叫道:“爷爷,爷爷,你的推文有人点赞啦!”