1 model.eval()
和 model.train()
model.eval()
和 model.train()
是 PyTorch 中用于切换模型状态的两个方法,它们有以下不同点:
-
模型状态:
model.train()
:将模型切换到训练模式。在训练模式下,模型启用了一些与训练相关的特性,如启用 Dropout 层和 Batch Normalization 层,以及跟踪参数的梯度用于反向传播。model.eval()
:将模型切换到评估模式。在评估模式下,模型关闭了一些与训练相关的特性,如关闭 Dropout 层和使用批次统计信息进行 Batch Normalization,以便获得更稳定的评估结果。
-
Dropout 层:
model.train()
:在训练模式下,Dropout 层会保持激活,以便在每个前向传播中随机丢弃一部分神经元的输出,用于防止过拟合。model.eval()
:在评估模式下,Dropout 层会关闭,以确保获得一致的评估结果。
-
Batch Normalization:
model.train()
:在训练模式下,Batch Normalization 层使用当前批次的统计信息来进行归一化,以便更好地适应批次数据。model.eval()
:在评估模式下,Batch Normalization 层使用累积的统计信息来进行归一化,以确保获得一致的评估结果。
总之,model.eval()
用于将模型配置为适合评估或推理的状态,以确保获得一致的结果并关闭训练期间的特性,而 model.train()
用于将模型配置为适合训练的状态,以执行训练过程中需要的操作。通常,模型在训练期间会交替调用这两个方法以适应不同的任务。
2 Dataset类中的__getitem__
和 __len__
方法
torch.utils.data.Dataset是PyTorch中用来表示数据集的抽象类,Dataset是一个包装类,用来将数据包装为Dataset类,然后传入DataLoader中从而使DataLoader类更加快捷的对数据进行操作。当处理自定义的数据集的时候必须继承Dataset,然后重写 __len__()和__getitem__()函数。
1)__len__()
: 使得len(dataset)
返回数据集的大小;
2) __getitem__(self, index)
: 这个方法根据给定的索引index
返回数据集中指定索引位置的样本。这通常是一个字典,包含输入数据和标签等。
在PyTorch中,一般使用DataLoader
来加载自定义Dataset
并进行数据的批处理和数据加载。DataLoader
将自动处理数据的批处理、随机化、数据并行等方面的工作。然后在迭代中获取每个批处理的数据,并将其传递给模型进行训练。
3 nn.Module
类
在 PyTorch 中,当你定义一个新的类,特别是一个神经网络模型时,通常会继承自 nn.Module
类。定义类的参数 nn.Module
表示该类是一个 PyTorch 模型或模型的组件,这允许你使用 PyTorch 框架提供的模型组件,如线性层、卷积层、循环神经网络等。
继承自 nn.Module
的类具有以下重要特点:
-
参数管理:
nn.Module
类提供了参数管理的功能。当你在类中定义神经网络的层或组件时,这些层和组件的参数(例如权重和偏置)会自动注册到模型中,允许你方便地访问和管理这些参数。 -
前向传播:你需要在继承自
nn.Module
的类中实现前向传播逻辑。前向传播定义了如何将输入数据传递到模型中的各个层和组件,并最终生成输出。通常,你会在类的forward
方法中定义前向传播逻辑。 -
模型组合:你可以将多个继承自
nn.Module
的类组合在一起,构建复杂的神经网络架构。这使得模型的设计更加模块化和可扩展。 -
状态管理:
nn.Module
类会自动跟踪模型中各个层和组件的状态。这允许你轻松保存和加载模型,管理模型的训练和推理状态,以及在需要时修改模型的组件。
4 nn.Embedding模块
nn.Embedding
是 PyTorch 中的一个模块,通常用于学习输入数据的嵌入(embedding)。嵌入是将高维的离散数据(如单词、类别、标签等)映射到低维的实数向量空间的过程。嵌入通常用于将离散数据转换为连续值表示,以便能够输入神经网络进行训练。
nn.Embedding
模块的主要参数是词汇表的大小(vocab_size)和嵌入维度(embedding_dim)。通常,你需要指定这两个参数,然后在训练过程中,PyTorch 会自动学习嵌入的权重。
关于nn.Embedding与nn.Embedding.from_pretrained的区别: 可以参考博文:nn.Embedding与nn.Embedding.from_pretrained-优快云博客
下面引用一下博文内容:
在NLP任务中,当我们搭建网络时,第一层往往是嵌入层,对于嵌入层有两种方式初始化embedding向量,一种是直接随机初始化,另一种是使用预训练好的词向量初始化,接下来分别介绍这种的使用方式,以及torch中对应的源码。
torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None, norm_type=2.0, scale_grad_by_freq=False, sparse=False, _weight=None, device=None, dtype=None)
这是一个简单的查找表,用于存储固定字典和大小的嵌入。该模块通常用于存储词嵌入并使用索引检索它们。 该模块的输入是索引列表,输出是相应的词嵌入。
num_embeddings (int) - 嵌入字典的大小
embedding_dim (int) - 每个嵌入向量的大小
padding_idx (int, optional) - 如果提供的话,则 padding_idx位置处的嵌入不会影响梯度,也就是训练时不会更新该索引位置的嵌入向量,默认为零向量,也可以更新为另一个值以用作填充向量。
max_norm (float, optional) - 如果提供的话,会重新归一化词嵌入,使它们的范数小于提供的值
norm_type (float, optional) - 对于max_norm选项计算p范数时的p
scale_grad_by_freq (boolean, optional) - 如果提供的话,会根据字典中单词频率缩放梯度
weight weight (Tensor) -形状为(num_embeddings, embedding_dim)的模块中可学习的权值
embedding = nn.Embedding(10, 3)
input = torch.LongTensor([[1,2,4,5],[4,3,2,9]])
print(embedding(input))
------
tensor([[[-0.0251, -1.6902, 0.7172],
[-0.6431, 0.0748, 0.6969],
[ 1.4970, 1.3448, -0.9685],
[-0.3677, -2.7265, -0.1685]],
[[ 1.4970, 1.3448, -0.9685],
[ 0.4362, -0.4004, 0.9400],
[-0.6431, 0.0748, 0.6969],
[ 0.9124, -2.3616, 1.1151]]])
5 混合精度训练
if args.fp16:
scaler = torch.cuda.amp.GradScaler()
else:
scaler = None
上述代码片段中,根据args.fp16
参数的值来创建了一个用于混合精度训练(mixed-precision training)的PyTorch的torch.cuda.amp.GradScaler
对象或者赋值为None
。
在混合精度训练中,模型的参数通常使用较低精度(例如半精度浮点数)进行计算,以提高训练速度和减少内存占用。然而,梯度计算通常需要在较高精度上进行以避免数值不稳定性。GradScaler
用于帮助自动缩放梯度以在这两种精度之间进行平衡。
在上述代码中:
- 如果
args.fp16
为True
,表示启用混合精度训练,因此创建一个torch.cuda.amp.GradScaler
对象并将其分配给scaler
。 - 如果
args.fp16
为False
,表示不使用混合精度训练,将scaler
分配为None
,这意味着在训练过程中不会使用梯度缩放。
GradScaler
的主要目的是在反向传播期间缩放梯度,以防止在低精度计算中发生梯度下溢或上溢。这通常有助于提高训练速度和内存效率,同时保持模型的训练质量。