主页 > 互联网  > 

《深度学习》——调整学习率和保存使用最优模型

《深度学习》——调整学习率和保存使用最优模型
调整学习率

在使用 PyTorch 进行深度学习训练时,调整学习率是一个重要的技巧,合适的学习率调整策略可以帮助模型更好地收敛。 PyTorch 提供了多种调整学习率的方法,下面将详细介绍几种常见的学习率调整策略及实例代码:

torch.optim.lr_scheduler.StepLR(固定步长学习率调度器) StepLR 是一种简单的学习率调整策略,它会每隔一定的训练步数(epoch)将学习率乘以一个固定的衰减因子。

import torch import torch.nn as nn import torch.optim as optim from torch.optim.lr_scheduler import StepLR # 定义一个简单的模型 class SimpleModel(nn.Module): def __init__(self): super(SimpleModel, self).__init__() self.fc = nn.Linear(10, 1) def forward(self, x): return self.fc(x) model = SimpleModel() optimizer = optim.SGD(model.parameters(), lr=0.1) # 定义 StepLR 调度器,每 3 个 epoch 将学习率乘以 0.1 scheduler = StepLR(optimizer, step_size=3, gamma=0.1) # 模拟训练过程 for epoch in range(10): # 训练代码... print(f'Epoch {epoch}: Learning rate = {optimizer.param_groups[0]["lr"]}') optimizer.step() scheduler.step()

torch.optim.lr_scheduler.MultiStepLR(多步学习率调度器) MultiStepLR 允许你在指定的训练步数(epoch)处将学习率乘以一个固定的衰减因子。 import torch import torch.nn as nn import torch.optim as optim from torch.optim.lr_scheduler import MultiStepLR model = SimpleModel() optimizer = optim.SGD(model.parameters(), lr=0.1) # 定义 MultiStepLR 调度器,在 epoch 为 3 和 7 时将学习率乘以 0.1 milestones = [3, 7] scheduler = MultiStepLR(optimizer, milestones=milestones, gamma=0.1) # 模拟训练过程 for epoch in range(10): # 训练代码... print(f'Epoch {epoch}: Learning rate = {optimizer.param_groups[0]["lr"]}') optimizer.step() scheduler.step()

torch.optim.lr_scheduler.ExponentialLR(指数学习率调度器) ExponentialLR 会在每个训练步数(epoch)将学习率乘以一个固定的衰减因子。 import torch import torch.nn as nn import torch.optim as optim from torch.optim.lr_scheduler import ExponentialLR model = SimpleModel() optimizer = optim.SGD(model.parameters(), lr=0.1) # 定义 ExponentialLR 调度器,每个 epoch 将学习率乘以 0.9 scheduler = ExponentialLR(optimizer, gamma=0.9) # 模拟训练过程 for epoch in range(10): # 训练代码... print(f'Epoch {epoch}: Learning rate = {optimizer.param_groups[0]["lr"]}') optimizer.step() scheduler.step()

torch.optim.lr_scheduler.ReduceLROnPlateau(自适应学习率调度器) ReduceLROnPlateau 会根据验证集上的指标(如损失值)来动态调整学习率。当指标在一定的训练步数内没有改善时,它会将学习率乘以一个固定的衰减因子。 import torch import torch.nn as nn import torch.optim as optim from torch.optim.lr_scheduler import ReduceLROnPlateau model = SimpleModel() optimizer = optim.SGD(model.parameters(), lr=0.1) # 定义 ReduceLROnPlateau 调度器,当验证损失在 2 个 epoch 内没有改善时,将学习率乘以 0.1 scheduler = ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=2) # 模拟训练过程 for epoch in range(10): # 训练代码... # 假设这是验证集上的损失 val_loss = torch.rand(1).item() print(f'Epoch {epoch}: Learning rate = {optimizer.param_groups[0]["lr"]}') optimizer.step() scheduler.step(val_loss)

保存最优模型

在深度学习训练过程中,保存最优模型是一个常见的需求,这样可以在训练结束后使用表现最好的模型进行预测或评估。通常,我们会根据验证集上的某个指标(如准确率、损失值等)来判断模型是否为最优。

