【pytorch】(五)优化模型参数

本文涉及的产品
交互式建模 PAI-DSW,5000CU*H 3个月
简介:

优化模型参数

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda

device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)

# ======================= 数据 =======================
training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor()
)

test_data = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor()
)

train_dataloader = DataLoader(training_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)


# ======================= 模型 =======================
class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()

        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28 * 28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = x.flatten(1)
        logits = self.linear_relu_stack(x)
        return logits

现在我们已经有模型和数据集了,是时候利用数据集来训练、验证和测试我们的模型了。训练模型是一个迭代过程;在每次迭代(称为epoch)中,数据输入模型;模型对输出进行估计;优化器根据估计值与真实值的误差(损失loss)计算其相对于模型参数的导数(如前一节所示),然后使用梯度下降优化模型的参数。

超参数

超参数是可调的参数,我们可以通过调整超参数来控制模型优化过程:超参数取不同值可能会影响模型训练和收敛速度。

我们为模型的训练定义以下超参数:

learning_rate = 1e-3
batch_size = 64
epochs = 10
  • Epochs:遍历整个数据集的次数
  • Batch Size:更新参数之前输入模型的数据样本数
  • 学习率(Learning Rate):在每个批次/epoch更新模型参数的程度。小的学习率会导致学习速度较慢,而较大的值可能会导致模型不收敛。

循环优化

一旦我们设置了超参数,我们就可以通过循环优化来训练和优化我们的模型。优化循环的每次迭代称为一个epoch

每个epoch由两个主要部分组成:

(1) 训练循环(The Train Loop):迭代训练数据集,尝试着让模型参数收敛到最佳参数。

在训练环节中,优化分为三个步骤:

  • 调用optimizer.zero_grad()重置模型参数的梯度。默认情况下,梯度是累加的;为了防止重复计数,我们在每次迭代时显式地将它们归零。
  • 通过调用loss.backward()对预测损失进行反向传播。PyTorch将存储损失关于每个参数的梯度。
  • 一旦我们得到了梯度,我们就调用optimizer.step(),这将通过在反向传播中收集的梯度来调整参数。

def train_loop(dataloader, model, loss_fn, optimizer):
    '''训练循环'''
    size = len(dataloader.dataset)
    for batch, (X, y) in enumerate(dataloader):
        X = X.to(device)
        y = y.to(device)
        # 计算估计值与损失
        pred = model(X)
        loss = loss_fn(pred, y)

        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

(2) 验证/测试循环(The Validation/Test Loop):迭代测试数据集,检查模型性能是否正在改善。


def test_loop(dataloader, model, loss_fn):
    '''测试循环'''
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, correct = 0, 0

    with torch.no_grad():  
        for X, y in dataloader:
            X = X.to(device)
            y = y.to(device)
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()

    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {(100 * correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")

让我们简单地熟悉一下上文训练循环中使用的一些概念。

损失函数

当输入一些训练数据时,未经训练的网络可能无法输出正确的答案。损失函数衡量估计值与目标值的差距,我们希望在训练过程中最小化损失。为了计算损失,我们使用给定数据样本作为输入进行预测,并将其与真实数据标签值进行比较。

常见的损失函数包括回归任务的nn.MSELoss(均方误差)和用于分类的 nn.NLLLoss(负对数似然)。nn.CrossEntropyLossnn.LogSoftmaxnn.NLLLoss合成。(在后续文章再详细介绍。)

我们将模型的输出逻辑传递给nn.CrossEntropyLoss,它将规范化logits(模型的输出)并计算预测误差。

loss_fn = nn.CrossEntropyLoss()

优化器

优化是在每个训练步骤中调整模型参数以减少模型误差的过程。优化算法指定如何执行该过程(在本例中,我们使用随机梯度下降)。所有优化逻辑都封装在优化器对象中。这里,我们使用SGD优化器;此外,Pytorch中有许多不同的优化器,如Adam和RMSProp。(在后续文章再详细介绍。)

我们通过传递所需要训练的模型参数和学习率参数来初始化优化器。

optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

完整实现

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda

device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)

# ======================= 数据 =======================
training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor()
)

test_data = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor()
)

train_dataloader = DataLoader(training_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)


# ======================= 模型 =======================
class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()

        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28 * 28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = x.flatten(1)
        logits = self.linear_relu_stack(x)
        return logits


def train_loop(dataloader, model, loss_fn, optimizer):
    '''训练循环'''
    size = len(dataloader.dataset)
    for batch, (X, y) in enumerate(dataloader):
        X = X.to(device)
        y = y.to(device)
        # 计算估计值与损失
        pred = model(X)
        loss = loss_fn(pred, y)

        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

