Pytorch深度学习全流程代码框架——Base Codes for Deep Learning Using Pytorch
# 导入必要的库 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, Dataset # 定义超参数 epochs = 10 # 训练轮数 lr = 0.01 # 学习率 batch_size = 64 # 批量大小 # 定义数据集和数据加载器 class MyDataset(Dataset): def __init__(self): # 加载数据,预处理数据,划分训练集和测试集等操作 pass def __getitem__(self, index): # 返回第index个样本的数据和标签 pass def __len__(self): # 返回数据集的大小 pass train_dataset = MyDataset() # 创建训练集对象 train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) # 创建训练集数据加载器 test_dataset = MyDataset() # 创建测试集对象 test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False) # 创建测试集数据加载器 # 定义模型 class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() # 定义模型的结构,如卷积层,全连接层等 pass def forward(self, x): # 定义模型的前向传播,即如何根据输入x计算输出 pass model = MyModel() # 创建模型对象 model.to(device) # 将模型移动到指定设备,如GPU # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() # 定义交叉熵损失函数,适用于多分类问题 optimizer = optim.SGD(model.parameters(), lr=lr) # 定义随机梯度下降优化器 # 训练模型 for epoch in range(epochs): model.train() # 将模型设置为训练模式,启用诸如Dropout和BatchNorm等层的功能 train_loss = 0.0 # 记录训练集的累计损失 train_acc = 0.0 # 记录训练集的累计准确率 for i, (inputs, labels) in enumerate(train_loader): # 遍历训练集的每个批次 inputs = inputs.to(device) # 将输入数据移动到指定设备 labels = labels.to(device) # 将标签数据移动到指定设备 optimizer.zero_grad() # 将优化器中的梯度清零 outputs = model(inputs) # 将输入数据喂入模型,得到输出 loss = criterion(outputs, labels) # 根据输出和标签计算损失 loss.backward() # 反向传播计算梯度 optimizer.step() # 根据梯度更新参数 train_loss += loss.item() * inputs.size(0) # 累加批次的损失 _, preds = torch.max(outputs, 1) # 根据输出得到预测类别 train_acc += torch.sum(preds == labels).item() # 累加批次的正确预测数 train_loss = train_loss / len(train_dataset) # 计算训练集的平均损失 train_acc = train_acc / len(train_dataset) # 计算训练集的平均准确率 print(f'Epoch {epoch+1}, Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f}') # 打印训练结果 # 测试模型 model.eval() # 将模型设置为评估模式,关闭诸如Dropout和BatchNorm等层的功能 test_loss = 0.0 # 记录测试集的累计损失 test_acc = 0.0 # 记录测试集的累计准确率 with torch.no_grad(): # 关闭梯度计算,节省内存,加快速度 for inputs, labels in test_loader: # 遍历测试集的每个批次 inputs = inputs.to(device) # 将输入数据移动到指定设备 labels = labels.to(device) # 将标签数据移动到指定设备 outputs = model(inputs) # 将输入数据喂入模型,得到输出 loss = criterion(outputs, labels) # 根据输出和标签计算损失 test_loss += loss.item() * inputs.size(0) # 累加批次的损失 _, preds = torch.max(outputs, 1) # 根据输出得到预测类别 test_acc += torch.sum(preds == labels).item() # 累加批次的正确预测数 test_loss = test_loss / len(test_dataset) # 计算测试集的平均损失 test_acc = test_acc / len(test_dataset) # 计算测试集的平均准确率 print(f'Test Loss: {test_loss:.4f}, Test Acc: {test_acc:.4f}') # 打印测试结果 # 绘图 import matplotlib.pyplot as plt plt.plot(train_loss, label='Train Loss') # 绘制训练集损失曲线 plt.plot(valid_loss, label='Valid Loss') # 绘制验证集损失曲线 plt.xlabel('Iterations') # 设置x轴标签 plt.ylabel('Loss') # 设置y轴标签 plt.legend() # 显示图例 plt.show() # 显示图像 plt.plot(train_acc, label='Train Acc') # 绘制训练集准确率曲线 plt.plot(valid_acc, label='Valid Acc') # 绘制验证集准确率曲线 plt.xlabel('Iterations') # 设置x轴标签 plt.ylabel('Accuracy') # 设置y轴标签 plt.legend() # 显示图例 plt.show() # 显示图像
DataLoader:
# 定义数据集和数据加载器 class MyDataset(Dataset): def __init__(self): # 加载数据,预处理数据,划分训练集和测试集等操作 # 假设数据集路径是'~/dataset' # 假设数据集是MNIST手写数字识别,每个样本是28x28的灰度图像,标签是0-9的数字 # 假设数据集已经分为train.csv和test.csv两个文件,每行是一个样本,第一个元素是标签,后面是784个像素值 import pandas as pd from sklearn.model_selection import train_test_split data = pd.read_csv('~/dataset/train.csv') # 读取训练集文件 X = data.iloc[:, 1:].values # 获取特征矩阵,即像素值 y = data.iloc[:, 0].values # 获取标签向量,即数字类别 X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=42) # 划分训练集和验证集 self.X = X_train / 255.0 # 归一化处理,将像素值映射到[0,1]区间 self.y = y_train # 获取训练集标签 self.X_valid = X_valid / 255.0 # 归一化处理,将像素值映射到[0,1]区间 self.y_valid = y_valid # 获取验证集标签 def __getitem__(self, index): # 返回第index个样本的数据和标签 if self.flag == 'train': # 如果是训练集 return torch.from_numpy(self.X[index]).view(1, 28, 28), torch.tensor(self.y[index]) # 将numpy数组转换为torch张量,并将图像reshape为1x28x28的形式 elif self.flag == 'valid': # 如果是验证集 return torch.from_numpy(self.X_valid[index]).view(1, 28, 28), torch.tensor(self.y_valid[index]) # 将numpy数组转换为torch张量,并将图像reshape为1x28x28的形式 def __len__(self): # 返回数据集的大小 if self.flag == 'train': # 如果是训练集 return len(self.X) # 返回训练集的大小 elif self.flag == 'valid': # 如果是验证集 return len(self.X_valid) # 返回验证集的大小 train_dataset = MyDataset(flag='train') # 创建训练集对象 train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) # 创建训练集数据加载器 valid_dataset = MyDataset(flag='valid') # 创建验证集对象 valid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=False) # 创建验证集数据加载器
模型保存和加载:
'''一种是保存和加载整个模型,包括模型的结构和参数。这种方法的优点是可以直接使用加载的模型进行预测或继续训练,无需重新定义模型的结构。缺点是保存的文件较大,且可能存在版本兼容性的问题。 保存整个模型的代码如下:''' torch. Save(model, PATH) # model是要保存的模型对象,PATH是要保存的文件路径 # 加载整个模型的代码如下: model = torch.load(PATH) # PATH是要加载的文件路径,model是加载后的模型对象
'''另一种是保存和加载模型的状态字典(state_dict),即模型的参数张量。这种方法的优点是保存的文件较小,且不依赖于特定的模型结构。缺点是需要先定义好模型的结构,然后再加载状态字典。 保存模型的状态字典的代码如下:''' torch. Save(model.state_dict(), PATH) # model是要保存的模型对象,PATH是要保存的文件路径 # 加载模型的状态字典的代码如下: model = TheModelClass(*args, **kwargs) # 先定义好模型的结构,TheModelClass是模型类,*args和**kwargs是初始化参数 model.load_state_dict(torch.load(PATH)) # 加载状态字典,PATH是要加载的文件路径 # 一般来说,推荐使用第二种方法进行模型保存和加载
模型可视化:
''' 在pytorch中进行模型可视化的方法有多种,主要可以分为两类: 一类是可视化模型的结构,即展示模型的各个层和参数。这类方法有: 使用tensorboard,利用torch.utils.tensorboard.SummaryWriter.add_graph()方法,将模型和输入数据传入,生成模型的计算图; 使用netron,将模型保存为.pt或.pth文件,然后用netron打开,可以查看模型的层级结构和参数; 使用torchviz,利用torchviz.make_dot()方法,将模型的输出和参数传入,生成一个graphviz对象,可以保存为图片或pdf文件; 使用hiddenlayer,利用hiddenlayer.build_graph()方法,将模型和输入数据传入,生成一个hiddenlayer.Graph对象,可以保存为图片或pdf文件。 一类是可视化模型的训练过程,即展示模型的损失函数、准确率、梯度等指标的变化。这类方法有: 使用tensorboard,利用torch.utils.tensorboard.SummaryWriter.add_scalar()方法,将每个训练步骤或周期的指标值传入,生成标量曲线图; 使用hiddenlayer,利用hiddenlayer.History()和hiddenlayer.Canvas()方法,记录每个训练步骤或周期的指标值,并绘制成折线图; 使用tensorwatch,利用tensorwatch.Watcher()和tensorwatch.StreamViewer()方法,在jupyter notebook中实时监控和可视化模型的训练过程。 '''
另一个可参考代码框架(使用datasets模块,transform模块的train和test):
# 导入必要的库 import torch import torch.nn as nn import torch.optim as optim from torchvision import models, datasets, transforms # 定义超参数 num_classes = 10 # 数据集类别数 batch_size = 64 # 批量大小 num_epochs = 10 # 训练轮数 lr = 0.01 # 学习率 # 定义数据集和数据加载器 transform = transforms.Compose([ # 定义数据预处理操作 transforms.Resize(256), # 调整图像大小为256x256 transforms.CenterCrop(224), # 中心裁剪为224x224 transforms.ToTensor(), # 转换为张量 transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) # 归一化 ]) train_dataset = datasets.ImageFolder(root='data/train', transform=transform) # 创建训练集对象 train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) # 创建训练集数据加载器 test_dataset = datasets.ImageFolder(root='data/test', transform=transform) # 创建测试集对象 test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False) # 创建测试集数据加载器 # 定义模型 model = models.resnet18(pretrained=True) # 加载预训练好的resnet18模型 model.fc = nn.Linear(model.fc.in_features, num_classes) # 修改最后一层为全连接层,输出维度为num_classes # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() # 定义交叉熵损失函数,适用于多分类问题 optimizer = optim.SGD(model.parameters(), lr=lr, momentum=0.9) # 定义随机梯度下降优化器 # 训练模型 for epoch in range(num_epochs): model.train() # 将模型设置为训练模式,启用诸如Dropout和BatchNorm等层的功能 train_loss = 0.0 # 记录训练集的累计损失 train_acc = 0.0 # 记录训练集的累计准确率 for i, (inputs, labels) in enumerate(train_loader): # 遍历训练集的每个批次 optimizer.zero_grad() # 将优化器中的梯度清零 outputs = model(inputs) # 将输入数据喂入模型,得到输出 loss = criterion(outputs, labels) # 根据输出和标签计算损失 loss.backward() # 反向传播计算梯度 optimizer.step() # 根据梯度更新参数 train_loss += loss.item() * inputs.size(0) # 累加批次的损失 _, preds = torch.max(outputs, 1) # 根据输出得到预 train_acc += torch.sum(preds == labels).item() # 累加批次的正确预测数 if (i + 1) % 10 == 0: # 每10个批次打印一次训练结果 print(f'Epoch {epoch + 1}, Batch {i + 1}, Loss: {loss.item():.4f}, Acc: {torch.sum(preds == labels).item() / inputs.size(0):.4f}') train_loss = train_loss / len(train_dataset) # 计算训练集的平均损失 train_acc = train_acc / len(train_dataset) # 计算训练集的平均准确率 print(f'Epoch {epoch + 1}, Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f}') # 打印训练结果 model.eval() # 将模型设置为评估模式,关闭诸如Dropout和BatchNorm等层的功能 test_loss = 0.0 # 记录测试集的累计损失 test_acc = 0.0 # 记录测试集的累计准确率 with torch.no_grad(): # 关闭梯度计算,节省内存,加快速度 for inputs, labels in test_loader: # 遍历测试集的每个批次 outputs = model(inputs) # 将输入数据喂入模型,得到输出 loss = criterion(outputs, labels) # 根据输出和标签计算损失 test_loss += loss.item() * inputs.size(0) # 累加批次的损失 _, preds = torch.max(outputs, 1) # 根据输出得到预测类别 test_acc += torch.sum(preds == labels).item() # 累加批次的正确预测数 test_loss = test_loss / len(test_dataset) # 计算测试集的平均损失 test_acc = test_acc / len(test_dataset) # 计算测试集的平均准确率 print(f'Epoch {epoch + 1}, Test Loss: {test_loss:.4f}, Test Acc: {test_acc:.4f}') # 打印测试结果
超参的配置文件导入和运行选项的解析:
*.cfg文件如下:
[settings] name = Alice age = 25 color = blue
引入这个cfg文件的过程如下:
import configparser config = configparser.ConfigParser() config.read('settings.cfg') name = config['settings']['name'] age = config['settings']['age'] color = config['settings']['color'] print(name, age, color)
argparse的用法如下:
import argparse parser = argparse.ArgumentParser(description='A simple calculator.') parser.add_argument('x', type=float, help='the first number') parser.add_argument('y', type=float, help='the second number') parser.add_argument('operation', choices=['+', '-', '*', '/'], help='the operation') args = parser.parse_args() if args.operation == '+': result = args.x + args.y elif args.operation == '-': result = args.x - args.y elif args.operation == '*': result = args.x * args.y elif args.operation == '/': result = args.x / args.y print(result)
如果这篇文章帮助到了你,你可以请作者喝一杯咖啡