Bootstrap

深度学习2:从零开始掌握PyTorch:数据操作不再是难题


在这里插入图片描述

本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描述事情本身

一、导读

在深度学习的广阔天地里,数据操作是每一位AI算法工程师必须掌握的基本技能。今天我们将通过PyTorch这一流行的深度学习框架,深入探讨数据操作的核心内容,包括张量的定义、基本操作、广播机制、索引与切片、内存管理,以及与其他Python对象的转换。希望借助这篇文章,你能对深度学习的数据操作有更深入的认知,在实际项目里运用得更得心应手。

二、张量的定义与基本操作

张量是深度学习中用于存储和操作数据的基本单位,它是一个n维数组。在PyTorch中,张量类名为torch.Tensor,与NumPy的ndarray类似,但支持GPU加速计算和自动微分,更适合深度学习应用。

1. 张量的创建

我们可以通过多种方式创建张量,例如使用torch.arangetorch.zerostorch.onestorch.random等函数。以下是一些示例代码:

import torch

# 创建一个行向量,包含0到11的整数
x = torch.arange(12)
print(x)
# 输出:tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

# 创建一个形状为(2,3,4)的全0张量
zeros_tensor = torch.zeros((2, 3, 4))
print(zeros_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.]]])

# 创建一个形状为(3,4)的标准高斯分布随机张量
random_tensor = torch.random(3, 4)
print(random_tensor)
# 输出:tensor([[ 0.0561, -0.2157,  0.3538, -0.1382],
#               [-0.2219, -0.3074, -0.5218, -0.4200],
#               [ 0.3139, -0.2678, -0.2274, -0.3605]])

2. 张量的形状与大小

通过.shape属性可以获取张量的形状,通过.numel()方法或.size()属性可以获取张量中元素的总数。

print(x.shape)  # 输出:torch.Size([12])
print(x.numel())  # 输出:12
print(x.size())  # 输出:torch.Size([12])

3. 张量的重塑

使用.reshape方法可以改变张量的形状而不改变其元素值。

# 将x重塑为形状为(3,4)的矩阵
X = x.reshape(3, 4)
print(X)
# 输出:tensor([[ 0.,  1.,  2.,  3.],
#               [ 4.,  5.,  6.,  7.],
#               [ 8.,  9., 10., 11.]])

4. 张量的按元素运算

PyTorch支持常见的标准算术运算符(+、-、*、/、**)的按元素运算。

y = torch.tensor([2, 2, 2, 2])
print(X + y, X - y, X * y, X / y, X ** y)
# 输出:
# tensor([[ 2.,  3.,  4.,  5.],
#         [ 6.,  7.,  8.,  9.],
#         [10., 11., 12., 13.]]) 
# tensor([[-2., -1.,  0.,  1.],
#         [ 2.,  3.,  4.,  5.],
#         [ 6.,  7.,  8.,  9.]]) 
# tensor([[ 0.,  2.,  4.,  6.],
#         [ 8., 10., 12., 14.],
#         [16., 18., 20., 22.]]) 
# tensor([0.0000, 0.5000, 1.0000, 1.5000])
#        [2.0000, 2.5000, 3.0000, 3.5000])
#        [4.0000, 4.5000, 5.0000, 5.5000]])
# tensor([[ 1.,  1.,  1.,  1.],
#         [16., 25., 36., 49.],
#         [256., 512., 1024., 2048.]])

三、广播机制

广播机制允许PyTorch在执行按元素运算时自动扩展张量的形状,以匹配另一个张量的形状。

# 创建两个形状不同的张量
a = torch.arange(3).reshape(3, 1)
b = torch.arange(2).reshape(1, 2)
print(a, b)
# 输出:
# tensor([[0.],
#         [1.],
#         [2.]]) 
# tensor([[0, 1]])

# 通过广播机制进行按元素相加
print(a + b)
# 输出:
# tensor([[0., 1.],
#         [1., 2.],
#         [2., 3.]])

四、索引与切片

在PyTorch中,张量的元素可以通过索引和切片进行访问和修改。

# 访问最后一个元素
print(X[-1])
# 输出:tensor([ 8.,  9., 10., 11.])

# 访问第二行到第三行的所有列
print(X[1:3, :])
# 输出:tensor([[ 4.,  5.,  6.,  7.],
#               [ 8.,  9., 10., 11.]])

# 修改第二行第三列的元素值
X[1, 2] = 99
print(X)
# 输出:tensor([[ 0.,  1.,  2.,  3.],
#               [ 4.,  5., 99.,  7.],
#               [ 8.,  9., 10., 11.]])

五、内存管理

在PyTorch中,原地操作可以节省内存开销。原地操作是指直接修改现有张量而不创建新的张量。

# 创建一个新的张量Y,形状与X相同
Y = torch.zeros_like(X)
print('id(Y) before:', id(Y))

# 使用原地操作将X+Y的结果赋值给Y
Y[:] = X + Y
print('id(Y) after:', id(Y))
# 输出:id(Y) before 和 id(Y) after 的值相同,说明Y没有指向新的内存位置

六、与其他Python对象的转换

PyTorch张量可以轻松地转换为NumPy数组,反之亦然。但需要注意的是,转换后的结果不共享内存。

# 将PyTorch张量转换为NumPy数组
A = X.numpy()
print(type(A))  # 输出:<class 'numpy.ndarray'>

# 将NumPy数组转换为PyTorch张量
B = torch.tensor(A)
print(type(B))  # 输出:<class 'torch.Tensor'>

参考文献:
动手学深度学习在线课程(https://zh-v2.d2l.ai/chapter_introduction/index.html)

;