ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

DIDL笔记(pytorch版)(七)

2021-06-02 11:33:00  阅读:222  来源: 互联网

标签:nn DIDL self 笔记 channels pytorch train device net


文章目录

前言

大致总结一下深度学习的流程:

  • 配置变量:批次,学习率,迭代次数设备等。
  • 导入数据:数据预处理(标准化,清洗,去噪,划分数据集),弹性形变等。
  • 搭建网络:卷积、池化、激活函数等。
  • 训练模型:选择损失函数,选择优化方法,迭代循环嵌套批次循环。(训练外层可以套k折交叉验证)
    • 内层循环执行过程:x输入网络得到输出y->y与标签比对得到损失->梯度清零->计算梯度->反馈->记录损失以及正确率方便每次迭代后展示。

LeNet

第一次将卷积神经网络推上舞台,为世人所知。
在这里插入图片描述

import time
import torch
from torch import nn, optim
import d2l as d2l


# 设计网络
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 6, 5),     # in_channels, out_channels, kernel_size
            nn.Sigmoid(),
            nn.MaxPool2d(2, 2),     # kernel_size, stride
            nn.Conv2d(6, 16, 5),
            nn.Sigmoid(),
            nn.MaxPool2d(2, 2)
        )
        self.fc = nn.Sequential(
            nn.Linear(16*4*4, 120),
            nn.Sigmoid(),
            nn.Linear(120, 84),
            nn.Sigmoid(),
            nn.Linear(84, 10)
        )

    def forward(self, img):
        feature = self.conv(img)
        output = self.fc(feature.view(img.shape[0], -1))
        return output


def train_ch5(net, train_iter, test_iter, batch_size, loss, optimizer, device, num_epochs):
    net = net.to(device)
    print("training on", device)
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n, batch_count, start = 0.0, 0.0, 0, 0, time.time()
        for X, y in train_iter:
            X = X.to(device)
            y = y.to(device)

            y_hat = net(X)
            l = loss(y_hat, y)
            optimizer.zero_grad()
            l.backward()
            optimizer.step()

            # 计算损失,呈现数据
            train_l_sum += l.cpu().item()
            train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()
            n += y.shape[0]
            batch_count += 1
        # 一个周期,计算一次test,其实也非必要
        test_acc = evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec'
              % (epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start))


def evaluate_accuracy(data_iter, net, device=None):
    if device is None and isinstance(net, torch.nn.Module):
        # 如果没指定device就使用net的device
        device = list(net.parameters())[0].device
    acc_sum, n = 0.0, 0
    with torch.no_grad():
        for X, y in data_iter:
            net.eval()  # 评估模式, 这会关闭dropout
            acc_sum += (net(X.to(device)).argmax(dim=1) == y.to(device)).float().sum().cpu().item()
            net.train()     # 改回训练模式
            n += y.shape[0]
    return acc_sum / n

if __name__ == "__main__":
    # 配置
    lr, num_epochs = 0.001, 5
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    batch_size = 256
    # 导入数据
    train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)
    # 网络、损失、优化方法
    net = LeNet()
    loss = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(net.parameters(), lr=lr)
    train_ch5(net, train_iter, test_iter, batch_size, loss, optimizer, device, num_epochs)

AlexNet

LeNet被其他机器学习方法超越了,因为在小数据集上取得好成绩,但是在大数据集上不行;而且计算开销大。想要设计一个多通道、多层、多参数的无法完成。从上面也可以看到层数少,通道少。

当时认为机器学习只做分类即可。但是有些科学家认为神经网络可以自己提取特征并且分类。在以前,特征是基于各种手工设计的函数从数据中提取出来的。机器学习只负责分类就好。例如,分类癌细胞与非癌细胞,机器学习要计算出每个细胞的大小,形状、细胞间的距离等等。这些都是设计函数计算得到的特征,然后把特征给机器学习分类。而且,计算机视觉的人认为数据和特征比选择一个机器学习的模型更重要

  • AlexNet首次证明了学习到的特征可以超越手工设计的特征,从而一举打破计算机视觉研究的前状。
  • AlexNet提出丢弃法。
  • AlexNet引入旋转和颜色变换等数据增强。

下面的代码与论文网络结构相比有改动,因为之前显存有限设置双数据流,现在不需要了。

class AlexNet(nn.Module):
    def __init__(self):
        super(AlexNet, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 96, 11, 4), # in_channels, out_channels, kernel_size, stride
            nn.ReLU(),
            nn.MaxPool2d(3, 2), # kernel_size, stride
            # 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
            nn.Conv2d(96, 256, 5, 1, 2),# in_channels, out_channels, kernel_size, stride, padding
            nn.ReLU(),
            nn.MaxPool2d(3, 2),
            # 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。前两个卷积层后不使用池化层来减小输入的高和宽
            nn.Conv2d(256, 384, 3, 1, 1),
            nn.ReLU(),
            nn.Conv2d(384, 384, 3, 1, 1),
            nn.ReLU(),
            nn.Conv2d(384, 256, 3, 1, 1),
            nn.ReLU(),
            nn.MaxPool2d(3, 2)
        )
         # 这里全连接层的输出个数比LeNet中的大数倍。使用丢弃层来缓解过拟合
        self.fc = nn.Sequential(
            nn.Linear(256*5*5, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            # 输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000
            nn.Linear(4096, 10),
        )

    def forward(self, img):
        feature = self.conv(img)
        output = self.fc(feature.view(img.shape[0], -1))
        return output

VGGNet

论文总结

import time
import torch
from torch import nn, optim

import d2l as d2l
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')


# 添加多少卷积层,设计多层vgg更加灵活
def vgg_block(num_convs, in_channels, out_channels):
    blk = []
    for i in range(num_convs):
        if i == 0:
            blk.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
        else:
            blk.append(nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1))
        blk.append(nn.ReLU())
    blk.append(nn.MaxPool2d(kernel_size=2, stride=2))
    return nn.Sequential(*blk)


def vgg(conv_arch, fc_features, fc_hidden_units=4096):
    net = nn.Sequential()
    # 卷积层部分
    for i, (num_convs, in_channels, out_channels) in enumerate(conv_arch):
        # 每经过一个vgg_block都会使宽高减半
        net.add_module("vgg_block_" + str(i+1), vgg_block(num_convs, in_channels, out_channels))
    # 全连接层部分
    net.add_module("fc", nn.Sequential(d2l.FlattenLayer(),  # 全连接层,一张图片要拉成一维数组
                                 nn.Linear(fc_features, fc_hidden_units),
                                 nn.ReLU(),
                                 nn.Dropout(0.5),
                                 nn.Linear(fc_hidden_units, fc_hidden_units),
                                 nn.ReLU(),
                                 nn.Dropout(0.5),
                                 nn.Linear(fc_hidden_units, 10)
                                ))
    return net

标签:nn,DIDL,self,笔记,channels,pytorch,train,device,net
来源: https://blog.csdn.net/Alter__/article/details/117440683

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有