【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

目录
相关文章
|
人工智能 小程序 API
【一步步开发AI运动小程序】十三、自定义一个运动分析器,实现计时计数02
本文介绍如何利用“云智AI运动识别小程序插件”开发AI运动小程序,详细解析了俯卧撑动作的检测规则构建与执行流程,涵盖卧撑和撑卧两个姿态的识别规则,以及如何通过继承`sports.SportBase`类实现运动分析器,适用于小程序开发者。
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【10月更文挑战第4天】在数字化时代,网络安全和信息安全已成为我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术和安全意识等方面的知识,并提供一些实用的建议来保护您的个人信息和设备。通过阅读本文,您将了解到如何识别和防范网络威胁,以及如何提高自己的安全意识。
136 0
|
存储 分布式计算 监控
Hadoop冗余数据存储
【4月更文挑战第13天】Hadoop的HDFS分布式文件系统通过数据块划分、冗余存储(副本创建)和多样化存储类型提升可靠性与扩展性。NameNode监控副本数量,确保数据安全。使用数据压缩算法节省空间,数据本地化优化提高效率。支持并行处理,实现高效大规模数据处理。
302 1
|
存储 Java 容器
Java数据类型与变量
在Java编程语言中,数据类型和变量是基础概念,它们对于理解程序结构和逻辑至关重要。本文将详细介绍Java中的数据类型和变量,包括它们的分类、声明、初始化和使用。通过了解这些基础知识,我们将能够更好地理解和编写Java程序。
|
存储 弹性计算 运维
阿里云容器镜像服务 | 学习笔记
快速学习阿里云容器镜像服务
阿里云容器镜像服务 | 学习笔记
|
消息中间件 调度
RabbitMQ 实战教程(二) 工作队列
RabbitMQ 实战教程(二) 工作队列
209 0
RabbitMQ 实战教程(二) 工作队列
|
机器学习/深度学习 自然语言处理 安全
快速入门Python机器学习(二)
快速入门Python机器学习(二)
490 0
|
前端开发 Python
8. Python3源码—Code对象与pyc文件
# 8.1. Python程序的执行过程 Python解释器在执行任何一个Python程序文件时,首先进行的动作都是先对文件中的Python源代码进行编译,编译的主要结果是产生一组Python的byte code(字节码),然后将编译的结果交给Python的虚拟机(Virtual Machine),由虚拟机按照顺序一条一条地执行字节码,从而完成对Python程序的执行动作。 对于Pytho
7766 0