Pytorch主要组成模块

参考资料:

课程内容链接:https://github.com/datawhalechina/thorough-pytorch
教程视频链接:https://www.bilibili.com/video/BV1L44y1472Z

导入包的方式

import os
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
import torch.optim as optimizer

超参数包括:

  • batch size

  • 初始学习率(初始)

  • 训练次数(max_epochs)

  • GPU配置

GPU设置的两种常见方式:

# 方案一:使用os.environ,这种情况如果使用GPU不需要设置
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'
加载使用:
model.cuda()

# 方案二:使用“device”,后续对要使用GPU的变量用.to(device)即可
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")

加载和使用:

data = data.to(device)

model = Model(…).to(device)

数据读入通过Dataset+DataLoader

Dataset类来实现灵活的数据读取,定义的类需要继承PyTorch自身的Dataset类。主要包含三个函数:

  • __init__: 用于向类中传入外部参数,同时定义样本集

  • __getitem__: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据

  • __len__: 用于返回数据集的样本数

构建好Dataset后,就可以使用DataLoader来按批次读入数据了

from torch.utils.data import DataLoader

train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=4, shuffle=True, drop_last=True)
val_loader = torch.utils.data.DataLoader(val_data, batch_size=batch_size, num_workers=4, shuffle=False)
  • batch_size:样本是按“批”读入的,batch_size就是每次读入的样本数

  • num_workers:有多少个进程用于读取数据

  • shuffle:是否将读入的数据打乱

  • drop_last:对于样本最后一部分没有达到批次数的样本,使其不再参与训练

神经网络模型构建:

PyTorch中神经网络构造一般是基于 Module 类的模型来完成的,它让模型构造更加灵活。

Module 类是 nn 模块里提供的一个模型构造类,是所有神经⽹网络模块的基类,我们可以继承它来定义我们想要的模型。下面继承 Module 类构造多层感知机。这里定义的 MLP 类重载了 Module 类的 init 函数和 forward 函数。它们分别用于创建模型参数和定义前向计算。前向计算也即正向传播。

模型初始化:

mlp = MLP()  ##模型
print(list(mlp.parameters()))
print("-------初始化-------")

initialize_weights(mlp)
print(list(mlp.parameters()))

损失函数以交叉熵损失函数为例:

torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')

主要参数

weight:每个类别的loss设置权值。

size_average:数据为bool,为True时,返回的loss为平均值;为False时,返回的各样本的loss之和。

ignore_index:忽略某个类的损失函数。

reduce:数据类型为bool,为True时,loss的返回是标量。

训练和评估:

for epoch in range(1, epochs+1):
    train(epoch)
    val(epoch)
训练:
def train(epoch):
    model.train()
    train_loss = 0
    for data, label in train_loader:
        data, label = data.cuda(), label.cuda()
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, label)
        loss.backward()
        optimizer.step()
        train_loss += loss.item()*data.size(0)
    train_loss = train_loss/len(train_loader.dataset)
    print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch, train_loss))

评估:

def val(epoch):       
    model.eval()
    val_loss = 0
    gt_labels = []
    pred_labels = []
    with torch.no_grad():
        for data, label in test_loader:
            data, label = data.cuda(), label.cuda()
            output = model(data)
            preds = torch.argmax(output, 1)
            gt_labels.append(label.cpu().data.numpy())
            pred_labels.append(preds.cpu().data.numpy())
            loss = criterion(output, label)
            val_loss += loss.item()*data.size(0)
    val_loss = val_loss/len(test_loader.dataset)
    gt_labels, pred_labels = np.concatenate(gt_labels), np.concatenate(pred_labels)
    acc = np.sum(gt_labels==pred_labels)/len(pred_labels)
    print('Epoch: {} \tValidation Loss: {:.6f}, Accuracy: {:6f}'.format(epoch, val_loss, acc))

优化器:

  1. optimizer在一个神经网络的epoch中需要实现下面两个步骤:

    1. 梯度置零

    2. 梯度更新

optimizer = torch.optim.SGD(net.parameters(), lr=1e-5)
for epoch in range(EPOCH):
	...
	optimizer.zero_grad()  #梯度置零
	loss = ...             #计算loss
	loss.backward()        #BP反向传播
	optimizer.step()       #梯度更新

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2022年5月20日
下一篇 2022年5月20日

相关推荐