当前位置:   article > 正文

深度学习——Dropout的基本用法

dropout

一、Dropout是什么:

Dropout 是一种在学习的过程中随机删除神经元的方法。训练时,随机选出隐藏层的神经元,然后将其删除。被删除的神经元不再进行信号的传递,如下图所示 。训练时,每传递一次数据,就会随机选择要删除的神经元。 然后,测试时,虽然会传递所有的神经元信号,但是对于各个神经元的输出, 要乘上训练时的删除比例后再输出。
Dropout的核心思想是在训练神经网络时,随机地关闭一些神经元(或节点)它们以及与下一层神经元之间的连接。这种随机关闭的过程模拟了在网络中删除了一些神经元的情况,从而导致网络不依赖于单个神经元或神经元组合,减少了过于简单的风险。

左边的(a)图是一般的神经网络,右边的(b)图是应用了 Dropout 的网络。
Dropout 通过随机选择并删除神经元,停止向前传递信号。

二、Dropout的工作原理和特点:

  1. 随机关闭神经元:在每个神经元被关闭的概率是相同的,这个概率是一个超参数。

  2. 前向传播时的关闭:在前向传播过程中,被关闭的神经元的输出值被设为零。这意味着每个神经元都可能在每个繁殖中被关闭,而不是始终激活。

  3. 逆向传播时的开启:在逆向传播过程中,被关闭的神经元不会接收到大量更新,它们的权重不会被调整。这意味着只有那些真正动员的神经元参与了权重更新。

  4. 集成学习效果:Dropout可以被调用是一种可以集成学习(Ensemble Learning)的方法,因为每次训练迭代都相当于训练了一个不同的子网络。通过平均或投票来集成多个子网络的预测,降低模型的仰角,提高泛化性能。

  5. 正则化效果:Dropout作为一种正则化技术,通常能够改善模型的泛化能力,减少过度,特别是在训练数据稀疏或较小的情况下。

  6. 关闭时的:在测试或推理训练时,Dropout通常是关闭的,所有神经元都保持开启状态。但是,为了保持测试的一致性,通常会在每个神经元的输出上乘以时关闭的概率的倒数,以平衡输出值的期望。

总之,Dropout是一种强大的正则化技术,用于改善神经网络的泛化性能,并减少过度的风险。它已经被广泛用于深度学习中的各种任务,包括分类、语音识别、自然语言处理等。 

三、简化的 Dropout 类的代码示例:

  1. class Dropout:
  2. def __init__(self, dropout_ratio=0.5):
  3. self.dropout_ratio = dropout_ratio # 指定丢弃的比例
  4. self.mask = None # 用于存储丢弃的掩码
  5. def forward(self, x, train_flg=True):
  6. if train_flg:
  7. self.mask = np.random.rand(*x.shape) > self.dropout_ratio # 生成与输入形状相同的随机掩码
  8. return x * self.mask # 在前向传播中应用掩码,以实现丢弃部分神经元
  9. else:
  10. return x * (1.0 - self.dropout_ratio) # 在测试或推理时,按比例缩放输出
  11. def backward(self, dout):
  12. return dout * self.mask # 反向传播时,根据之前生成的掩码进行相应的乘法操作

这个Dropout类有以下主要方法:

  • __init__: 类的初始化方法,指定用于丢弃的比例dropout_ratio,默认为0.5。

  • forward:正向传播方法,接受输入x和一个训练布尔值train_flg,用于判断是否为一个模式。如果在训练模式下,它会生成一个与输入x形状相同的随机掩码self.mask,输入x与掩码相乘,以实现丢弃一部分神经元。在测试或推理模式下,它会按比例缩放输出,以保持输出的期望值不变。

  • backward:逆向传播方法,接受最小dout,根据之前生成的预留码self.mask,对最小进行相应的乘法操作,以实现逆向传播。

四、 使用MNIST数据集进行验证,以确认Dropout的效果