def test_loop(dataloader, model, loss_fn):
    '''测试循环'''
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, correct = 0, 0

    with torch.no_grad():
        for X, y in dataloader:
            X = X.to(device)
            y = y.to(device)
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()

    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {(100 * correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")

# 超参数 
learning_rate = 1e-3
batch_size = 64
epochs = 10

# 模型实例
model = NeuralNetwork().to(device)
# 损失函数实例
loss_fn = nn.CrossEntropyLoss()
# 优化器实例
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

for t in range(epochs):
    print(f"Epoch {t + 1}\n-------------------------------")
    train_loop(train_dataloader, model, loss_fn, optimizer)
    test_loop(test_dataloader, model, loss_fn)
print("Done!")

参考:
[1] https://pytorch.org/tutorials/beginner/basics/optimization_tutorial.html

相关文章
|
3天前
|
机器学习/深度学习 自然语言处理 PyTorch
【PyTorch实战演练】基于AlexNet的预训练模型介绍
【PyTorch实战演练】基于AlexNet的预训练模型介绍
99 0
|
3天前
|
机器学习/深度学习 关系型数据库 MySQL
大模型中常用的注意力机制GQA详解以及Pytorch代码实现
GQA是一种结合MQA和MHA优点的注意力机制,旨在保持MQA的速度并提供MHA的精度。它将查询头分成组,每组共享键和值。通过Pytorch和einops库,可以简洁实现这一概念。GQA在保持高效性的同时接近MHA的性能,是高负载系统优化的有力工具。相关论文和非官方Pytorch实现可进一步探究。
132 4
|
3天前
|
PyTorch 算法框架/工具 异构计算
pytorch 模型保存与加载
pytorch 模型保存与加载
6 0
|
3天前
|
PyTorch 算法框架/工具 Python
【pytorch框架】对模型知识的基本了解
【pytorch框架】对模型知识的基本了解
|
3天前
|
机器学习/深度学习 算法 PyTorch
PyTorch模型优化与调优:正则化、批归一化等技巧
【4月更文挑战第18天】本文探讨了PyTorch中提升模型性能的优化技巧,包括正则化(L1/L2正则化、Dropout)、批归一化、学习率调整策略和模型架构优化。正则化防止过拟合,Dropout提高泛化能力;批归一化加速训练并提升性能;学习率调整策略动态优化训练效果;模型架构优化涉及网络结构和参数的调整。这些方法有助于实现更高效的深度学习模型。
|
3天前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch与迁移学习:利用预训练模型提升性能
【4月更文挑战第18天】PyTorch支持迁移学习,助力提升深度学习性能。预训练模型(如ResNet、VGG)在大规模数据集(如ImageNet)训练后,可在新任务中加速训练,提高准确率。通过选择模型、加载预训练权重、修改结构和微调,可适应不同任务需求。迁移学习节省资源,但也需考虑源任务与目标任务的相似度及超参数选择。实践案例显示,预训练模型能有效提升小数据集上的图像分类任务性能。未来,迁移学习将继续在深度学习领域发挥重要作用。
|
3天前
|
机器学习/深度学习 PyTorch 调度
PyTorch进阶:模型保存与加载,以及断点续训技巧
【4月更文挑战第17天】本文介绍了PyTorch中模型的保存与加载,以及断点续训技巧。使用`torch.save`和`torch.load`可保存和加载模型权重和状态字典。保存模型时,可选择仅保存轻量级的状态字典或整个模型对象。加载时,需确保模型结构与保存时一致。断点续训需保存训练状态,包括epoch、batch index、optimizer和scheduler状态。中断后,加载这些状态以恢复训练,节省时间和资源。
|
3天前
|
机器学习/深度学习 数据采集 PyTorch
构建你的第一个PyTorch神经网络模型
【4月更文挑战第17天】本文介绍了如何使用PyTorch构建和训练第一个神经网络模型。首先,准备数据集,如MNIST。接着,自定义神经网络模型`SimpleNet`,包含两个全连接层和ReLU激活函数。然后,定义交叉熵损失函数和SGD优化器。训练模型涉及多次迭代,计算损失、反向传播和参数更新。最后,测试模型性能,计算测试集上的准确率。这是一个基础的深度学习入门示例,为进一步探索复杂项目打下基础。
|
3天前
|
机器学习/深度学习 PyTorch 算法框架/工具
Python中用PyTorch机器学习神经网络分类预测银行客户流失模型
Python中用PyTorch机器学习神经网络分类预测银行客户流失模型
|
3天前
|
PyTorch 算法框架/工具 Python
Pytorch构建网络模型时super(__class__, self).__init__()的作用
Pytorch构建网络模型时super(__class__, self).__init__()的作用
14 0