模版,未完待续

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")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值