保存模型的状态字典(state_dict)到文件 best.pth 中。保存整个模型对象到文件 best1.pt 中。 if correct > best_acc: # 如果当前正确预测的样本数量大于之前记录的最优值 best_acc = correct # 更新最优准确率记录为当前的正确样本数量 print(model.state_dict().keys()) # 打印模型状态字典中的所有键,这些键代表了模型中可学习参数的名称, # 例如各个层的权重(weight)和偏置(bias)等 torch.save(model.state_dict(), 'best.pth') # 将模型的状态字典保存到名为 'best.pth' 的文件中。 # 状态字典包含了模型中所有可学习参数的值,这种保存方式只保存参数,不保存模型结构, # 后续加载时需要先定义相同结构的模型,再加载参数 torch.save(model, 'best1.pt') # 将整个模型对象保存到名为 'best1.pt' 的文件中。 # 这种保存方式不仅保存了模型的参数,还保存了模型的结构信息, # 后续加载时可以直接加载整个模型对象 注意 保存状态字典与保存整个模型的区别 保存状态字典(torch.save(model.state_dict(), ‘best.pth’)): 优点:文件体积相对较小,适合在不同环境下共享模型参数,因为只需要模型结构定义代码一致,就可以加载参数。缺点:需要手动定义模型结构,再加载参数。如果模型结构发生变化,可能会导致加载失败。 保存整个模型(torch.save(model, ‘best1.pt’)): 优点:加载方便,直接加载整个模型对象,不需要重新定义模型结构。缺点:文件体积较大,并且依赖于保存时的 Python 环境和 PyTorch 版本,在不同环境下加载可能会出现兼容性问题。 准确率指标的选择 代码中使用 correct(正确预测的样本数量)作为判断模型优劣的指标,在实际应用中,更常见的做法是使用准确率(correct / total),因为 correct 的数值会受到验证集样本数量的影响,而准确率是一个相对稳定的指标。 文件路径管理 代码中直接使用相对路径保存模型文件,在实际项目中,建议使用绝对路径或者更规范的文件路径管理方式,避免文件保存位置混乱。 使用最优模型 使用best.pth 中的状态字典(state_dict) 。使用best1.pt 中的模型对象 。 # 尝试从 'best.pth' 文件中加载模型的状态字典(state_dict), # 状态字典包含了模型中所有可学习参数(如权重、偏置)的值, # 但不包含模型的结构信息。所以在使用此方式加载前, # 必须先定义好与保存时结构一致的模型实例。 # torch.load('best.pth') 用于从文件中读取状态字典数据, # model.load_state_dict() 方法将读取到的状态字典数据赋值给当前的 model 实例。 model.load_state_dict(torch.load('best.pth')) # 这行代码会直接从 'best.pt' 文件中加载整个模型对象, # 该文件保存时使用了 torch.save(model, 'best.pt') 方式, # 这种保存方式不仅保存了模型的参数,还保存了模型的结构信息。 # 加载后,model 变量将指向一个完整的、可直接使用的模型对象。 # 不过需要注意的是,如果之前使用的 Python 环境、PyTorch 版本不同, # 或者模型定义代码发生了变化,可能会导致加载失败或出现兼容性问题。 # 并且这行代码与上一行 'model.load_state_dict(...)' 存在冲突, # 因为这里会覆盖掉上一行代码对 model 实例参数的加载结果, # 通常在实际使用中只会选择其中一种加载方式。 model = torch.load('best.pt') # 将模型设置为评估模式。在评估模式下, # 一些在训练时起作用的特殊层(如 Dropout、BatchNorm 等) # 会改变其行为。例如,Dropout 层在训练时会随机丢弃部分神经元以防止过拟合, # 但在评估时会正常使用所有神经元;BatchNorm 层在训练时会根据当前批次的数据 # 计算均值和方差,而在评估时会使用训练过程中统计的全局均值和方差。 # 因此,在进行模型推理、验证或测试时,需要将模型设置为评估模式, # 以确保得到准确的结果。 model.eval() 实例

数据集:照片文件:

test.txt:

train.txt:

test_true.txt:

保存最优模型

对食物分类中food dataset2目录下的test、train中的照片进行卷积神经训练,进行食物分类并保存最优模型,并调整学习率。 代码:

