import torch
from torchvision.datasets import FashionMINST # 加载数据库,自己的数据集要更改
from torchvision import transforms
import torch.utils.data as Data
import numpy as np
import matplotlib.pyplot as plt
from model import LeNet # 导入自己写的模型
import torch.nn as nn
import time
import copy
import pandas as pd
# 定义一个加载数据集并处理的代码
def train_val_data_process():
# 把数据集加载进来,进行处理,如果是自己的数据集,要更换代码
train_data = FashionMINST(root='./data',
train=True,
transform=transforms.Compose([[transforms.Resize(size=28)], transforms.ToTensor()]),
download=True)
# 划分数据集
train_data, val_data = Data.random_split(train_data, [round(0.8*len(train_data)), round(0.2*len(train_data))])
# Dataloader是一个可迭代的数据装载器,组合了数据集和采样器,并在给定数据集上提供可迭代对象。
# 可以完成对数据集中多个对象的集成。
train_dataloader = Data.DataLoader(dataset=train_data,
batch_size=128,
shuffle=True,
num_workers=8)
val_dataloader = Data.DataLoader(dataset=val_data,
batch_size=128,
shuffle=True,
num_workers=8)
return train_dataloader, val_dataloader
# 训练模型函数 定义一些参数,把模型,训练数据、验证数据和训练轮次加载进来
def train_model_process(model, train_dataloader, val_dataloader, num_epochs):
# 设定训练所用到的设备,有GPU用GPU
device = torch.device("cude"if torch.cude.is_available() else "cpu")
# 定义一个优化器,选取梯度下降法中的Adam优化算法,后面会使用
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
# 定义一个损失函数,交叉熵损失
criterion = nn.CrossEntropyLoss()
# 将模型放入到训练设备GPU上
model = model.to(device)
# 复制最好模型的权重,后期加载这个权重用于测试
best_model_wts = copy.deepcopy(model.state_dict())
# 初始化参数
# 最高准确度
best_acc = 0.0
# 训练集损失列表,保存loss值
train_loss_all = []
# 验证集损失列表,保存loss值
val_loss_all = []
# 训练集精度列表
train_acc_all = []
# 验证集准确度列表
val_acc_all = []
# 保存当前时间,方便看每轮训练的时间
since = time.time()
# 准备工作完毕,现在开始进入循环
for epoch in range(num_epochs):
print("Epoch{}/{}".format(epoch, num_epochs-1))
print("-"*10)
# 初始化参数
# 训练集损失函数
train_loss = 0.0
# 训练集准确度
train_corrects = 0.0
# 验证集损失函数
val_loss = 0.0
# 验证集准确度
val_corrects = 0.0
# 训练集样本数量
train_num = 0
# 验证集样本数量
val_num = 0
# 对每一个mini-batch训练和计算
for step, (b_x, b_y) in enumerate(train_dataloader):
# 将特征放入到训练设备中
b_x = b_x.to(device)
# 将标签放入大训练设备中
b_y = b_y.to(device)
# 设置模型为训练模式
model.train()
# 前向传播过程,输入为一个batch,输出为一个batch中对应的预测
output = model(b_x)
# 查找每一行中最大值对应的行标,即本轮结果
pre_label = torch.argmax(output, dim=1)
# 计算每一个batch的损失函数
loss = criterion(output, b_y)
# 将梯度初始化为0,防止把前面训练的梯度累加
optimizer.zero_grad()
# 利用上面计算的损失函数进行反向传播,反向传播计算
loss.backward()
# 根据网络反向传播的梯度信息来更新网络参数,以起到降低loss函数计算值的作用
optimizer.step()
# 对损失函数进行一个累加,loss.item()是计算该批次每个样本的损失值,用这个损失值乘以该批次的样本数得到该批次样本损失
train_loss += loss.item() * b_x.size(0)
# 如果预测正确,准确度train_corrects加1
train_corrects += torch.sum(pre_label == b_y.data)
# 当前(该轮次)用于训练的样本数量
train_num += b_x.size(0)
# 验证过程相较于训练过程,没有反向传播
for step, (b_x, b_y) in enumerate(val_dataloader):
# 将特征放入到验证设备中
b_x = b_x.to(device)
# 将标签放入到验证设备中
b_y = b_y.to(device)
# 设置模型为评估模式
model.eval()
# 前向传播过程,输入一个batch,输出为一个batch中对应的人预测
output = model(b_x)
# 查找每一行中最大值对应的行标
pre_lab = torch.argmax(output, dim=1)
# 计算每一个把batch的损失函数
loss = criterion(output, b_y)
# 对损失函数进行累加
val_loss += loss.item() * b_x.size(0)
# 如果预测正确,则准确度val_corrects加1
val_corrects += torch.sum(pre_lab == b_y.data)
# 当前用于验证的样本数量
val_num += b_x.size(0)
# 计算并保存每一个迭代的loss值和准确率
# 计算并保存训练集的loss值
train_loss_all.append(train_loss / train_num)
# 计算并保存训练集的准确度
train_acc_all.append(train_corrects.doubule().item() / train_num)
# 计算并保存验证集的loss值
val_loss_all.append(val_loss / val_num)
# 计算并保存验证集的准确率
val_acc_all.append(val_corrects.doubule().item() / val_num)
print('{} Train Loss:{:,4f} Train Acc:{:, 4f}'.format(epoch, train_loss_all[-1], train_acc_all[-1]))
print('{} Val Loss:{:,4f} Val Acc:{:, 4f}'.format(epoch, train_loss_all[-1], train_acc_all[-1]))
# 寻找最高准确度的权重参数
if val_acc_all[-1] > best_acc:
# 保存当前最高准确度
best_acc = val_acc_all[-1]
# 保存最高准确对的权重参数
best_model_wts = copy.deepcopy(model.state_dict())
# 训练耗费时间
time_use = time.time() - since
print("训练和验证耗费时间{:,0f}m{:,0f}s".format(time_use//60, time_use % 60))
# 选择最优参数,加载最优准确率下的模型参数
model.load_state_dict(best_model_wts)
torch.save(model.load_state_dict(best_model_wts), "这里要加入一个文件夹地址")
train_process = pd.DataFrame(data={"epoch": range(num_epochs),
"train_loss_all": train_loss_all,
"val_loss_all": train_acc_all,
"val_acc_all": val_acc_all
})
return train_process
def matplot_acc_loss(train_process):
plt.figure(figsize=12, 4)
plt.subplot(1,2,1)
plt.plot(train_process["epoch"], train_process.train_loss_all, "ro-", label="train loss")
plt.plot(train_process["epoch"], train_process.val_loss_all, "ro-", label="val loss")
plt.legend()
plt.xlabel("epoch")
plt.ylabel("loss")
模版,未完待续
最新推荐文章于 2024-10-13 20:15:58 发布