为了能够完成各种数据操作,我们需要某种方法来存储和操作数据。 通常,我们需要做两件重要的事:(1)获取数据;(2)将数据读入计算机后对其进行处理。 如果没有某种方法来存储数据,那么获取数据是没有意义的。
首先,我们介绍维数组,也称为张量(tensor)。 使用过Python中NumPy计算包的读者会对本部分很熟悉。 无论使用哪个深度学习框架,它的张量类(在MXNet中为ndarray, 在PyTorch和TensorFlow中为Tensor)都与Numpy的ndarray类似。 但深度学习框架又比Numpy的ndarray多一些重要功能: 首先,GPU很好地支持加速计算,而NumPy仅支持CPU计算; 其次,张量类支持自动微分。 这些功能使得张量类更适合深度学习。 如果没有特殊说明,本书中所说的张量均指的是张量类的实例。–《动手学深度学习》
一、
x = torch.arange(12) # 创建一个含有12个元素的行向量
print(x) # 输出创建的张量,张量表示由一个数值组成的数组,这个数组可能有多个维度
print(x.shape) # 通过张量的shape属性来访问张量(沿每个轴的长度)的形状
print(x.numel()) # 张量中元素的总数
输出:
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
torch.Size([12])
12
二、
X = x.reshape(3, 4) # 将x从行向量转变为3行4列的矩阵,还可以通过x.reshape(3,-1)或者x.reshape(-1,4)让torch自动计算
print(X)
输出:
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
四、
y = torch.zeros((2, 3, 4)) # 创建一个形状为(2,3,4)的张量,其中所有元素都设置为0,第一个参数代表创建几个3行4列的矩阵
print(y)
z = torch.ones((2, 3, 4)) # 创建一个形状为(2,3,4)的张量,其中所有元素都设置为1,第一个参数代表创建几个3行4列的矩阵
print(z)
输出:
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.]]])
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.]]])
五、
a = torch.randn(3, 4) # 每个元素都从均值为0、标准差为1的标准高斯分布(正态分布(Normal distribution))中随机采样
print(a)
输出:
tensor([[-0.1024, 0.1142, -0.6478, -0.0730],
[ 0.4957, 0.1379, 0.1367, -0.6389],
[ 0.3903, 0.0232, 1.1764, -0.0586]])
六、
# 通过提供包含数值的Python列表(或嵌套列表),来为所需张量中的每个元素赋予确定值。 在这里,最外层的列表对应于轴0,内层的列表对应于轴1
b = torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(b)
输出:
tensor([[2, 1, 4, 3],
[1, 2, 3, 4],
[4, 3, 2, 1]])
七、
# 可以在同一形状的任意两个张量上调用按元素操作
c = torch.tensor([1.0, 2, 4, 8])
d = torch.tensor([2, 2, 2, 2])
print(c + d) # 加法
print(c - d) # 减法
print(c * d) # 乘法
print(c / d) # 除法
print(c ** d) # 求幂运算
print(torch.exp(c)) # c的e次幂
输出:
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.])
tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
八、
# 可以把多个张量连结(concatenate)在一起, 把它们端对端地叠起来形成一个更大的张量
e = torch.arange(12, dtype=torch.float32).reshape(3, 4)
f = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(torch.cat((e, f), dim=0)) # 沿行(轴-0,形状的第一个元素)连结两个矩阵,输出张量的轴-0长度(6)是两个输入张量轴-0长度的总和(3+3)
print(torch.cat((e, f), dim=1)) # 按列(轴-1,形状的第二个元素)连结两个矩阵,输出张量的轴-1长度(8)是两个输入张量轴-1长度的总和(4+4)
输出:
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.]])
九、
print(e == f) # 对于每个位置,如果X和Y在该位置相等,则新张量中相应项的值为1,这意味着逻辑语句e == f在该位置处为真,否则该位置为0,意味着假
print(e.sum()) # 对张量中的所有元素进行求和,会产生一个单元素张量
输出:
tensor([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
tensor(66.)
十、
# 广播机制
# 工作方式如下:首先,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状.其次,对生成的数组执行按元素操作
g = torch.arange(3).reshape((3, 1))
h = torch.arange(2).reshape((1, 2))
# 由于a和b分别是和矩阵,如果让它们相加,它们的形状不匹配.我们将两个矩阵广播为一个更大的矩阵,如下所示:矩阵a将复制列,矩阵b将复制行,然后再按元素相加
print(g)
print(h)
print(g + h)
输出:
tensor([[0],
[1],
[2]])
# 相当于复制成
# tensor([[0, 0],
# [1, 1],
# [2, 2]])
tensor([[0, 1]])
# 相当于复制成
# tensor([[0, 1], [0, 1], [0, 1]])
tensor([[0, 1],
[1, 2],
[2, 3]])
十一、
# 索引与切片
print(x[-1]) # 最后一个元素索引是-1
print(x[1:3]) # 用[1:3]选择第二个和第三个元素
b[1, 2] = 9 # 通过指定索引来将元素写入矩阵
print(b)
i = torch.arange(12).reshape(3, 4)
j = torch.arange(12).reshape(3, 4)
i[0:2, :] = 12 # 按列的方向修改,实际是修改1,2行
j[:, 0:2] = 12 # 按行的方向修改,实际是修改1,2列
print(i)
print(j)
输出:
tensor(11)
tensor([1, 2])
tensor([[2, 1, 4, 3],
[1, 2, 9, 4],
[4, 3, 2, 1]])
tensor([[12, 12, 12, 12],
[12, 12, 12, 12],
[ 8, 9, 10, 11]])
tensor([[12, 12, 2, 3],
[12, 12, 6, 7],
[12, 12, 10, 11]])
十二、
# 原地操作的方式:1.Y[:] = 2.X += Y
# 第一种
k = torch.zeros_like(i)
print(id(k))
k[:] = k + i
print(id(k))
# 第二种
before = id(k)
k += i
if before == id(k):
print("true")
else:
print("false")
输出:
1610199749248
1610199749248
true
十三、
# 将深度学习框架定义的张量转换为NumPy张量(ndarray)很容易,反之也同样容易.torch张量和numpy数组将共享它们的底层内存,就地操作更改一个张量也会同时更改另一个张量
A = X.numpy()
B = torch.tensor(A)
print(type(A))
print(type(B))
输出:
<class 'numpy.ndarray'>
<class 'torch.Tensor'>
十四、
# 将大小为1的张量转换为Python标量,我们可以调用item函数或Python的内置函数
l = torch.tensor([3.5])
print(l)
print(l.item())
print(float(l))
print(int(l))
输出:
tensor([3.5000])
3.5
3.5
3