【7】nn.module使用与数据增强

简介: 【7】nn.module使用与数据增强

1.nn.module


使用nn.module有很多的好处


1)可以使用使用现成的神经网络模块

nn.Linear
nn.ReLU
nn.Sigmoid
nn.Conv2d
nn.CosineEmbeddingLoss
nn.Dropout


2)nn.Sequential方便的构造神经网络

self.model = nn.Sequential(
            nn.Linear(784, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 200),
            nn.LeakyReLU(inplace=True),
            nn.Linear(200, 10),
            nn.LeakyReLU(inplace=True),
        )


3)可以管理参数

# 构建两层全连接层
net = nn.Sequential(
    nn.Linear(4,2),
    nn.Linear(2,2),
)
list(net.parameters())[0]
# 直接查看第一层参数权重w
# Parameter containing:
# tensor([[-0.0824,  0.2460, -0.0154,  0.1714],
#         [ 0.1619,  0.1596,  0.0725, -0.1022]], requires_grad=True)
list(net.parameters())[2]
# 直接查看第二层参数权重w
# Parameter containing:
# tensor([[-0.5342,  0.0013],
#         [ 0.3502, -0.2241]], requires_grad=True)
# list(net.parameters())
# 这句可以直接的查看全部的参数,且pytorch会给这些参数全部都赐予宇哥名字
dict(net.named_parameters()).items()
# dict_items([(
# '0.weight', Parameter containing:
# tensor([[-0.0824,  0.2460, -0.0154,  0.1714],
#         [ 0.1619,  0.1596,  0.0725, -0.1022]], requires_grad=True)), 
# ('0.bias', Parameter containing:
# tensor([-0.2492, -0.4491], requires_grad=True)), 
# ('1.weight', Parameter containing:
# tensor([[ 0.0464, -0.1378],
#         [ 0.3071,  0.3216]], requires_grad=True)), 
# ('1.bias', Parameter containing:
# tensor([0.1583, 0.4684], requires_grad=True))])
# 由于设置的是两层网络,所以会有两层权值w与偏置b,这些参数的shape都是与所设定的相匹配的
optimizer = optim.SGD(net.parameters(),lr=1e-3)
# 由于pytorch帮助我们管理了参数,所以直接将net.parameters()直接传入优化器即可


4)可以得到网络结构的直系亲属

# 一个比较小的神经网络
class BasicNet(nn.Module):
    def __init__(self):
        super(BasicNet, self).__init__()
        self.net = nn.Linear(4, 3)
    def forward(self, x):
        return self.net(x)
# 一个比较大的神经网络
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.net = nn.Sequential(BasicNet(),
                                 nn.ReLU(),
                                 nn.Linear(3, 2))
    def forward(self, x):
        return self.net(x)
# 也就是可以嵌套的定义神经网络


5)使用GPU加速

# GPU加速操作
device = torch.device('cuda')
# 抽象出一个设备,一会来讲数据放在gpu上面
# device = torch.device('cpu')
net = Net()
net.to(device)
# 需要注意,以上的两个net是同一样的内容,也就是对于一个网络来说返回的内容是一样的
# 但是,如果是对于一堆数据那返回内容的就是不一样的
# net.to(device) == net = net.to(device)


6)保存网络的中间状态

# save与load的操作
device = torch.device('cuda')
net = Net()
net.to(device)
# 将训练过程中的中间数据参数net.state_dicta()保存在ckpt.mdl文件中
torch.save(net.state_dicta(),'ckpt.mdl')
# 将ckpt.mdl文件中的参数解压出来然后加载load_state_dict都net网络中
net.load_state_dict(torch.load('ckpt.mdl'))
# 有这个加载与保存参数的操作就不需要从0开始训练网络


7)训练或者测试过程状态的转换

# 状态的切换操作
# eg:Dropout与BatchNorm这样的操作,训练与测试的操作是不一样的
# 因此分别需要对参数状态进行切换
device = torch.device('cuda')
net = Net()
net.to(device)
# 训练过程,进行train状态的切换
net.train()
...
# 测试过程,进行test状态的切换
net.eval()
...


