深度学习小白一枚,最近在看李沐的动手学深度学习(2021版本),一些代码感觉看不太懂,于是写个博客记录下代码的一些个人理解,也方便后续复习。
import torch
x = torch.arange(12)
x
#结果:tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
这里的张量我理解的就是一个’数组‘,一维是向量,二维是矩阵。torch.arange(12)创建一个大小为12的行向量。
x.shape
#结果:torch.Size([12])
x.numel()
#结果:12
x.shape查看张量x每一个维度所包含元素的个数。x.numel()查看所有的元素个数。
X = x.reshape(3, 4)
X
#结果:tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
改变张量x的形状,也可以用x.reshape(-1,4)或x.reshape(3,-1),给出一个维度之后会自动计算出另一个维度。注意此时x应该是一个二维矩阵了。
torch.zeros((2, 3, 4))
#结果:
#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((2, 3, 4))
#结果:
#tensor([[[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]],
#
# [[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]]])
torch.zero&torch.ones分别生成全0和全1矩阵,第一个参数表示高度(样本个数),后两个参数表示高度和宽度。注意此时生成的应该是三维的数组。
torch.randn(3, 4)
#结果:
# tensor([[-0.9464, 0.7712, -0.0070, 1.0236],
# [-2.1246, -0.7854, -1.9674, -0.1727],
# [ 0.0397, -0.0477, -0.0160, -0.0113]])
创建一个3行4列,每个元素都从均值为0、标准差为1的标准高斯(正态)分布中随机采样的张量。
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
#结果:
# tensor([[2, 1, 4, 3],
# [1, 2, 3, 4],
# [4, 3, 2, 1]])
手动输入参数创建张量(3行4列)。
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y # **运算符是求幂运算
#结果: (tensor([ 3., 4., 6., 10.]),
# tensor([-1., 0., 2., 6.]),
# tensor([ 2., 4., 8., 16.]),
# tensor([0.5000, 1.0000, 2.0000, 4.0000]),
# tensor([ 1., 4., 16., 64.]))
加减乘除比较简单,相对应的元素相加减乘除就可以。注意x**y是求幂运算。
torch.exp(x)
#结果:tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
对张量x进行幂指数运算。
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)
#(tensor([[ 0., 1., 2., 3.],
#[ 4., 5., 6., 7.],
#[ 8., 9., 10., 11.],
#[ 2., 1., 4., 3.],
# [ 1., 2., 3., 4.],
# [ 4., 3., 2., 1.]]),
#tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],
# [ 4., 5., 6., 7., 1., 2., 3., 4.],
# [ 8., 9., 10., 11., 4., 3., 2., 1.]]))
张量连结(concatenate),这里分别将X和Y按行(轴0)和按列(轴1)连结在一起,这里为什么行是轴0,列是轴1呢?因为最开始创建的一维张量是一个行向量。按轴0,那就是两个张量按行连结列数不变共6行,按列就是行数不变共8列。
X==Y
# tensor([[False, True, False, True],
# [False, False, False, False],
# [False, False, False, False]])
逻辑运算符构建一个张量,里面应该都是布尔型元素。
X.sum()
#tensor(66.)
对张量中所有元素进行求和。
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a, b
#(tensor([[0],
# [1],
# [2]]),
# tensor([[0, 1]]))
a+b
# tensor([[0, 1],
# [1, 2],
# [2, 3]])
广播机制。比如两个形状不同的张量相加,先各自将张量复制成能互相相加的形状,然后再相加。
X[-1], X[1:3]
#(tensor([ 8., 9., 10., 11.]),
# tensor([[ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.]]))
很简单的python语法,注意python中下标是从0开始,一般最后一个下边不被包含在其中。
X[1, 2] = 9
X
#tensor([[ 0., 1., 2., 3.],
# [ 4., 5., 9., 7.],
# [ 8., 9., 10., 11.]])
X[0:2, :] = 12
X
#tensor([[12., 12., 12., 12.],
# [12., 12., 12., 12.],
# [ 8., 9., 10., 11.]])
通过指定索引将元素写入矩阵。
before = id(Y)
Y = Y + X
id(Y) == before
#False
引用Y=Y+X会为Y开辟一个新地址,可能会造成资源浪费,而且更新时可能会引用旧的地址的值,造成错误。可以用id()来查询其确切地址。
Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z))
#id(Z): 140272150341696
#id(Z): 140272150341696
before = id(X)
X += Y
id(X) == before
#True
切片表示法分配给之前准备好的数组Z,也可以直接就用Y[:]。或者用+=。
A = X.numpy()
B = torch.tensor(A)
type(A), type(B)
#(numpy.ndarray, torch.Tensor)
张量和numpy库中的数组进行转换之后不共享地址。
a = torch.tensor([3.5])
a, a.item(), float(a), int(a)
#(tensor([3.5000]), 3.5, 3.5, 3)
要将大小为1的张量转换为Python标量,我们可以调用item
函数或Python的内置函数。