PyTorch生成式人工智能实战(2)——PyTorch基础
PyTorch生成式人工智能实战(2)——PyTorch基础
- 0. 前言
- 1. 创建 PyTorch 张量
- 2. PyTorch 张量索引和切片
- 3. PyTorch 张量形状
- 4. 在 PyTorch 张量数学运算
- 小结
- 系列链接
0. 前言
为了训练生成式人工智能模型,我们可以使用多种数据格式,如原始文本、音频文件、图像像素以及数字数组等。然而,在 PyTorch
中创建的深度神经网络无法直接接受这些数据格式作为输入。因此,我们必须先将它们转换为神经网络能够理解和接受的格式。具体来说,需要先把各种形式的原始数据转换为 PyTorch
张量(用于表示和处理数据的基本数据结构),然后再将它们输入到深度神经网络模型中。因此,在本节中,我们将学习有关数据类型的基础知识,如何创建各种类型的 PyTorch
张量,以及如何在深度学习中使用它们。
1. 创建 PyTorch 张量
在训练深度神经网络时,我们将数字数组作为输入提供给模型。根据生成模型所要生成的内容,这些数字有不同的类型。例如,在生成图像时,输入是原始像素,表示为介于 0
到 255
之间的整数,但为了训练稳定,我们会将其转换为介于 -1
和 1
之间的浮动点数;而在生成文本时,会有一个类似于字典的“词汇表”,输入是一个整数序列,表示每个单词在字典中的对应项。
假设我们想要计算班级上学生的平均身高。首先,我们可以收集学生们的身高数据(单位为厘米),并将其存储在一个 Python
列表中:
heights = [189, 168, 183, 180, 183, 193, 182, 170,173, 193, 168, 178, 182, 185, 189, 183,178, 180, 182, 183, 191, 163, 173, 173,170, 188, 177, 183, 173, 174, 178, 175,185, 171, 175, 183, 182, 179, 188, 185,178, 183, 180, 183, 188, 183]
我们可以通过 PyTorch
的 tensor()
方法将 Python
列表转换为 PyTorch
张量:
import torch
heights_tensor = torch.tensor(heights, dtype=torch.float64) # 指定 PyTorch 张量中的数据类型
使用 tensor()
方法中的 dtype
参数可以指定数据类型。PyTorch
张量的默认数据类型是 float32
,即 32
位浮点数。在以上代码中,我们将数据类型转换为 float64
,即双精度浮点数。float64
提供比 float32
更精确的结果,但计算时间更长,精度和计算成本之间存在权衡,使用哪种数据类型取决于具体任务的需要。下表列出了不同的数据类型及其对应的 PyTorch
张量类型,包括具有不同精度的整数和浮点数:
PyTorch 张量类型 | tensor()中的dtype参数值 | 数据类型 |
---|---|---|
FloatTensor | torch.float32 or torch.float | 32位浮点型 |
HalfTensor | torch.float16 or torch.half | 16位浮点型 |
DoubleTensor | torch.float64 or torch.double | 64位浮点型 |
CharTensor | torch.int8 | 8 位整数(有符号) |
ByteTensor | torch.uint8 | 8 位整数(无符号) |
ShortTensor | torch.int16 or torch.short | 16位整数(有符号) |
IntTensor | torch.int32 or torch.int | 32位整数(有符号) |
LongTensor | torch.int64 or torch.long | 64位整数(有符号) |
可以通过两种方式来创建一个具有特定数据类型的张量。第一种方法是使用 PyTorch
类,如上表第一列所指定。第二种方法是使用 torch.tensor()
方法,并通过 dtype
参数指定数据类型(该参数的值在上表的第二列中列出)。例如,要将 Python
列表 [1, 2, 3]
转换为一个包含 32
位整数的 PyTorch
张量,可以使用以下两种方法:
# 使用 torch.IntTensor() 指定张量类型
t1=torch.IntTensor([1, 2, 3])
# 使用 dtype=torch.int 指定张量类型
t2=torch.tensor([1, 2, 3], dtype=torch.int)
print(t1)
print(t2)
输出结果如下所示:
tensor([1, 2, 3], dtype=torch.int32)tensor([1, 2, 3], dtype=torch.int32)
有时,我们需要创建一个所有值都为 0
的 PyTorch
张量。例如,在生成对抗网络中,我们创建一个全是 0
的张量来表示伪造样本的标签。PyTorch
中的 zeros()
方法能够根据指定张量的形状生成一个所有元素为零的张量。在 PyTorch
中,张量是一个 n
维数组,它的形状是一个表示每个维度大小的元组。生成一个形状为 (2, 3)
的全零张量:
tensor1 = torch.zeros(2, 3)
print(tensor1)
输出结果如下:
tensor([[0., 0., 0.],[0., 0., 0.]])
该张量的形状为 (2, 3)
,意味着该张量是一个二维数组,第一维有两个元素,第二维有三个元素。在这里,我们没有指定数据类型,因此使用默认的数据类型 float32
。
有时,我们需要创建一个所有值都为 1
的 PyTorch
张量。例如,在生成对抗网络中,我们创建一个所有值为 1
的张量,作为真实样本的标签。使用 ones()
方法创建一个所有值为 1
的三维张量:
tensor2 = torch.ones(1,4,5)
print(tensor2)
输出结果如下所示,可以看到生成了一个三维的 PyTorch
张量,该张量的形状为 (1, 4, 5)
:
tensor([[[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.]]])
除了 Python
列表外,我们也可以在张量构造函数中使用 NumPy
数组:
import numpy as np
nparr=np.array(range(10))
pt_tensor=torch.tensor(nparr, dtype=torch.int)
print(pt_tensor)
输出结果如下所示:
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=torch.int32)
2. PyTorch 张量索引和切片
可以使用方括号 ([]
) 来对 PyTorch
张量进行索引和切片,就像对 Python
列表进行操作一样。索引和切片允许我们操作张量中的一个或多个元素,而不是操作所有元素。继续以学生身高为例,如果我们想查看第 3
个学生的身高:
height = heights_tensor[2]
print(height)
# tensor(183., dtype=torch.float64)
我们也可以使用负索引从张量的末尾进行计数,例如,要查找倒数第2个学生的身高,可以使用索引 -2
:
height = heights_tensor[-2]
print(height)
# tensor(188., dtype=torch.float64)
如果我们想知道张量 heights_tensor
中倒数后 5
位学生的身高,可以通过切片获取张量的一部分:
five_heights = heights_tensor[-5:]
print(five_heights)
# tensor([183., 180., 183., 188., 183.], dtype=torch.float64)
冒号 (:
) 用于分隔起始和结束索引。如果没有提供起始索引,默认值是 0
;如果没有提供结束索引,则会包含张量中的最后一个元素,负索引表示从末尾开始计数。
3. PyTorch 张量形状
PyTorch
张量有一个 shape
属性,用于获取张量的维度。了解 PyTorch
张量的形状非常重要,因为形状不匹配会导致操作时发生错误。例如,想了解张量 heights_tensor
的形状:
print(heights_tensor.shape)
输出结果如下所示,表明 heights_tensor
是一个包含 46
个值的 1D
张量:
torch.Size([46])
我们也可以改变 PyTorch
张量的形状。为了学习如何改变张量形状,首先我们将高度从厘米转换为英尺。因为 1
英尺大约等于 30.48 厘米,我们可以通过将张量除以 30.48
来实现:
heights_in_feet = heights_tensor / 30.48
print(heights_in_feet)
输出结果如下所示,新的张量 heights_in_feet
存储的是英尺单位的高度:
我们可以使用 PyTorch
中的 cat()
方法来连接这两个张量:
heights_2_measures = torch.cat([heights_tensor,heights_in_feet], dim=0)
print(heights_2_measures.shape)
# torch.Size([92])
dim
参数用于在各种张量操作中指定操作执行的维度。在以上代码中,dim=0
表示我们沿着第一个维度连接这两个张量。结果张量是一个 1D
张量,包含 92
个值,其中一些是以厘米为单位的高度,另一些是以英尺为单位的高度。将其重新调整为 2
行 46
列的形状,这样第一行表示厘米单位的高度,第二行表示英尺单位的高度:
heights_reshaped = heights_2_measures.reshape(2, 46)
新的张量 heights_reshaped
是一个 2D
张量,形状为 (2, 46)
。我们也可以使用方括号对多维张量进行索引和切片。例如,打印倒数第 2
位学生的身高(英尺单位):
print(heights_reshaped[1,-2])
# tensor(6.1680, dtype=torch.float64)
heights_reshaped[1, -2]
告诉 Python
查找第二行倒数第二列的值。需要注意的是,引用张量中的标量值所需的索引数量与张量的维度相同。这就是为什么我们在 1D
张量 heights_tensor
中使用一个索引来定位值,而在 2D
张量 heights_reshaped
中使用两个索引来定位值。
4. 在 PyTorch 张量数学运算
我们可以使用不同的方法对 PyTorch
张量进行数学运算,如 mean()
、median()
、sum()
、max()
等。例如,要找出 46
位学生的身高中位数(单位:厘米):
print(torch.median(heights_reshaped[0,:]))
# tensor(182., dtype=torch.float64)
heights_reshaped[0,:]
返回张量 heights_reshaped
的第一行的所有值,torch.median(heights_reshaped[0,:])
返回第一行的中位数。
要获取每行的平均身高,可以在 mean()
方法中使用参数 dim=1
:
print(torch.mean(heights_reshaped,dim=1))
dim=1
参数表示通过合并列(索引为 1
的维度)来计算平均值,实际上是沿着索引为 0
的维度计算平均值。输出结果如下所示,结果如下,两行的平均值分别是 180.0652
厘米和 5.9077
英尺:
tensor([180.0652, 5.9077], dtype=torch.float64)
获取最高的学生身高:
values, indices = torch.max(heights_reshaped, dim=1)
print(values)
print(indices)
输出如下所示,torch.max()
方法返回两个张量,一个是包含最高学生身高的张量(单位为厘米和英尺),另一个是包含该学生索引的张量:
tensor([193.0000, 6.3320], dtype=torch.float64)
tensor([5, 5])
小结
PyTorch
张量是多维数据的基本结构,支持灵活的形状变换、索引操作和数学计算。数据类型的选择(如精度权衡)和形状匹配是深度学习中的重要考量。通过张量操作,可高效实现数据预处理、特征整合及模型输入输出处理。
系列链接
PyTorch生成式人工智能实战:从零打造创意引擎
PyTorch生成式人工智能实战(1)——神经网络与模型训练过程详解