8)实现自定义的类

# 例子一:
# 自定义的实现一个类函数
class Flatten(nn.Module):
    def __init__(self):
        super(Flatten, self).__init__()
  # 默认是将第一个维度保留下来,然好将后面的维度全部打平来操作
    def forward(self, input):
        return input.view(input.size(0), -1)
class TestNet(nn.Module):
    def __init__(self):
        super(TestNet, self).__init__()
        self.net = nn.Sequential(nn.Conv2d(1, 16, stride=1, padding=1),
                                 nn.MaxPool2d(2, 2),
                                 # 将数据打平
                                 Flatten(),
                                 nn.Linear(1*14*14, 10))
    def forward(self, x):
        return self.net(x)
# 将自定义的类写在Sequential里面便可以一次性的进行forward操作


# 例子二:
# 自定义实习类似nn.Linear的类操作
class MyLinear(nn.Module):
    def __init__(self, inp, outp):
        super(MyLinear, self).__init__()
        # requires_grad = True
        # 将w,b的参数自动的添加到nn.Parameter当中取,这样就可以自动的被optim.SGD优化
        self.w = nn.Parameter(torch.randn(outp, inp))
        self.b = nn.Parameter(torch.randn(outp))
    def forward(self, x):
        x = x @ self.w.t() + self.b
        return x
# 这个自定义的类与nn.Linear的功能是完全一样的


2.数据增强


常见的数据增强的手段有:

1)Flip翻转操作

2)Rotate旋转操作

3)Random Move & Crop

4)GAN


1)Flip操作

image.png

参考代码:

# 对训练集进行数据增强Filp操作
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       # 进行水平方向的随机翻转
                       transforms.RandomHorizontalFlip(),
                       # 进行竖直方向的随机翻转
                       transforms.RandomVerticalFlip(),
                       transforms.ToTensor(),
                       # transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)


2)Rotate操作

image.png

参考代码:


# 对训练集进行数据增强Rotate操作
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       # 对图片进行一个随机的旋转角度,范围是[-15°-15°]
                       transforms.RandomRotation(15),
                       # 对图片进行一个随机的固定数值旋转角度,可以选择的角度在一个list中,eg:[90, 180, 270]
                       transforms.RandomRotation([90, 180, 270]),
                       transforms.ToTensor(),
                       # transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)


3)Scale操作

image.png

参考代码:


# 对训练集进行数据增强Scale操作
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
        # 将原来的图片大小由28*28变成32*32
                       transforms.Resize([32, 32]),
                       transforms.ToTensor(),
                       # transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)


4)Crop Part操作

image.png


参考代码:


# 对训练集进行数据增强Crop操作,也就是随机的裁剪
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
        # 将原来的图片随机裁剪为28*28的大小
                       transforms.RandomCrop([28, 28]),
                       transforms.ToTensor(),
                       # transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)


尽管可以使用数据增强对图片进行很多的变换操作,但其分布不会提高很多,只会有一点的改进


5)多种操作结合处理

# 随机裁剪一个面积为原始面积10%到100%的区域,该区域的宽高比从0.5到2之间随机取值。 然后,区域的宽度和高度都被缩放到200像素。
shape_aug = torchvision.transforms.RandomResizedCrop(
    (32, 32), scale=(0.5, 1), ratio=(0.5, 2))
# 随机更改图像的亮度、对比度、饱和度、色调,随机值为原始图像的50%( 1−0.5 )到150%( 1+0.5 )之间
color_aug = torchvision.transforms.ColorJitter(
    brightness=0.5, contrast=0.5, saturation=0.5, hue=0.5)
# 数据增强
train_augs = torchvision.transforms.Compose([
    # 水平翻转   
    torchvision.transforms.RandomHorizontalFlip(),
    # 竖直翻转
    torchvision.transforms.RandomVerticalFlip(),
    # 颜色改变
    color_aug,
    # 裁剪变化:
    shape_aug,
    # 格式转化
    torchvision.transforms.ToTensor()])