import os from PIL import Image # 定义函数用于生成训练集和测试集的文件列表及对应的标签 def train_test_file(root, dir): # 打开一个以dir命名的txt文件,用于写入图像路径和标签 file_txt = open(dir + '.txt', 'w') # 拼接完整的路径 path = os.path.join(root, dir) # 遍历指定路径下的所有文件和文件夹 for roots, directories, files in os.walk(path): # os.list_dir() # 如果存在子文件夹,将子文件夹名称存储在dirs列表中 if len(directories) != 0: dirs = directories else: # 获取当前文件夹的名称 now_dir = roots.split('\\') # 遍历当前文件夹下的所有文件 for file in files: # 拼接图像文件的完整路径 path_1 = os.path.join(roots, file) print(path_1) # 将图像路径和对应的标签写入txt文件,标签为当前文件夹在dirs列表中的索引 file_txt.write(path_1 + ' ' + str(dirs.index(now_dir[-1])) + '\n') # 关闭文件 file_txt.close() # 数据集根目录 root = r'.\食物分类\food_dataset' # 训练集文件夹名称 train_dir = 'train' # 测试集文件夹名称 test_dir = 'test' # 生成训练集的文件列表及标签 train_test_file(root, train_dir) # 生成测试集的文件列表及标签 train_test_file(root, test_dir) # 自定义类,用于演示__getitem__和__len__方法 class USE_getitem(): def __init__(self, text): # 初始化传入的文本 self.text = text def __getitem__(self, index): # 获取指定索引位置的字符并转换为大写 result = self.text[index].upper() return result def __len__(self): # 返回文本的长度 return len(self.text) # 创建USE_getitem类的实例 p = USE_getitem('pytorch') # 打印索引为0和1的字符 print(p[0], p[1]) # 调用__len__方法获取文本长度 len(p) import torch from torch.utils.data import Dataset, DataLoader import numpy as np from torchvision import transforms from torch import nn # 定义训练集和验证集的数据预处理转换 data_transforms = { 'train': transforms.Compose([ # 将图像大小调整为300x300 transforms.Resize([300, 300]), # 随机旋转图像,旋转角度范围为-45到45度 transforms.RandomRotation(45), # 从图像中心裁剪出256x256的区域 transforms.CenterCrop(256), # 以0.5的概率随机水平翻转图像 transforms.RandomHorizontalFlip(p=0.5), # 以0.5的概率随机垂直翻转图像 transforms.RandomVerticalFlip(p=0.5), # 随机调整图像的亮度、对比度、饱和度和色相 transforms.ColorJitter(brightness=0.2, contrast=0.1, saturation=0.1, hue=0.1), # 以0.1的概率将图像转换为灰度图 transforms.RandomGrayscale(p=0.1), # 将图像转换为Tensor transforms.ToTensor(), # 对图像进行归一化处理 transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]), 'valid': transforms.Compose([ # 将图像大小调整为256x256 transforms.Resize([256, 256]), # 将图像转换为Tensor transforms.ToTensor(), # 对图像进行归一化处理 transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) } # 自定义数据集类,继承自torch.utils.data.Dataset class food_dataset(Dataset): def __init__(self, file_path, transform=None): # 初始化文件路径 self.file_path = file_path # 用于存储图像路径的列表 self.imgs = [] # 用于存储图像标签的列表 self.labels = [] # 初始化数据预处理转换 self.transform = transform # 打开文件并读取每一行 with open(self.file_path) as f: # 将每一行按空格分割成图像路径和标签 samples = [x.strip().split(' ') for x in f.readlines()] for img_path, label in samples: # 将图像路径添加到imgs列表中 self.imgs.append(img_path) # 图像路径 # 将标签添加到labels列表中 self.labels.append(label) # 标签 def __len__(self): # 返回图像的数量 return len(self.imgs) def __getitem__(self, idx): # 打开指定索引位置的图像 image = Image.open(self.imgs[idx]) # 如果存在数据预处理转换,对图像进行转换 if self.transform: image = self.transform(image) # 获取指定索引位置的标签 label = self.labels[idx] # 将标签转换为torch.Tensor类型 label = torch.from_numpy(np.array(label, dtype=np.int64)) return image, label # 创建训练集数据集对象 training_data = food_dataset(file_path='./train.txt', transform=data_transforms['train']) # 创建测试集数据集对象 test_data = food_dataset(file_path='./test.txt', transform=data_transforms['valid']) # 创建训练集数据加载器,批量大小为64,数据打乱 train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True) # 创建测试集数据加载器,批量大小为64,数据打乱 test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True) # 判断是否支持GPU或MPS,如果支持则使用,否则使用CPU device = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu' print(f'Using {device} device') # 定义卷积神经网络类,继承自torch.nn.Module class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() # 第一个卷积块 self.conv_block1 = nn.Sequential( # 输入通道数为3,输出通道数为32,卷积核大小为3,填充为1 nn.Conv2d(3, 32, kernel_size=3, padding=1), # 批量归一化 nn.BatchNorm2d(32), # ReLU激活函数 nn.ReLU(inplace=True), # 最大池化层,池化核大小为2 nn.MaxPool2d(2) ) # 第二个卷积块 self.conv_block2 = nn.Sequential( nn.Conv2d(32, 64, kernel_size=3, padding=1), nn.BatchNorm2d(64), nn.ReLU(inplace=True), nn.MaxPool2d(2) ) # 第三个卷积块 self.conv_block3 = nn.Sequential( nn.Conv2d(64, 128, kernel_size=3, padding=1), nn.BatchNorm2d(128), nn.ReLU(inplace=True), nn.MaxPool2d(2) ) # 第四个卷积块 self.conv_block4 = nn.Sequential( nn.Conv2d(128, 256, kernel_size=3, padding=1), nn.BatchNorm2d(256), nn.ReLU(inplace=True), nn.MaxPool2d(2) ) # 第五个卷积块 self.conv_block5 = nn.Sequential( nn.Conv2d(256, 512, kernel_size=3, padding=1), nn.BatchNorm2d(512), nn.ReLU(inplace=True), nn.MaxPool2d(2) ) # 计算经过卷积和池化后特征图的尺寸 # 每次池化操作将尺寸缩小一半,经过5次池化,256 / 2^5 = 8 self.fc1 = nn.Linear(512 * 8 * 8, 2048) self.relu = nn.ReLU(inplace=True) # 随机丢弃50%的神经元,防止过拟合 self.dropout = nn.Dropout(0.5) # 输出层,输出20个类别 self.fc2 = nn.Linear(2048, 20) def forward(self, x): # 前向传播,依次通过各个卷积块 x = self.conv_block1(x) x = self.conv_block2(x) x = self.conv_block3(x) x = self.conv_block4(x) x = self.conv_block5(x) # 将多维的特征图展平为一维向量 x = x.view(-1, 512 * 8 * 8) # 通过第一个全连接层 x = self.fc1(x) x = self.relu(x) x = self.dropout(x) # 通过输出层 output = self.fc2(x) return output # 创建CNN模型实例并将其移动到指定设备上 model = CNN().to(device) # 定义训练函数 def train(dataloader, model, loss_fn, optimizer): # 将模型设置为训练模式 model.train() # 记录当前批次的编号 batch_size_num = 1 # 遍历数据加载器中的每个批次 for x, y in dataloader: # 其中batch为每一个数据的编号 # 将训练数据和标签移动到指定设备上 x, y = x.to(device), y.to(device) # 前向传播,计算模型的预测结果 pred = model.forward(x) # 通过交叉熵损失函数计算损失值 loss = loss_fn(pred, y) # 梯度值清零 optimizer.zero_grad() # 反向传播计算每一个参数的梯度值 loss.backward() # 根据梯度更新网络参数 optimizer.step() # 从tensor数据中提取损失值 loss_value = loss.item() # 每10个批次打印一次损失值 if batch_size_num % 10 == 0: print(f'loss:{loss_value:7f} [number:{batch_size_num}]') # 批次编号加1 batch_size_num += 1 # 记录最佳准确率 best_acc = 0 # 定义测试函数 def test(dataloader, model, loss_fn): global best_acc # 数据集的总样本数 size = len(dataloader.dataset) # 数据加载器中的批次数量 num_batches = len(dataloader) # 将模型设置为评估模式 model.eval() # 初始化测试损失和正确预测的样本数 test_loss, correct = 0, 0 # 关闭梯度计算 with torch.no_grad(): for x, y in dataloader: # 将测试数据和标签移动到指定设备上 x, y = x.to(device), y.to(device) # 前向传播,计算模型的预测结果 pred = model.forward(x) # 累加每个批次的损失值 test_loss += loss_fn(pred, y).item() # 计算正确预测的样本数 correct += (pred.argmax(1) == y).type(torch.float).sum().item() a = (pred.argmax(1) == y) # dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值对应的索引号 b = (pred.argmax(1) == y).type(torch.float) # 计算平均测试损失 test_loss /= num_batches # 计算平均准确率 correct /= size # 如果当前准确率高于最佳准确率,更新最佳准确率并保存模型 if correct > best_acc: best_acc = correct print(model.state_dict().keys()) # 保存模型的参数 torch.save(model.state_dict(), 'best.pth') # 保存整个模型 torch.save(model, 'best1.pt') print(f'Test result: \n Accuracy:{(100 * correct)}%,Avg loss:{test_loss}') # 创建交叉熵损失函数对象 loss_fn = nn.CrossEntropyLoss() # 创建Adam优化器,用于更新模型参数 optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # 训练的轮数 epochs = 150 # 循环训练多个轮次 for t in range(epochs): print(f'epoch{t + 1}\n--------------------') # 训练模型 train(train_dataloader, model, loss_fn, optimizer) # 测试模型 test(test_dataloader, model, loss_fn) print('Done!')

