【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战

【项目简介】

        PyTorch是利用深度学习进行数据科学研究的重要工具,在灵活性、可读性和性能上都具备相当的优势,近年来已成为学术界实现深度学习算法最常用的框架。考虑到PyTorch的学习兼具理论储备和动手训练,两手都要抓两手都要硬的特点,我们开发了 《深入浅出PyTorch》课程,期望以组队学习的形式,帮助大家从入门到熟练掌握PyTorch工具,进而实现自己的深度学习算法。学习的先修要求是,会使用Python编程,了解包括神经网络在内的机器学习算法,勤于动手实践。

        我们的愿景是:通过组队学习,大家能够掌握由浅入深地PyTorch的基本知识和内容,经过自己的动手实践加深操作的熟练度。同时通过项目实战,充分锻炼编程能力,掌握PyTorch进行深度学习的基本流程,提升解决实际问题的能力。

        

【教程地址】
在线教程链接:深入浅出PyTorch — 深入浅出PyTorch
Github在线教程:GitHub - datawhalechina/thorough-pytorch: PyTorch入门教程,在线阅读地址:https://datawhalechina.github.io/thorough-pytorch/
Gitee在线教程:https://gitee.com/datawhalechina/thorough-pytorch 
b站视频:深入浅出Pytorch_哔哩哔哩_bilibili


【框架模块整理】

【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第1张图片【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第2张图片


【实战案例】

【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第3张图片

 导包:

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

配置训练环境和超参数:

【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第4张图片

GPU配置:

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

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

超参数设置:

  •  batch size
batch_size = 16
# 批次的大小
# 图片比较小 设置256

  • 有多少线程供读入数据
num_workers = 4  
 
# 对于Windows用户,这里应设置为0,否则会出现多线程错误
  • 初始学习率(初始) - learning rate (补偿)

lr = 1e-4
# 优化器的学习率

  • 训练次数(max_epochs)  

max_epochs = 100

数据读入:

第一种数据读入方式

只适用于常见的数据集,如MNIST,CIFAR10等,PyTorch官方提供了数据下载。这种方式往往适用于快速测试方法(比如测试下某个idea在MNIST数据集上是否有效)

 读取方式一:使用torchvision自带数据集 datasets.xxx

## 读取方式一:使用torchvision自带数据集,下载可能需要一段时间
from torchvision import datasets

train_data = datasets.FashionMNIST(root='./', train=True, download=True, transform=data_transform)
#训练集 train=True

test_data = datasets.FashionMNIST(root='./', train=False, download=True, transform=data_transform)
#测试集 train=False

#有warnning 不影响使用 下载时带的 大概是只能用PyTorch使用

 【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第5张图片 

数据进行必要的变换,比如说需要将图片统一为一致的大小,以便后续能够输入网络训练;需要将数据格式转为Tensor类,等等。

【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第6张图片

借助torchvision包——PyTorch官方用于图像处理的工具库

第二种数据读入方式

需要自己构建Dataset,这对于PyTorch应用于自己的工作中十分重要

读取格式不定的本地数据:写一个Daraset类,去继承

Daraset类主要包含三个函数:

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

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

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

 ## 读取方式二:读入csv格式的数据,自行构建Dataset类

csv下载链接:Fashion MNIST | Kaggle

csv 的内容(每一行代表一个样本,包括图像和标签,其中图像用 28*28 个数值来表示)

【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第7张图片

## 读取方式二:读入csv格式的数据,自行构建Dataset类
# csv数据下载链接:https://www.kaggle.com/zalando-research/fashionmnist
class FMDataset(Dataset):
    def __init__(self, df, transform=None):
        self.df = df 
        self.transform = transform
        self.images = df.iloc[:,1:].values.astype(np.uint8)
        # .iloc是pandas的操作 “:”- 所有 “1:”- 从第二列所有的列 uint8是图像格式
        self.labels = df.iloc[:, 0].values 
        
        
    def __len__(self): #数据结构长度
        return len(self.images)
    
    def __getitem__(self, idx): #重要 
        image = self.images[idx].reshape(28,28,1) 
        #第idx行的image 变成28*28 1是加了个通道
        label = int(self.labels[idx])
        #所有的标签 对应第idx行的label
        if self.transform is not None:
            image = self.transform(image)
        else:
            image = torch.tensor(image/255., dtype=torch.float)
        label = torch.tensor(label, dtype=torch.long)
        return image, label

#实例化这个类

#train_df = pd.read_csv("./FashionMNIST/fashion-mnist_train.csv")
#test_df = pd.read_csv("./FashionMNIST/fashion-mnist_test.csv")
#可改成自己的数据集地址
train_df = pd.read_csv("G:/Datawhale/Pytorch学习/FashionMNIST/fashion-mnist_train.csv")
test_df = pd.read_csv("G:/Datawhale/Pytorch学习/FashionMNIST/fashion-mnist_test.csv")
train_data = FMDataset(train_df, data_transform)
test_data = FMDataset(test_df, data_transform)

使用DataLoader来按批次读入数据

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)

读入后,我们可以做一些数据可视化操作,主要是验证我们读入的数据是否正确  

 【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第8张图片 

卡在这里一直没运行出来

import matplotlib.pyplot as plt
image, label = next(iter(train_loader))  # next() 返回迭代器的下一个项目。next() 函数要和生成迭代器的 iter() 函数一起使用。
print(image.shape, label.shape)  # torch.Size([256, 1, 28, 28]) torch.Size([256])
plt.imshow(image[0][0], cmap="gray")  # iamge[0][0] 是取值 0-1 的矩阵

在队友的指点下终于在kaggle运行出来 [热泪盈眶.gif] 感恩

 【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第9张图片 

大概是用cpu跑的原因

环境明天重新配置一遍吧,明明之前配置好了,可能清理c盘不小心删了什么……

  

  


配置好环境之后

定义模型

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)    #10是有十类
        )
        
    def forward(self, x):         #前馈
        x = self.conv(x)
        x = x.view(-1, 64*4*4)
        x = self.fc(x)
        # x = nn.functional.normalize(x)
        return x

model = Net()               #实例化
model = model.cuda()        #.cuda把模型放到GPU上
# model = nn.DataParallel(model).cuda()   # 多卡训练时的写法,之后的课程中会进一步讲解

设定损失函数

使用torch.nn模块自带的CrossEntropy损失  

PyTorch会自动把整数型的label转为one-hot型,用于计算CE loss  

这里需要确保label是从0开始的,同时模型不加softmax层(使用logits计算),这也说明了PyTorch训练中各个部分不是独立的,需要通盘考虑

criterion = nn.CrossEntropyLoss()
# criterion = nn.CrossEntropyLoss(weight=[1,1,1,1,3,1,1,1,1,1])

**设定优化器**  

这里我们使用Adam优化器  

ptimizer = optim.Adam(model.parameters(), lr=0.001)  #lr为学习率

**训练和测试(验证)**  

各自封装成函数,方便后续调用  

关注两者的主要区别:  

- 模型状态设置  

- 是否需要初始化优化器

- 是否需要将loss传回到网络

- 是否需要每步更新optimizer  

此外,对于测试或验证过程,可以计算分类准确率

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))
for epoch in range(1, epochs+1):
    train(epoch)
    val(epoch)

【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第10张图片

【Datawhale 组队学习Pytorch】Task02 PyTorch的各个组件和实战_第11张图片 

 

你可能感兴趣的:(pytorch,深度学习,python)