test_augs = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()])
root = "E:\学习\机器学习\数据集\cifar"
batch_size = 64
tr_dataset = torchvision.datasets.CIFAR10(root=root, train=True, transform=train_augs, download=False)
dataset = torchvision.datasets.CIFAR10(root=root, train=True, transform=test_augs, download=False)
tr_dataloader = torch.utils.data.DataLoader(tr_dataset, batch_size=batch_size, shuffle=True)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)
# 这里有一个问题,通过一些列的结构其实明没有增加样本量
# 这时候可以通过将数据增强后的数据再与元数据结合,label保持不变
# 再把扩充的数据丢到dataloader中进行加载,如下操作所示
data = tr_dataset + dataset
loader = torch.utils.data.DataLoader(data, batch_size=batch_size, shuffle=True)
print(len(tr_dataset), len(dataset), len(data), len(tr_dataloader), len(dataloader), len(loader))


输出结果为:50000 50000 100000 782 782 1563

可以看见,数据增强后的数据可以正常的加载,而且有效的扩充了样本数量


查看多种数据增加后的处理结果


def show_image(image, n_row, n_column):
    plt.figure(figsize=(12, 8), dpi=144)
# 测试,显示一张图像
    for i, img in enumerate(image):
        plt.subplot(n_row, n_column, i+1)
        plt.axis("off")
        plt.imshow(img.permute(1,2,0))
    #     plt.show()
        # time.sleep(1)
# 输出转换后的图像数据
print("after transform: ")
image,_ = iter(tr_dataloader).next()
print(image.shape)
show_image(image, 8, 8)

image.png

目录
相关文章
|
4月前
|
机器学习/深度学习 PyTorch 算法框架/工具
【从零开始学习深度学习】16. Pytorch中神经网络模型的构造方法:Module、Sequential、ModuleList、ModuleDict的区别
【从零开始学习深度学习】16. Pytorch中神经网络模型的构造方法:Module、Sequential、ModuleList、ModuleDict的区别
|
4月前
|
机器学习/深度学习 数据可视化 Python
No module named 'pytorch_wavelets'问题如何解决
【6月更文挑战第21天】No module named 'pytorch_wavelets'问题如何解决
138 0
|
5月前
|
前端开发
平台设计-moduleID的使用
整个平台上有很多相同的功能
|
5月前
|
机器学习/深度学习 编解码 算法
Yolov5改进算法之添加Res2Net模块
Res2Net(Residual Resolution Network)是一种用于图像处理和计算机视觉任务的深度卷积神经网络架构。它旨在解决传统的ResNet(Residual Network)存在的问题,如对不同尺度和分辨率特征的建模不足以及网络深度受限的问题。Res2Net通过引入多分支的结构和逐级增加的分辨率来提高网络的表达能力,从而在各种视觉任务中取得了显著的性能提升。
278 0
|
存储 PyTorch 算法框架/工具
PyTorch模型创建与nn.Module
PyTorch模型创建与nn.Module
106 1
Can‘t get attribute ‘SiLU‘ on <module ‘torch.nn.modules.activation‘
Can‘t get attribute ‘SiLU‘ on <module ‘torch.nn.modules.activation‘
|
机器学习/深度学习 人工智能 PyTorch
|
PyTorch 算法框架/工具
pytorch中nn.ModuleList()使用方法
pytorch中nn.ModuleList()使用方法
322 0
|
机器学习/深度学习 缓存 自然语言处理
【40】torch.nn汇总(各类与函数接口的解释说明)
【40】torch.nn汇总(各类与函数接口的解释说明)
402 0
【40】torch.nn汇总(各类与函数接口的解释说明)
|
缓存 PyTorch 算法框架/工具
pytorch中的nn.Module抽象类的参数
pytorch中的nn.Module抽象类的参数
105 0