Pytorch主要组成模块

1. 数据读入模块

PyTorch数据读入是通过Dataset + DataLoader的方式完成的,Dataset定义好数据的格式和数据变换形式,Dataloader用iterative的方式不断读入批次数据。

组成Dataset的主要方式有两种,用程序自带的数据集或者我们可以定义自己的Dataset类来实现灵活的数据读取。
下面以cifar10数据集为例:

程序自带读取方式

train_data = torchvision.datasets.CIFAR10(root="./torch_dataset",train=True,
                                          transform=torchvision.transforms.ToTensor(),download=False)

test_data = torchvision.datasets.CIFAR10(root="./torch_dataset",train=False,
                                          transform=torchvision.transforms.ToTensor(),download=False)

自定义Dataset类

定义的类需要继承PyTorch自身的Dataset类。主要包含三个函数:

  • __init__: 用于向类中传入外部参数,同时定义样本集
  • __getitem__: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据
  • __len__: 用于返回数据集的样本数

下面以CIFAR10数据集为例给出构建Dataset类的方式:

class MyDataset(Dataset):
    def __init__(self, data_dir, info_csv, image_list, transform=None):
        """
        Args:
            data_dir: path to image directory.
            info_csv: path to the csv file containing image indexes
                with corresponding labels.
            image_list: path to the txt file contains image names to training/validation set
            transform: optional transform to be applied on a sample.
        """
        label_info = pd.read_csv(info_csv)
        image_file = open(image_list).readlines()
        self.data_dir = data_dir
        self.image_file = image_file
        self.label_info = label_info
        self.transform = transform

    def __getitem__(self, index):
        """
        Args:
            index: the index of item
        Returns:
            image and its labels
        """
        image_name = self.image_file[index].strip('\n')
        raw_label = self.label_info.loc[self.label_info['Image_index'] == image_name]
        label = raw_label.iloc[:,0]
        image_name = os.path.join(self.data_dir, image_name)
        image = Image.open(image_name).convert('RGB')
        if self.transform is not None:
            image = self.transform(image)
        return image, label

    def __len__(self):
        return len(self.image_file)

2. 神经网络构建

Pytorch中对神经网络的构建首先要继承nn.Module模块,之后再定义网络中需要的各种操作(如:卷积、池化等等),最后再在forward 中定义各层需要采取的操作。

2.1 常见的操作

A. 不含模型参数的层

下⾯构造的 MyLayer 类通过继承 Module 类自定义了一个将输入减掉均值后输出的操作,并将层的计算定义在了 forward 函数里。这个层里不含模型参数,只是简单的定义了一个减法操作。

import torch
from torch import nn

class MyLayer(nn.Module):
    def __init__(self, **kwargs):
        super(MyLayer, self).__init__(**kwargs)
    def forward(self, x):
        return x - x.mean()  

B. 含模型参数的层

我们直接来看一个例子吧,这个里面规定了网络的参数parameters,并在forward中添加了一个torch.mm的操作(torch.mm(a, b)是矩阵a和b矩阵相乘,比如a的维度是(1, 2),b的维度是(2, 3),返回的就是(1, 3)的矩阵)。整体下来,可以理解成在做线性回归,我们需要在后续训练回归的参数值。

class MyListDense(nn.Module):
    def __init__(self):
        super(MyListDense, self).__init__()
        self.params = nn.ParameterList([nn.Parameter(torch.randn(4, 4)) for i in range(3)])
        self.params.append(nn.Parameter(torch.randn(4, 1)))

    def forward(self, x):
        for i in range(len(self.params)):
            x = torch.mm(x, self.params[i])
        return x
net = MyListDense()
print(net)

注意:Parameter 类其实是 Tensor 的子类,如果一 个 Tensor 是 Parameter ,那么它会⾃动被添加到模型的参数列表里。所以在⾃定义含模型参数的层时,我们应该将参数定义成 Parameter ,除了直接定义成 Parameter 类外,还可以使⽤ ParameterList 和 ParameterDict 分别定义参数的列表和字典。

C. 二维卷积层

二维卷积层可以自己定义,也可以直接调用 torch.nn 中的 Conv2d 函数。
自己定义:

import torch
from torch import nn

# 卷积运算(二维互相关)
def corr2d(X, K): 
    h, w = K.shape
    X, K = X.float(), K.float()
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i: i + h, j: j + w] * K).sum()
    return Y

# 二维卷积层
class Conv2D(nn.Module):
    def __init__(self, kernel_size):
        super(Conv2D, self).__init__()
        self.weight = nn.Parameter(torch.randn(kernel_size))
        self.bias = nn.Parameter(torch.randn(1))

    def forward(self, x):
        return corr2d(x, self.weight) + self.bias

调用函数:

class Wdz(nn.Module):
    def __init__(self):
        super(Wdz, self).__init__()
        self.conv1 = Conv2d(3,32,(5,5),padding=2)
        
    def forward(self,x):
        x = self.conv1(x)
        return x

D. 池化层

池化层每次对输入数据的一个固定形状窗口(⼜称池化窗口)中的元素计算输出。不同于卷积层里计算输⼊和核的互相关性,池化层直接计算池化窗口内元素的最大值或者平均值。该运算也 分别叫做最大池化或平均池化。在二维最⼤池化中,池化窗⼝口从输⼊入数组的最左上⽅方开始,按从左往右、从上往下的顺序,依次在输⼊数组上滑动。当池化窗口滑动到某⼀位置时,窗口中的输入子数组的最大值即输出数组中相应位置的元素。
同样,池化层可以自己定义或者调用torch.nn import 中的 MaxPool2d 或者其他池化函数。
自己定义:

import torch
from torch import nn

def pool2d(X, pool_size, mode='max'):
    p_h, p_w = pool_size
    Y = nd.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            if mode == 'max':
                Y[i, j] = X[i: i + p_h, j: j + p_w].max()
            elif mode == 'avg':
                Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
    return Y

调用函数


class Wdz(nn.Module):
    def __init__(self):
        super(Wdz, self).__init__()
       

        self.model1 = Sequential(
            Conv2d(3, 32, (5, 5), padding=2),
            MaxPool2d((2, 2))
        )

    def forward(self,x):
        x = self.model1(x)
        return x

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