Pytorch 模块与基础实践

Pytorch 模块与基础实践

神经网络学习机制

  • 数据预处理
  • 模型设计
  • 损失函数和优化方案设计
  • 前向传播
  • 反向传播
  • 参数更新

在这里插入图片描述

深度学习实现的特殊性

  • 样本大,通常需要分批次(batch)加载进内存
  • 逐层、模块化搭建网络(卷积层,全连接层,LSTM等)
  • 多样化损失函数和优化器设计
  • GPU的运算处理(并行计算)
  • 各个模块之间的配合

各模块拆解

根据需求修改内容即可

  • 基本配置
  • 数据读入
  • 模型构建
  • 损失函数
  • 优化器
  • 训练与评估

案例:FashionMNIST时装分类

数据集介绍:FashionMNIST 是一个替代 MNIST手写数字数据集
的图像数据集。其大小、格式和训练集/测试集划分与原始的 MNIST 完全一致。60000/10000 的训练测试数据划分,28x28 的灰度图片。

在这里插入图片描述

包导入

#包的导入
import os
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset,DataLoader

配置训练环境和超参数

#配置GPU
#一.全局配置
#os.environ['CUDA_VISIBLE_DEVICES']='0' #全局设置部署到第一块显卡上
#二.定义device,后续可直接用.to(device)
device= torch.device("cuda:1" if torch.cuda.is_available() else "cpu")

## 超参数配置
#每次训练读入的数据数量
batch_size=256
#工作线程数
num_woorkers=4
#学习率
lr=1e-4
#训练轮次
epochs=20

数据读入与加载

  • 本地数据读取:Dataset
    • —init— , — getitem— , —len—
  • 数据加载供模型使用:DataLoader
    • -batch_size , num_worders,shuffle,drop_last,pin_memory(将数据放入锁业内存:速度更快,更占内存按需)

两种导入方式#

  • 下载使用Pytorch内置数据集
    • 方便
    • 不可修改
    • 可用于测试idea的效果
  • 从网站下载以csv存储的数据,读入并转为预期格式
    • 创建Dataset
    • 进行必要的转换
    • 数据格式转为tensor

数据变换

#数据变换
from torchvision import transforms

image_size=28
data_transform=transforms.Compose([
    transforms.ToPILImage(),#对于读取内置数据集不需要
    transforms.Resize(image_size),#匹配网络
    transforms.ToTensor()#转为tensor
])

读取数据

##读取方式一:使用torchvision自带数据集
from torchvision import datasets
train_data=datasets.FashionMNIST(root='./',train=True,download=True,transform=data_transform)
test_data=datasets.FashionMNIST(root='./',train=False,download=True,transform=data_transform)

#读取方式二:
#csv文件下载链接:https://www.kaggle.com/datasets/zalando-research/fashionmnist?resource=download
#链接:https://pan.baidu.com/s/1gHBCTX-rMSJfeqOOp1Ik-A?pwd=oef6 提取码:oef6
class FMDataset(Dataset):
  def __init__(self,df,transform=None):
    self.df=df
    self.transform=transform
    #一张图片像素为一列,切片转为uint8
    self.images=df.iloc[:,1:].values.astype(np.uint8)
    self.labels=df.iloc[:,0].values
  
  def __len__(self):
    return len(self.images)
  
  def __getitem__(self,idx):
    #一行数据转为28*28的灰度图像
    image=self.images[idx].reshape(28,28,1)
    label=int(self.labels[idx])
    #如果有数据预处理
    if self.transform is not None:
      image=self.transform(image)
    else:
      #没有预处理,转为0-1方便计算
      image=torch.tensor(image/255.,dtype=torch.float)
    label=torch.tensor(label,dtype=torch.long)
    return image,label

train_df=pd.read_csv("fashion-mnist_train.csv")
test_df=pd.read_csv("fashion-mnist_test.csv")
train_data=FMDataset(train_df,data_transform)
test_data=FMDataset(test_df,data_transform)
train_df

在这里插入图片描述
在这里插入图片描述

(train_csv中第一列为label , 然后是pixell列为对应像素值(0,255))

定义DataLoader类

定义一个迭代器,便于取数据

#定义迭代器
#数据集,batch_size,shuffle:随机取数,num_workers:线程数,drop_last:丢掉最后一批,防止数据不满一个batch
train_loader=DataLoader(train_data,batch_size=batch_size,shuffle=True,num_workers=num_workers,drop_last=True)
test_loader=DataLoader(test_data,batch_size=batch_size,shuffle=False,num_workers=num_workers)

可视化

import matplotlib.pyplot as plt
#单批次迭代
image,label=next(iter(train_loader))
print(image.shape,label.shape)
plt.imshow(image[0][0],cmap='gray')

在这里插入图片描述

模型设计

  • 神经网络的构造:基于nn.Moudle
      • -init- -,forward
  • 通过层定义+层排序构建网络
  • 常见层:nn.Conv2d,nn.MaxPool2d,nn.Linear,nn.Relu

模型搭建

#模型搭建
class Net(nn.Module):
  def __init__(self):
    super(Net,self).__init__()
    #卷积层定义
    self.conv=nn.Sequential(
        nn.Conv2d(1,32,5),
        nn.ReLU(),
        nn.MaxPool2d(2,stride=2),
        nn.Dropout(0.3),
        nn.Conv2d(32,64,5),
        nn.ReLU(),
        nn.MaxPool2d(2,stride=2),
        nn.Dropout(0.3)
    )
    #全连接层定义
    self.fc=nn.Sequential(
        nn.Linear(64*4*4,512),
        nn.ReLU(),
        nn.Linear(512,10)
    )
  def forward(self,x):
    x=self.conv(x)
    x=x.view(-1,64*4*4)
    s=self.fc(x)
    #x=nn.functional.normalize(x)
    return x

model=Net()
#模型移到cuda
#model=model.cuda()
#model=nn.DataParallel(model).cuda()  #多卡训练时的写法

损失函数

  • torch.nn提供多种预定义损失函数
  • 使用backward()进行反向传递

code

使用torch.nn中的CrossEntropy损失

Pytorch自动将整数行lable转为one-hot编码

#多分类问题,使用交叉熵函数
criterion=nn.CrossEntropyLoss()

优化器

  • torch.optim提供多种预定义优化器
  • 根据需求选用
  • 常用操作:step(),zero_grad(),load_state_dict()

code

#使用Adam优化器 lr学习率
optimizer=optim.Adam(model.parameters(),lr=0.001)

训练与预测

  • model.train(),model.eval()
  • 训练流程:读取数据,转换,梯度归零,输入,计算loss,backward,更新参数
  • 验证:读取数据,转换,输入,计算损失,计算指标

code

#封装为函数
def train(epoch):
  model.train()
  train_loss=0
  for i ,(data,label) in enumerate(train_loader):
    #data.label=data.cuda(),label.cuda() 转到GPU
    optimizer.zero_grad()#梯度清0
    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())#添加真实label
      pred_labels.append(preds.cpu().data.numpy())#添加预测label
      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))
#开始训练
for epoch in range(1,epochs+1):
  train(epoch)
  val(epoch)

在这里插入图片描述

最后监控gpu使用情况

#监控gpu使用情况
#shell中 gpu_info=!nvidia-smi -i 0
gpu_info = '\n'.join(gpu_info)
print(gpu_info)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值