代码如下:

  1. import os
  2. import sys
  3. sys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. from dataset.mnist import load_mnist
  7. from common.multi_layer_net_extend import MultiLayerNetExtend
  8. # from common.trainer import Trainer
  9. from common.optimizer import *
  10. class Trainer:
  11. def __init__(self, network, x_train, t_train, x_test, t_test,
  12. epochs=20, mini_batch_size=100,
  13. optimizer='SGD', optimizer_param={'lr': 0.01},
  14. evaluate_sample_num_per_epoch=None, verbose=True):
  15. self.network = network
  16. self.verbose = verbose
  17. self.x_train = x_train
  18. self.t_train = t_train
  19. self.x_test = x_test
  20. self.t_test = t_test
  21. self.epochs = epochs
  22. self.batch_size = mini_batch_size
  23. self.evaluate_sample_num_per_epoch = evaluate_sample_num_per_epoch
  24. # optimzer
  25. optimizer_class_dict = {'sgd': SGD, 'momentum': Momentum, 'nesterov': Nesterov,
  26. 'adagrad': AdaGrad, 'rmsprpo': RMSprop, 'adam': Adam}
  27. self.optimizer = optimizer_class_dict[optimizer.lower()](**optimizer_param)
  28. self.train_size = x_train.shape[0]
  29. self.iter_per_epoch = max(self.train_size / mini_batch_size, 1)
  30. self.max_iter = int(epochs * self.iter_per_epoch)
  31. self.current_iter = 0
  32. self.current_epoch = 0
  33. self.train_loss_list = []
  34. self.train_acc_list = []
  35. self.test_acc_list = []
  36. def train_step(self):
  37. batch_mask = np.random.choice(self.train_size, self.batch_size)
  38. x_batch = self.x_train[batch_mask]
  39. t_batch = self.t_train[batch_mask]
  40. grads = self.network.gradient(x_batch, t_batch)
  41. self.optimizer.update(self.network.params, grads)
  42. loss = self.network.loss(x_batch, t_batch)
  43. self.train_loss_list.append(loss)
  44. if self.verbose: print("train loss:" + str(loss))
  45. if self.current_iter % self.iter_per_epoch == 0:
  46. self.current_epoch += 1
  47. x_train_sample, t_train_sample = self.x_train, self.t_train
  48. x_test_sample, t_test_sample = self.x_test, self.t_test
  49. if not self.evaluate_sample_num_per_epoch is None:
  50. t = self.evaluate_sample_num_per_epoch
  51. x_train_sample, t_train_sample = self.x_train[:t], self.t_train[:t]
  52. x_test_sample, t_test_sample = self.x_test[:t], self.t_test[:t]
  53. train_acc = self.network.accuracy(x_train_sample, t_train_sample)
  54. test_acc = self.network.accuracy(x_test_sample, t_test_sample)
  55. self.train_acc_list.append(train_acc)
  56. self.test_acc_list.append(test_acc)
  57. if self.verbose: print(
  58. "=== epoch:" + str(self.current_epoch) + ", train acc:" + str(train_acc) + ", test acc:" + str(
  59. test_acc) + " ===")
  60. self.current_iter += 1
  61. def train(self):
  62. for i in range(self.max_iter):
  63. self.train_step()
  64. test_acc = self.network.accuracy(self.x_test, self.t_test)
  65. if self.verbose:
  66. print("=============== Final Test Accuracy ===============")
  67. print("test acc:" + str(test_acc))
  68. (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
  69. # 为了再现过拟合,减少学习数据
  70. x_train = x_train[:300]
  71. t_train = t_train[:300]
  72. # 设定是否使用Dropuout,以及比例 ========================
  73. use_dropout = False # 不使用Dropout的情况下为False
  74. dropout_ratio = 0.2
  75. # ====================================================
  76. network = MultiLayerNetExtend(input_size=784, hidden_size_list=[100, 100, 100, 100, 100, 100],
  77. output_size=10, use_dropout=use_dropout, dropout_ration=dropout_ratio)
  78. trainer = Trainer(network, x_train, t_train, x_test, t_test,
  79. epochs=301, mini_batch_size=100,
  80. optimizer='sgd', optimizer_param={'lr': 0.01}, verbose=True)
  81. trainer.train()
  82. train_acc_list, test_acc_list = trainer.train_acc_list, trainer.test_acc_list
  83. # 绘制图形==========
  84. markers = {'train': 'o', 'test': 's'}
  85. x = np.arange(len(train_acc_list))
  86. plt.plot(x, train_acc_list, marker='o', label='train', markevery=10)
  87. plt.plot(x, test_acc_list, marker='s', label='test', markevery=10)
  88. plt.xlabel("epochs")
  89. plt.ylabel("accuracy")
  90. plt.ylim(0, 1.0)
  91. plt.legend(loc='lower right')
  92. plt.show()

得出的效果:

 左边没有使用Dropout,右边使用了Dropout

通过使用 Dropout ,训练数据和测试数据的识别精度的差距变小了。并且,训练数据也没有到达100% 的识别精度。像这样,通过使用Dropout,即便是表现力强的网络,也可以抑制过拟合。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/826351
推荐阅读
相关标签
  

闽ICP备14008679号