保存模型:

使用最优模型

对数据中的测试数据进行测试训练,路径文件为test_true.txt。

from PIL import Image import torch from torch.utils.data import Dataset, DataLoader import numpy as np from torchvision import transforms from torch import nn # 定义数据预处理转换,这里只定义了验证集的转换 data_transforms = { 'valid': transforms.Compose([ # 将图像调整为 256x256 的大小 transforms.Resize([256, 256]), # 将图像转换为 PyTorch 的张量 transforms.ToTensor(), # 对图像进行归一化处理,使用 ImageNet 的均值和标准差 transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) } # 自定义食物数据集类,继承自 torch.utils.data.Dataset class food_dataset(Dataset): def __init__(self, file_path, transform=None): # 保存数据集文件路径 self.file_path = file_path # 用于存储图像路径的列表 self.imgs = [] # 用于存储图像标签的列表 self.labels = [] # 保存数据预处理转换 self.transform = transform # 打开数据集文件 with open(self.file_path) as f: # 读取文件的每一行,并按空格分割成图像路径和标签 samples = [x.strip().split(' ') for x in f.readlines()] for img_path, label in samples: # 将图像路径添加到 imgs 列表中 self.imgs.append(img_path) # 将标签添加到 labels 列表中 self.labels.append(label) def __len__(self): # 返回数据集的长度,即图像的数量 return len(self.imgs) def __getitem__(self, idx): # 打开指定索引的图像 image = Image.open(self.imgs[idx]) # 如果存在数据预处理转换,则对图像进行转换 if self.transform: image = self.transform(image) # 获取指定索引的标签 label = self.labels[idx] # 将标签转换为 PyTorch 的张量 label = torch.from_numpy(np.array(label, dtype=np.int64)) # 返回图像和标签 return image, label # 判断是否支持 GPU 或 MPS,如果支持则使用,否则使用 CPU device = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu' print(f'Using {device} device') # 定义卷积神经网络类,继承自 torch.nn.Module class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() # 第一个卷积块 self.conv_block1 = nn.Sequential( # 输入通道数为 3,输出通道数为 32,卷积核大小为 3,填充为 1 nn.Conv2d(3, 32, kernel_size=3, padding=1), # 批量归一化层 nn.BatchNorm2d(32), # ReLU 激活函数 nn.ReLU(inplace=True), # 最大池化层,池化核大小为 2 nn.MaxPool2d(2) ) # 第二个卷积块 self.conv_block2 = nn.Sequential( nn.Conv2d(32, 64, kernel_size=3, padding=1), nn.BatchNorm2d(64), nn.ReLU(inplace=True), nn.MaxPool2d(2) ) # 第三个卷积块 self.conv_block3 = nn.Sequential( nn.Conv2d(64, 128, kernel_size=3, padding=1), nn.BatchNorm2d(128), nn.ReLU(inplace=True), nn.MaxPool2d(2) ) # 第四个卷积块 self.conv_block4 = nn.Sequential( nn.Conv2d(128, 256, kernel_size=3, padding=1), nn.BatchNorm2d(256), nn.ReLU(inplace=True), nn.MaxPool2d(2) ) # 第五个卷积块 self.conv_block5 = nn.Sequential( nn.Conv2d(256, 512, kernel_size=3, padding=1), nn.BatchNorm2d(512), nn.ReLU(inplace=True), nn.MaxPool2d(2) ) # 全连接层的输入维度,经过 5 次池化后,特征图大小为 8x8,通道数为 512 self.fc1 = nn.Linear(512 * 8 * 8, 2048) # ReLU 激活函数 self.relu = nn.ReLU(inplace=True) # Dropout 层,防止过拟合 self.dropout = nn.Dropout(0.5) # 输出层,输出 20 个类别 self.fc2 = nn.Linear(2048, 20) def forward(self, x): # 依次通过各个卷积块 x = self.conv_block1(x) x = self.conv_block2(x) x = self.conv_block3(x) x = self.conv_block4(x) x = self.conv_block5(x) # 将多维的特征图展平为一维向量 x = x.view(-1, 512 * 8 * 8) # 通过第一个全连接层 x = self.fc1(x) # 通过 ReLU 激活函数 x = self.relu(x) # 通过 Dropout 层 x = self.dropout(x) # 通过输出层 output = self.fc2(x) return output # 创建 CNN 模型实例,并将其移动到指定设备上 model = CNN().to(device) # 加载之前保存的模型参数 model.load_state_dict(torch.load('best.pth')) # 也可以直接加载整个模型 # model = torch.load('best.pt') # 将模型设置为评估模式 model.eval() # 创建测试数据集实例 test_data = food_dataset(file_path='test_true.txt', transform=data_transforms['valid']) # 创建测试数据加载器,批量大小为 1,数据打乱 test_dataloader = DataLoader(test_data, batch_size=1, shuffle=True) # 用于存储模型的预测结果 result = [] # 用于存储真实标签 lables = [] # 定义测试函数,用于获取每个样本的预测结果和真实标签 def test_true(dataloader, model): # 关闭梯度计算,减少内存消耗 with torch.no_grad(): for x, y in dataloader: # 将输入数据和标签移动到指定设备上 x, y = x.to(device), y.to(device) # 进行前向传播,得到模型的预测结果 pred = model.forward(x) # 获取预测结果中概率最大的类别索引,并添加到 result 列表中 result.append(pred.argmax(1).item()) # 获取真实标签,并添加到 lables 列表中 lables.append(y.item()) # 调用测试函数 test_true(test_dataloader, model) # 打印模型的预测结果 print('预测值:\t', result) # 打印真实标签 print('真实值:\t', lables) # 定义测试函数,用于计算模型的准确率和平均损失 def test(dataloader, model, loss_fn): global best_acc # 数据集的总样本数 size = len(dataloader.dataset) # 数据加载器中的批次数量 num_batches = len(dataloader) # 将模型设置为评估模式 model.eval() # 初始化测试损失和正确预测的样本数 test_loss, correct = 0, 0 # 关闭梯度计算,减少内存消耗 with torch.no_grad(): for x, y in dataloader: # 将输入数据和标签移动到指定设备上 x, y = x.to(device), y.to(device) # 进行前向传播,得到模型的预测结果 pred = model.forward(x) # 计算当前批次的损失,并累加到 test_loss 中 test_loss += loss_fn(pred, y).item() # 统计正确预测的样本数 correct += (pred.argmax(1) == y).type(torch.float).sum().item() a = (pred.argmax(1) == y) # dim=1 表示每一行中的最大值对应的索引号,dim=0 表示每一列中的最大值对应的索引号 b = (pred.argmax(1) == y).type(torch.float) # 计算平均测试损失 test_loss /= num_batches # 计算准确率 correct /= size # 打印测试结果 print(f'Test result: \n Accuracy:{(100 * correct)}%,Avg loss:{test_loss}') # 创建交叉熵损失函数实例 loss_fn = nn.CrossEntropyLoss() # 创建 Adam 优化器实例 optimizer = torch.optim.Adam(model.parameters(), lr=0.0001) # 调用测试函数,计算模型的准确率和平均损失 test(test_dataloader, model, loss_fn)

标签:

《深度学习》——调整学习率和保存使用最优模型由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“《深度学习》——调整学习率和保存使用最优模型