深度学习笔记Week4

1、为什么要用卷积来学习呢?
图像都是用矩阵来表达的,学习的本质就是要抽象出特征,以边缘检测为例,它就是识别数字图像中亮度变化明显的点,这些点连接起来往往是物体的边缘。
所有基于卷积神经网络来学习的图像算法,都是通过不断的卷积来进行特征的抽象,直到实现网络的目标。

mnist手写数字识别

import torch
import matplotlib.pyplot as plt
# 利用DataLoader 来加载自己的数据集或者官方提供的数据集时,必须导入Dataloader
# transforms 属于 torchvision 中的模块,用于对数据进行预处理,主要是图像的处理(裁剪(Crop)翻转和旋转(Flip and Rotation)图像变换(resize)等),可以使用Compose将其链接在一起。
from torchvision import transforms, datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim

os.environ["CUDA_VISIBLE_DEVICES"] = "0"
#加载数据集
batch_size = 64
#我们拿到的图片是pillow,我们要把他转换成模型里能训练的tensor也就是张量的格式
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307, ), (0.3081, ))])
#加载训练集
train_dataset = datasets.MNIST(root = '../dataset/mnist', train = True, download = True, transform = transform)
train_loader = DataLoader(train_dataset, batch_size = batch_size, shuffle = True)
#加载测试集
test_dataset = datasets.MNIST(root = '../dataset/mnist/', train = False, download = True, transform = transform)
test_loader = DataLoader(test_dataset, shuffle = False, batch_size = batch_size)

#构建网络
class ConvolutionNet(torch.nn.Module):
    def __init__(self):
        super(ConvolutionNet,self).__init__()
        # 卷积层① 1是指输入的Channel,灰色图像是1维的;10是指输出的Channel,
        # 也可以说第一个卷积层需要10个卷积核;kernel_size=5,卷积核大小是5*5;
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size = 5)   
        # 卷积层② 需要20个卷积核
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size = 5)
        # 池化层① 2*2采样
        self.pooling = torch.nn.MaxPool2d(2)
        # 分类用的线性层,320就是指要进行全连接操作时,输入的特征维度
        self.fc = torch.nn.Linear(320, 10) 
    # 计算的过程
    def forward(self, x):
        # Flatten data from (n, 1, 28, 28) to (n, 784)
        batch_size = x.size(0) #这里面的0是x大小第1个参数,自动获取batch大小
        #输入x经过一个卷积层,之后经历一个池化层,最后用relu做激活
        x = F.relu(self.pooling(self.conv1(x)))
        #再经历上面的过程
        x = F.relu(self.pooling(self.conv2(x)))
        #为了给我们最后一个全连接的线性层用
        #我们要把一个二维的图片(实际上这里已经是处理过的)20x4x4张量变成一维的
        x = x.view(batch_size, -1)# flatten
        #经过线性层,确定他是0~9每一个数的概率
        x = self.fc(x)
        return x
model = Net()#实例化模型
#把计算迁移到GPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)

#定义一个损失函数,来计算我们模型输出的值和标准值的差距
criterion = torch.nn.CrossEntropyLoss()
#定义一个优化器,训练模型咋训练的,就靠这个,他会反向的更改相应层的权重
optimizer = optim.SGD(model.parameters(),lr=0.1,momentum=0.5)#lr为学习率


def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):#每次取一个样本
        inputs, target = data
        inputs, target = inputs.to(device), target.to(device)
        #优化器清零
        optimizer.zero_grad()
        # 正向计算一下
        outputs = model(inputs)
        #计算损失
        loss = criterion(outputs, target)
        #反向求梯度
        loss.backward()
        #更新权重
        optimizer.step()
        #把损失加起来
        running_loss += loss.item()
        #每300次输出一下数据
        if batch_idx % 300 == 299:
            print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 2000))
            running_loss = 0.0

