深度学习入门基于python的的理论与实现(学习笔记).第六章 与学习相关的技巧(第四部分)

6.4正则化:
机器学习问题中,过拟合(overfit)是一个很常见的问题。过拟合指的是只能拟合训练数据,但不能很好地拟合不包含在训练数据中的其他数据的状态。机器学习的目标是提高泛化能力,即便是没有包含在训练数据里的未观测数据,也希望模型可以进行正确的识别。我们可以制作复杂的,表现力强的模型,但是相应地,抑制过拟合的技巧也很重要。
发生过拟合(high variance)的原因,主要有以下两个:

  • 模型拥有大量参数、表现力强
  • 训练数据少

解决过拟合问题的方法:

  • Get more data
  • Regularization
  • Find a more appropriate neural network architecture

我们故意满足发生过拟合的两个条件,制造过拟合现象,进行一次实验。

sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.multi_layer_net import MultiLayerNet
from common.optimizer import SGD

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)

# 为了再现过拟合,减少学习数据
x_train = x_train[:300]
t_train = t_train[:300]

# weight decay(权值衰减)的设定 =======================
weight_decay_lambda = 0 # 不使用权值衰减的情况
#weight_decay_lambda = 0.1
# ====================================================

network = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100, 100, 100], output_size=10,
                        weight_decay_lambda=weight_decay_lambda)
optimizer = SGD(lr=0.01)

max_epochs = 201
train_size = x_train.shape[0]
batch_size = 100

train_loss_list = []
train_acc_list = []
test_acc_list = []

iter_per_epoch = max(train_size / batch_size, 1)
epoch_cnt = 0

for i in range(1000000000):
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]

    grads = network.gradient(x_batch, t_batch)
    optimizer.update(network.params, grads)

    if i % iter_per_epoch == 0:
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)

        print("epoch:" + str(epoch_cnt) + ", train acc:" + str(train_acc) + ", test acc:" + str(test_acc))

        epoch_cnt += 1
        if epoch_cnt >= max_epochs:
            break


# 3.绘制图形==========
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, train_acc_list, marker='o', label='train', markevery=10)
plt.plot(x, test_acc_list, marker='s', label='test', markevery=10)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

结果为:
在这里插入图片描述
可知模型对训练时没有使用的一般数据(测试数据)拟合得不是很好。

  • 权值衰减(weight decay)(L2 Regularization)
    权值衰减是一直以来经常使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来以制过拟合。很多过拟合原本就是因为权重参数取值过大才发生的。
    在这里插入图片描述
    将上面代码修改下使用权值衰减后跑出结果为:
    在这里插入图片描述
    可见训练数据的识别精度和测试数据的识别精度之间有差距,但是与没有使用权值衰减的结果相比,差距变小了。

  • Dropoout:
    如果网络的模型变得很复杂,只用权值衰减就难以应对过拟合了。在这种情况下,经常使用Dropout。当然,如果没有过拟合,就不要使用Dropout(会损失精度)。
    Dropout 是一种在学习的过程中随机删除神经元的方法,一般用于全连接层中。训练时,随机选出隐藏层的神经元,然后将其删除。被删除的神经元不再进行信号的传递。训练时,每传递一次数据,就会随机选择要删除的神经元。然后,测试时,虽然会传递所有的神经元信号,但是对于各个神经元的输出,要乘上训练时的删除比例后再输出(保持该层输出的期望值不变)。
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
代码实现:

class Dropout:
    def __init__(self, dropout_ratio=0.5): # dropout_ratio一般选0.5
        self.dropout_ratio = dropout_ratio
        self.mask = None

    def forward(self, x, train_flg=True):
        if train_flg == True:
            retain_prob = 1 - self.dropout_ratio
            self.mask = np.random.binomial(1, p=retain_prob, size=x.shape)
            # self.mask = np.random.randn(*x.shape) > self.dropout_ratio         
            return x * self.mask
        else:
            return x * (1 - self.dropout_ratio)

    def backward(self, dout):
        return dout * self.mask

  • 超参数(hyper-parameter)的验证:
    超参数是指,比如各层的神经元数量、batch大小、参数更新时的学习率或权重衰减等。
    之前我们使用的数据集分成了训练数据和测试数据,训练数据用于学习,测试数据用于评估泛化能力。由此,就可以评估是否只过度拟合了训练数据(是否发生了过拟合),以及泛化能力如何等。下面我们要对超参数设置各种各样的值以进行验证。这里要注意的是,不能使用测试数据评估超参数的性能。这一点非常重要,但也容易被忽视。为什么不能用测试数据评估超参数的性能呢?这是因为如果使用测试数据调整超参数,超参数的值会对测试数据发生过拟合。因此,调整超参数时,必须使用超参数专用的确认数据。用于调整超参数的数据,一般称为验证数据(validation data)。
    分割数据集之前,要先打乱数据与标签,因为数据集中的数据可能存在偏向(比如,数据从“0”到“10”按顺序排列等)。
shuffle_data=True
(x_train, t_train), (x_test, t_test) = load_mnist(shuffle_data=True)
# 分割验证数据
validation_rate = 0.20
validation_num = int(x_train.shape[0] * validation_rate)
x_val = x_train[:validation_num]
t_val = t_train[:validation_num]
x_train = x_train[validation_num:]
t_train = t_train[validation_num:]

  • 超参数的最优化:
    进行超参数的最优化时,逐渐缩小超参数的“好值”的存在范围非常重要。所谓逐渐缩小范围,是指一开始先大致设定一个范围,从这个范围中随机选出一个超参数(采样),用这个采样到的值进行识别精度的评估;然后,多次重复该操作,观察识别精度的结果,根据这个结果缩小超参数的“好值”的范围。通过重复这一操作,就可以逐渐确定超参数的合适范围。
    超参数的范围只要“大致地指定”就可以了。所谓“大致地指定”,是指像0.001(10−3)到1000(103)这样,以“10 的阶乘”的尺度指定范围(也表述为“用对数尺度(log scale)指定”)。
    在这里插入图片描述
    在超参数的最优化中,要注意的是深度学习需要很长时间(比如,几天或几周)。因此,在超参数的搜索中,需要尽早放弃那些不符合逻辑的超参数。于是,在超参数的最优化中,减少学习的epoch,缩短一次评估所需的时间是一个不错的办法。

加粗样式
参考博文:
https://blog.csdn.net/weixin_42437114/article/details/106608441
关于范数的知识:https://blog.csdn.net/yangpan011/article/details/79461846

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值