PyTorch强化学习——PyTorch基础详解

1,134 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

PyTorch 基础

我们将使用 PyTorch 作为实现强化学习算法的数值计算库。PyTorchFacebook 开发的科学计算和机器学习库,张量 (Tensor) 是 PyTorch 中的核心数据结构,类似于 NumPy 中的 ndarray。 但是,PyTorch 在数组操作和遍历等方面的速度比 NumPy 更快,这主要是由于在 PyTorch 中,数组元素的访问速度更快。接下来,我们介绍一些 PyTorch 中的基本知识,以便在之后的强化学习实战中使用。

张量

创建张量

默认张量 (Tensor) 的数据类型是 torch.float32,这是张量运算最常用的数据类型。从区间 [0,1] 的均匀分布中随机采样生成浮点数:

>>> import torch
>>> x = torch.rand(4,3)
>>> print(x)
tensor([[0.1968, 0.6183, 0.9863],
        [0.6465, 0.5472, 0.7393],
        [0.4933, 0.1890, 0.0459],
        [0.4462, 0.8802, 0.4948]])

我们也可以创建指定数据类型的张量,例如,返回一个 double 类型的张量 (float64),如下所示:

>>> x = torch.rand(4,3,dtype=torch.double)
>>> print(x)
tensor([[0.3899, 0.2509, 0.5130],
        [0.5605, 0.5399, 0.2442],
        [0.5419, 0.8523, 0.3360],
        [0.4898, 0.1152, 0.4379]], dtype=torch.float64)

创建指定尺寸的矩阵,并用 01 进行填充:

>>> x = torch.zeros(4,3)
>>> print(x)
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
>>> x = torch.ones(4,3)
>>> print(x)
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])

可以使用数据的 size 方法获得张量的尺寸,其返回 torch.Size 元组:

>>> print(x.size())
torch.Size([4, 3])

可以使用 view 方法变换张量形状:

>>> x_reshaped = x.view(2,6)
>>> print(x_reshaped)
tensor([[1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1.]])

可以直接使用数据创建张量,包括单个值,列表和嵌套列表:

>>> x_1 = torch.tensor(4)
>>> print(x_1)
tensor(4)
>>> x_2 = torch.tensor([11.11,22,33,0])
>>> print(x_2)
tensor([11.1100, 22.0000, 33.0000,  0.0000])
>>> x_3 = torch.tensor([[1,2,3,4],[5,6.6,7.7,8.0]])
>>> print(x_3)
tensor([[1.0000, 2.0000, 3.0000, 4.0000],
        [5.0000, 6.6000, 7.7000, 8.0000]])

张量元素访问

可以使用类似于 NumPy 的方式利用索引来访问张量中的元素,对于单元素张量,我们也可以使用 item() 方法来访张量中的元素:

>>> print(x_3[0])
tensor([1., 2., 3., 4.])
>>> print(x_3[0,0])
tensor(1.)
>>> print(x_3[:,2])
tensor([3.0000, 7.7000])
>>> print(x_3[:,2:])
tensor([[3.0000, 4.0000],
        [7.7000, 8.0000]])
>>> print(x_1.item())
4

张量数据类型转换

TensorNumPy 数组可以相互转换,使用 numpy() 方法可以将张量转换为 NumPy 数组,而想要将 NumPy 数组转换为张量想要使用 from_numpy() 方法:

>>> print(x_3.numpy())
[[1.  2.  3.  4. ]
 [5.  6.6 7.7 8. ]]
>>> import numpy as np
>>> x_np = np.ones(4)
>>> x_torch = torch.from_numpy(x_np)
>>> print(x_torch)
tensor([1., 1., 1., 1.], dtype=torch.float64)

需要注意的是,如果输入的 NumPy 数组是 float 数据类型,输出张量默认情况下为 double 类型,因此可能需要类型转换。在以下代码中,我们可以将 double 类型的张量转换为 float 类型:

>>> print(x_torch.float())
tensor([1., 1., 1., 1.])

张量运算

PyTorch 中的运算操作也类似于 NumPy。接下来,我们以加法为例,可以直接使用 + 运算符,或者使用 add() 方法:

>>> x_4 = torch.tensor([[1,1,1,0],[1,2,3,4.]])
>>> print(x_3+x_4)
tensor([[ 2.0000,  3.0000,  4.0000,  4.0000],
        [ 6.0000,  8.6000, 10.7000, 12.0000]])
>>> print(torch.add(x_3, x_4))
tensor([[ 2.0000,  3.0000,  4.0000,  4.0000],
        [ 6.0000,  8.6000, 10.7000, 12.0000]])

同时,PyTorch 也支持就地 (in-place) 操作,这类操作可以直接改变张量对象:

>>> x_3.add_(x_4)
tensor([[ 2.0000,  3.0000,  4.0000,  4.0000],
        [ 6.0000,  8.6000, 10.7000, 12.0000]])
>>> print(x_3)
tensor([[ 2.0000,  3.0000,  4.0000,  4.0000],
        [ 6.0000,  8.6000, 10.7000, 12.0000]])

在以上输出中,可以看到使用 add_() 方法,会直接修改 x_3 的值,将其改变为原始 x_3x_4 之和。在 PyTorch 中,带有 _ 的方法都表明其为就地操作,它将使用结果值来更新张量。 默认情况下,PyTorch 张量存储在 CPU 上。PyTorch 张量可以使用 GPU 加速计算,这是张量与 NumPy 数组相比的主要优势。为了利用此优势,我们需要将张量移动到 CUDA 设备上。使用 cuda.is_available() 方法可以检测cuda的可用性,可以使用 to() 方法将张量移动到任何可用设备上:

>>> torch.cuda.is_available()
True
>>> torch.cuda.device_count() # 统计可用的GPU数量
1
>>> torch.cuda.current_device() # 当前GPU索引
0
>>> torch.cuda.get_device_name(0) # GPU型号
'NVIDIA GeForce RTX 2070 SUPER'
>>> x_3.device # 当前设备
device(type='cpu')
>>> device = 'cuda' if torch.cuda.is_available() else 'cpu'
>>> x_3 = x_3.to(device) # 将张量转移到指定设备上
>>> x_3.device
device(type='cuda', index=0)
>>> x_5 = torch.ones(3,3,device=device) # 创建张量时指定张量
>>> print(x_5)
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], device='cuda:0')

系列链接

PyTorch+Gym强化学习环境搭建 - 掘金 (juejin.cn)