def test():
    correct = 0
    total = 0
    with torch.no_grad():#不用算梯度
        for data in test_loader:
            inputs, target = data
            inputs, target = inputs.to(device), target.to(device)
            outputs = model(inputs)
            #我们取概率最大的那个数作为输出
            _, predicted = torch.max(outputs.data, dim=1)
            total += target.size(0)
            #计算正确率
            correct += (predicted == target).sum().item()
    print('Accuracy on test set: %d %% [%d/%d]' % (100 * correct / total, correct, total))


if __name__=='__main__':
    for epoch in range(10):
        train(epoch)
        if epoch % 10 == 9:
            test()

随机梯度下降(Stochastic gradient descent),简称sgd。
(1) 学习率大小和策略选择困难
(2) 学习率不够智能,对参数的各个维度一视同仁。
(3) 同时面临局部极值和鞍点的问题。
梯度下降算法改进:
1.Momentum 动量法
动量法做的很简单,相信之前的梯度。如果梯度方向不变,就越发更新的快,反之减弱当前梯度。
在这里插入图片描述
在这里插入图片描述
2.Adam算法
Adam对梯度的一阶和二阶都进行了估计与偏差修正,使用梯度的一阶矩估计和二阶矩估计来动态调整每个参数的学习率。
根据梯度对参数更新的幅度进行了动态调整,所以Adam对学习率没有那么敏感。

Adam每次迭代参数的学习步长都有一个确定的范围,不会因为很大的梯度导致很大的学习步长,参数的值比较稳定,但是它也并非真的是参数不敏感的,学习率在训练的后期可仍然可能不稳定导致无法收敛到足够好的值,泛化能力较差。

3.什么是泛化能力?
泛化能力指,机器学习方法训练出来一个模型,对于已知的数据(训练集)性能表现良好,对于未知的数据(测试集)也应该表现良好的机器能力。

试集的误差,也被称为泛化误差。

在机器学习中,泛化能力的好坏,最直观表现出来的就是模型的过拟合(overfitting)与欠拟合(underfitting)。

4.如何提高神经网络的泛化能力?

  1. 使用更多数据
    在有条件的前提下,尽可能多地获取训练数据是最理想的方法,更多的数据可以让模型得到充分的学习,也更容易提高泛化能力。

  2. 使用更大批次
    在相同迭代次数和学习率的条件下,每批次采用更多的数据将有助于模型更好的学习到正确的模式,模型输出结果也会更加稳定。

  3. 调整数据分布
    大多数场景下的数据分布是不均匀的,模型过多地学习某类数据容易导致其输出结果偏向于该类型的数据,此时通过调整输入的数据分布可以一定程度提高泛化能力。

  4. 调整目标函数
    调整目标函数使误差小的样本计算损失的梯度比误差大的样本更小,进而有效地平衡样本作用,提高模型泛化能力。

  5. 调整网络结构
    浅层卷积神经网络中,参数量较往往使模型的泛化能力不足而导致欠拟合,此时通过叠加卷积层可以有效地增加网络参数,提高模型表达能力;在深层卷积网络中,若没有充足的训练数据则容易导致模型过拟合,此时通过简化网络结构减少卷积层数可以起到提高模型泛化能力的作用。

  6. 数据增强/数据增广
    在有限数据的前提下通过平移、旋转、加噪声等一些列变换来增加训练数据,同类数据的表现形式也变得更多样,有助于模型提高泛化能力。transforms模块?

  7. 权值正则化
    权值正则化就是通常意义上的正则化,一般是在损失函数中添加一项权重矩阵的正则项作为惩罚项,用来惩罚损失值较小时网络权重过大的情况,此时往往是网络权值过拟合了数据样本。

  8. 屏蔽网络节点
    该方法可以认为是网络结构上的正则化,通过随机性地屏蔽某些神经元的输出让剩余激活的神经元作用,可以使模型的容错性更强。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fuhanghang@yeah.net

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值