当前位置: 首页 > wzjs >正文

网站建设 风险防控电商创客网站建设方案

网站建设 风险防控,电商创客网站建设方案,网站添加支付功能,久久建筑网的文件是免费下载吗本章将介绍神经网络的学习中的一些重要观点,主题涉及寻找最优权重 参数的最优化方法、权重参数的初始值、超参数的设定方法等。 此外,为了 应对过拟合,本章还将介绍权值衰减、 Dropout 等正则化方法,并进行实现。 最后将对近年来…
本章将介绍神经网络的学习中的一些重要观点,主题涉及寻找最优权重 参数的最优化方法、权重参数的初始值、超参数的设定方法等。
此外,为了 应对过拟合,本章还将介绍权值衰减、 Dropout 等正则化方法,并进行实现。
最后将对近年来众多研究中使用的 Batch Normalization 方法进行简单的介绍。
使用本章介绍的方法,可以高效地进行神经网络(深度学习)的学习,提高 识别精度。

6.1 参数的更新

神经网络的学习的目的是找到使损失函数的值尽可能小的参数。这是寻 找最优参数的问题,解决这个问题的过程称为 最优化(optimization)。遗憾的是, 神经网络的最优化问题非常难。这是因为参数空间非常复杂,无法轻易找到 最优解(无法使用那种通过解数学式一下子就求得最小值的方法)。而且,在 深度神经网络中,参数的数量非常庞大,导致最优化问题更加复杂。
在前几章中,为了找到最优参数,我们将参数的梯度(导数)作为了线索。 使用参数的梯度,沿梯度方向更新参数,并重复这个步骤多次,从而逐渐靠 近最优参数,这个过程称为 随机梯度下降法(stochastic gradient descent), 简称SGD SGD是一个简单的方法,不过比起胡乱地搜索参数空间,也算是“聪明”的方法。但是,根据不同的问题,也存在比 SGD更加聪明的方法。本节我们将指出 SGD 的缺点,并介绍 SGD 以外的其他最优化方法。

6.1.1 探险家的故事

有一个性情古怪的探险家。他在广袤的干旱地带旅行,坚持寻找幽 深的山谷。他的目标是要到达最深的谷底(他称之为“至深之地”)。这 也是他旅行的目的。并且,他给自己制定了两个严格的“规定”:一个 是不看地图;另一个是把眼睛蒙上。因此,他并不知道最深的谷底在这 个广袤的大地的何处,而且什么也看不见。在这么严苛的条件下,这位 探险家如何前往“至深之地”呢?他要如何迈步,才能迅速找到“至深 之地”呢?
寻找最优参数时,我们所处的状况和这位探险家一样,是一个漆黑的世界。我们必须在没有地图、不能睁眼的情况下,在广袤、复杂的地形中寻找 “至深之地”。大家可以想象这是一个多么难的问题。
在这么困难的状况下,地面的坡度显得尤为重要。探险家虽然看不到周 围的情况,但是能够知道当前所在位置的坡度(通过脚底感受地面的倾斜状况)。 于是,朝着当前所在位置的坡度最大的方向前进,就是 SGD的策略。勇敢 的探险家心里可能想着只要重复这一策略,总有一天可以到达“至深之地”。

6.1.2 SGD

让大家感受了最优化问题的难度之后,我们再来复习一下 SGD。用数学式可以将 SGD 写成如下的式( 6 . 1 )。

这里把需要更新的权重参数记为W,把损失函数关于W的梯度记为\frac{\partial L}{\partial W}

η表示学习率,实际上会取0.010.001这些事先决定好的值。式子中的←表示用右边的值更新左边的值。如式(6.1)所示,SGD是朝着梯度方向只前进一定距离的简单方法。现在,我们将SGD实现为一个Python类(为方便 后面使用,我们将其实现为一个名为SGD的类)。

class SGD:"""随机梯度下降法(Stochastic Gradient Descent)"""def __init__(self, lr=0.01):self.lr = lrdef update(self, params, grads):for key in params.keys():params[key] -= self.lr * grads[key] 
这里,进行初始化时的参数 lr表示learning rate(学习率) 。这个学习率 会保存为实例变量。此外,代码段中还定义了 update(params, grads)方法 , 这个方法在 SGD 中会被反复调用。参数 params grads(与之前的神经网络 的实现一样)是字典型变量,按 params['W1'] grads['W1']的形式,分别保 存了权重参数和它们的梯度。
使用这个 SGD类,可以按如下方式进行神经网络的参数的更新(下面的代码是不能实际运行的伪代码)。

这里首次出现的变量名 optimizer表示“优化器”的意思 ,这里 由 SGD 承担这个角色。参数的更新由 optimizer负责完成。我们在这里需要 做的只是将参数和梯度的信息传给 optimizer。 像这样,通过单独实现进行最优化的类,功能的模块化变得更简单。
比如,后面我们马上会实现另一个最优化方法 Momentum,它同样会实现 成拥有 update(params, grads)这个共同方法的形式。这样一来,只需要将 optimizer = SGD() 这一语句换成 optimizer = Momentum() ,就可以从 SGD 换为 Momentum
很多深度学习框架都实现了各种最优化方法,并且提供了可以简单切换这些方法的构造。比如 Lasagne深度学习框架,在updates.py 这个文件中以函数的形式集中实现了最优化方法。用户可以从中选 择自己想用的最优化方法。

6.1.3 SGD的缺点

虽然 SGD简单,并且容易实现,但是在解决某些问题时可能 没有效率 。 这里,在指出 SGD的缺点之际,我们来思考一下求下面这个函数的最小值 的问题。
如图 6-1 所示,式( 6 . 2 )表示的函数是向 x轴方向延伸的“碗”状函数。 实际上,式( 6 . 2 )的等高线呈向 x 轴方向延伸的椭圆状。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D# 生成数据
x = np.linspace(-50, 50, 200)  # 扩大范围以更好展示形状
y = np.linspace(-50, 50, 200)
X, Y = np.meshgrid(x, y)
Z = (1/20) * X**2 + Y**2# 创建三维曲面图
fig = plt.figure(figsize=(14, 6))# 三维曲面子图
ax1 = fig.add_subplot(121, projection='3d')
surf = ax1.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8, rstride=1, cstride=1)
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_zlabel('Z')
ax1.set_title('3D Surface Plot')
ax1.view_init(elev=30, azim=45)  # 调整视角# 添加颜色条
fig.colorbar(surf, ax=ax1, shrink=0.5, aspect=10)# 二维等高线子图
ax2 = fig.add_subplot(122)
contour = ax2.contour(X, Y, Z, levels=20, cmap='viridis')
ax2.clabel(contour, inline=True, fontsize=8)  # 添加等高线标签
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_title('Contour Plot')
fig.colorbar(contour, ax=ax2, shrink=0.5, aspect=10)plt.tight_layout()
plt.show()

现在看一下式( 6 . 2)表示的函数的梯度。如果用图表示梯度的话,则如 图 6-2 所示。这个梯度的特征是, y 轴方向上大, x轴方向上小。换句话说, 就是 y 轴方向的坡度大,而 x轴方向的坡度小。这里需要注意的是,虽然式 ( 6 . 2 )的最小值在 ( x, y ) = (0 , 0) 处,但是图 6-2中的梯度在很多地方并没有指 向 (0 , 0)
import numpy as np
import matplotlib.pyplot as plt# 生成数据
x = np.linspace(-10, 10, 20)  # 缩小范围以便清晰显示梯度
y = np.linspace(-10, 10, 20)
X, Y = np.meshgrid(x, y)# 计算函数值和梯度
Z = (1/20) * X**2 + Y**2
grad_x = X / 10  # ∂f/∂x = x/10
grad_y = 2 * Y   # ∂f/∂y = 2y# 创建图形
plt.figure(figsize=(10, 6))# 绘制梯度场(箭头图)
plt.quiver(X, Y, grad_x, grad_y,scale=20,      # 控制箭头长度scale_units='width',color='r',     # 箭头颜色edgecolor='k', # 箭头边缘颜色linewidth=0.5)# 叠加等高线
contour = plt.contour(X, Y, Z, levels=10, colors='b', linestyles='dashed')
plt.clabel(contour, inline=True, fontsize=8)  # 添加等高线标签# 图形设置
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Gradient Field of f(x,y) = (1/20)x² + y²')
plt.grid(True, linestyle='--', alpha=0.7)
plt.axis('equal')  # 保持坐标轴比例一致plt.show()
我们来尝试对图 6-1 这种形状的函数应用 SGD 。从 (x, y) = (7.0, 2.0)处 (初始值)开始搜索,结果如图 6-3 所示。
在图 6-3 中, SGD呈“之”字形移动。这是一个相当低效的路径。也就是说, SGD 的缺点是,如果函数的形状非均向( anisotropic),比如呈延伸状,搜索 的路径就会非常低效。因此,我们需要比单纯朝梯度方向前进的 SGD更聪 明的方法。 SGD 低效的根本原因是,梯度的方向并没有指向最小值的方向。
# 导入数值计算库
import numpy as np
# 导入绘图库
import matplotlib.pyplot as plt
# 导入3D绘图工具包
from mpl_toolkits.mplot3d import Axes3D# 定义目标函数 Z = (1/20)X² + Y²
def f(x, y):return (x**2)/20 + y**2# 定义目标函数的梯度(导数)
def grad_f(x, y):# X方向的梯度分量:∂Z/∂X = X/10grad_x = x / 10# Y方向的梯度分量:∂Z/∂Y = 2Ygrad_y = 2 * yreturn np.array([grad_x, grad_y])  # 返回梯度向量# 初始化随机梯度下降参数
start_x, start_y = -7.0, 2.0    # 起始点坐标
learning_rate = 0.1             # 学习率(步长)
iterations = 100                # 最大迭代次数# 初始化存储路径的列表
x_vals, y_vals = [start_x], [start_y]
current_x, current_y = start_x, start_y  # 当前位置初始化为起点# 执行随机梯度下降算法
for _ in range(iterations):grad = grad_f(current_x, current_y)  # 计算当前点的梯度# 更新参数:向梯度反方向移动(学习率 × 梯度)current_x -= learning_rate * grad[0]current_y -= learning_rate * grad[1]# 记录新的位置到路径列表x_vals.append(current_x)y_vals.append(current_y)# 创建画布和子图布局
fig = plt.figure(figsize=(12, 5))# ==== 三维曲面图 ====
# 创建第一个子图(3D投影)
ax1 = fig.add_subplot(121, projection='3d')
# 生成网格数据用于绘制曲面
X = np.linspace(-8, 8, 100)   # X轴范围-8到8,生成100个点
Y = np.linspace(-8, 8, 100)   # Y轴范围同上
# 生成二维网格坐标矩阵
X, Y = np.meshgrid(X, Y)
# 计算对应的Z值
Z = (X**2)/20 + Y**2
# 绘制3D曲面,使用渐变色填充
ax1.plot_surface(X, Y, Z, cmap='viridis', alpha=0.7)
# 绘制优化路径:红色折线带圆点
ax1.plot(x_vals, y_vals,f(np.array(x_vals), np.array(y_vals)),  # Z轴坐标根据函数计算color='red', marker='o', markersize=3, linewidth=1)
# 设置坐标轴标签
ax1.set_xlabel('X'), ax1.set_ylabel('Y'), ax1.set_zlabel('Z')
# 设置标题和标题位置
ax1.set_title('SGD Path on 3D Surface', y=0.9)# ==== 二维等高线图 ====
# 创建第二个子图(普通二维坐标)
ax2 = fig.add_subplot(122)
# 生成等高线数据:20条对数间隔的等高线
contour = ax2.contour(X, Y, Z,levels=np.logspace(-2, 3, 20),  # 等高线层级范围cmap='viridis')                  # 颜色映射
# 添加等高线数值标签
ax2.clabel(contour, inline=True, fontsize=8)
# 绘制优化路径:红色带圆点折线
ax2.plot(x_vals, y_vals, 'r-o', label='SGD Path')
# 标记起点(蓝色实心圆)
ax2.scatter(start_x, start_y,color='blue', s=50,label='Start')
# 标记最小值点(绿色实心圆)
ax2.scatter(0, 0,color='green', s=50,label='Minimum')
# 设置坐标轴标签
ax2.set_xlabel('X'), ax2.set_ylabel('Y')
# 设置标题和网格
ax2.set_title('SGD Path on Contour Plot')
ax2.legend()    # 显示图例
ax2.grid(True)  # 显示网格线# 调整子图间距并显示图形
plt.tight_layout()
plt.show()

6.1.4 Momentum

Momentum是“动量”的意思,和物理有关。用数学式表示Momentum方法,如下所示。

和前面的SGD一样,W表示要更新的权重参数, ∂L/∂W表示损失函数关于W的梯度,η表示学习率。这里新出现了一个变量v,对应物理上的速度

式(6.3)表示了物体在梯度方向上受力,在这个力的作用下,物体的速度增加这一物理法则。如图6-4所示,Momentum方法给人的感觉就像是小球在地面上滚动。

实例变量v会保存物体的速度。初始化时,v中什么都不保存,但当第一次调用update()时,v会以字典型变量的形式保存与参数结构相同的数据。剩余的代码部分就是将式(6.3)、式(6.4)写出来,很简单。 现在尝试使用Momentum解决式(6.2)的最优化问题,如图6-5所示。
图6-5中,更新路径就像小球在碗中滚动一样。和SGD相比,我们发现“ 之”字形的“程度”减轻了。这是因为虽然x轴方向上受到的力非常小,但是一直在同一方向上受力,所以朝同一个方向会有一定的加速。反过来,虽然y轴方向上受到的力很大,但是因为交互地受到正方向和反方向的力,它们会互相抵消,所以y轴方向上的速度不稳定。因此,和SGD时的情形相比,可以更快地朝x轴方向靠近,减弱“之”字形的变动程度。

6.1.5 AdaGrad

在神经网络的学习中,学习率(数学式中记为η)的值很重要。学习率过小,会导致学习花费过多时间;反过来,学习率过大,则会导致学习发散而不能正确进行。
在关于学习率的有效技巧中,有一种被称为 学习率衰减(learning rate decay)的方法,即随着学习的进行,使学习率逐渐减小。实际上,一开始“多”学,然后逐渐“少”学的方法,在神经网络的学习中经常被使用。
逐渐减小学习率的想法,相当于将“全体”参数的学习率值一起降低。而AdaGrad 进一步发展了这个想法,针对“一个一个”的参数,赋予其“定制”的值。
AdaGrad会为参数的每个元素适当地调整学习率,与此同时进行学习(AdaGrad的Ada来自英文单词Adaptive,即“适当的”的意思)。下面,让我们用数学式表示AdaGrad的更新方法。
和前面的SGD一样,W表示要更新的权重参数,∂L/∂W 表示损失函数关于W的梯度,η表示学习率。这里新出现了 变量h,如式(6.5)所示,它保存了以前的所有梯度值的平方和(式(6.5)中的⨀表示对应矩阵元素的乘法)。然后,在更新参数时,通过乘以1/ \sqrt{h} ,就可以调整学习的尺度。这意味着,参数的元素中变动较大(被大幅更新)的元素的学习率将变小。也就是说,可以按参数的元素进行学习率衰减,使变动大的参数的学习率逐渐减小。
AdaGrad会记录过去所有梯度的平方和。因此,学习越深入,更新的幅度就越小。实际上,如果无止境地学习,更新量就会变为 0,完全不再更新。为了改善这个问题,可以使用 RMSProp方法。RMSProp方法并不是将过去所有的梯度一视同仁地相加,而是逐渐地遗忘过去的梯度,在做加法运算时将新梯度的信息更多地反映出来。这种操作从专业上讲,称为“ 指数移动平均”,呈指数函数式地减小过去的梯度的尺度。
现在来实现 AdaGrad。AdaGrad 的 实 现 过 程 如 下 所 示(源 代 码 在common/optimizer.py中)。
这里需要注意的是,最后一行加上了微小值 1e-7。这是为了防止当 self.h[key] 中有 0 时,将 0用作除数的情况。在很多深度学习的框架中,这 个微小值也可以设定为参数,但这里我们用的是 1e-7 这个固定值。
现在,让我们试着使用 AdaGrad 解决式( 6 . 2 )的最优化问题,结果如图6-6 所示。

6.1.6 Adam

Momentum参照小球在碗中滚动的物理规则进行移动,AdaGrad为参数的每个元素适当地调整更新步伐。如果将这两个方法融合在一起会怎么样呢?这就是Adam方法的基本思路 。
Adam是2015年提出的新方法。它的理论有些复杂,直观地讲,就是融合了Momentum和AdaGrad的方法。通过组合前面两个方法的优点,有望实现参数空间的高效搜索。
此外,进行超参数的“ 偏置校正”也是Adam的特征。这里不再进行过多的说明,详细内容请参考原作者的论文[8]。关于Python的实现,common/optimizer.py中将其实现为了Adam类,有兴趣的读者可以参考。现在,我们试着使用Adam解决式(6.2)的最优化问题,结果如图6-7所示。

在图6-7中,基于Adam的更新过程就像小球在碗中滚动一样。虽然Momentun也有类似的移动,但是相比之下,Adam的小球左右摇晃的程度有所减轻。这得益于学习的更新程度被适当地调整了。

Adam会设置 3个超参数。一个是学习率(论文中以α出现),另外两个是一次momentum系数β1和二次momentum系数β2。根据论文,标准的设定值是β1为 0.9,β2 为 0.999。设置了这些值后,大多数情况下都能顺利运行。

6.1.7 使用哪种更新方法呢

到目前为止,我们已经学习了 4种更新参数的方法。这里我们来比较一 下这 4 种方法(源代码在 ch06/optimizer_compare_naive.py 中)。
如图 6-8所示,根据使用的方法不同,参数更新的路径也不同。只看这 个图的话, AdaGrad似乎是最好的,不过也要注意,结果会根据要解决的问 题而变。并且,很显然,超参数(学习率等)的设定值不同,结果也会发生变化。
# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from collections import OrderedDict
from common.optimizer import *def f(x, y):return x**2 / 20.0 + y**2def df(x, y):return x / 10.0, 2.0*yinit_pos = (-7.0, 2.0)
params = {}
params['x'], params['y'] = init_pos[0], init_pos[1]
grads = {}
grads['x'], grads['y'] = 0, 0optimizers = OrderedDict()
optimizers["SGD"] = SGD(lr=0.95)
optimizers["Momentum"] = Momentum(lr=0.1)
optimizers["AdaGrad"] = AdaGrad(lr=1.5)
optimizers["Adam"] = Adam(lr=0.3)idx = 1for key in optimizers:optimizer = optimizers[key]x_history = []y_history = []params['x'], params['y'] = init_pos[0], init_pos[1]for i in range(30):x_history.append(params['x'])y_history.append(params['y'])grads['x'], grads['y'] = df(params['x'], params['y'])optimizer.update(params, grads)x = np.arange(-10, 10, 0.01)y = np.arange(-5, 5, 0.01)X, Y = np.meshgrid(x, y) Z = f(X, Y)# for simple contour line  mask = Z > 7Z[mask] = 0# plot plt.subplot(2, 2, idx)idx += 1plt.plot(x_history, y_history, 'o-', color="red")plt.contour(X, Y, Z)plt.ylim(-10, 10)plt.xlim(-10, 10)plt.plot(0, 0, '+')#colorbar()#spring()plt.title(key)plt.xlabel("x")plt.ylabel("y")plt.show()

上面我们介绍了 SGD Momentum AdaGrad Adam 这4种方法,那 么用哪种方法好呢?非常遗憾,(目前)并不存在能在所有问题中都表现良好 的方法。这 4种方法各有各的特点,都有各自擅长解决的问题和不擅长解决 的问题。
很多研究中至今仍在使用 SGD Momentum AdaGrad也是值得一试 的方法。最近,很多研究人员和技术人员都喜欢用 Adam。本书将主要使用 SGD 或者 Adam ,读者可以根据自己的喜好多多尝试。

6.1.8 基于MNIST数据集的更新方法的比较

我 们 以 手 写 数 字 识 别 为 例,比 较 前 面 介 绍 的 SGD Momentum、 AdaGrad Adam 4种方法,并确认不同的方法在学习进展上有多大程度 的差异。先来看一下结果,如图 6-9 所示(源代码在ch06/optimizer_compare_ mnist.py 中)。
# coding: utf-8
import os
import sys
sys.path.append(os.pardir)  # 将父目录加入系统路径,用于导入自定义模块# 导入必要的第三方库
import matplotlib.pyplot as plt  # 绘图库
import numpy as np  # 数值计算库# 从自定义模块导入所需功能
from dataset.mnist import load_mnist  # MNIST数据集加载函数(当前未使用)
from common.util import smooth_curve  # 平滑曲线的工具函数
from common.multi_layer_net import MultiLayerNet  # 多层神经网络类
from common.optimizer import *  # 所有优化器类(SGD/Momentum/AdaGrad/Adam)# ======================
# 主程序开始
# ======================# 0: 加载MNIST数据集(改用TensorFlow Keras版本)
# 使用TensorFlow内置的MNIST数据集(无需手动下载)
(x_train, t_train), (x_test, t_test) = mnist.load_data()# 数据预处理
# 将图像数据展平为向量(28x28 -> 784),并归一化到[0,1]范围
x_train = x_train.reshape(-1, 784).astype(np.float32)/255.0
x_test = x_test.reshape(-1, 784).astype(np.float32)/255.0# 将标签转换为one-hot编码格式
t_train = np.eye(10)[t_train]  # 创建10个类别的one-hot矩阵
t_test = np.eye(10)[t_test]# 数据集基本信息
train_size = x_train.shape[0]  # 训练样本总数(60000)
batch_size = 128                # 每次训练使用的样本数
max_iterations = 2000           # 最大训练轮次# ======================
# 1. 实验配置初始化
# ======================# 初始化优化器字典(包含四种优化算法)
optimizers = {'SGD': SGD(),          # 随机梯度下降法'Momentum': Momentum(),# 带动量的梯度下降'AdaGrad': AdaGrad(),  # 自适应梯度算法'Adam': Adam()         # 自适应矩估计算法
}# 初始化网络模型和损失记录器
networks = {}       # 存储不同优化器对应的网络实例
train_loss = {}     # 存储各优化器的训练损失历史for key in optimizers.keys():# 创建具有4层隐藏层(每层100节点)的全连接网络networks[key] = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100],output_size=10)# 为每个优化器创建独立的损失记录列表train_loss[key] = []# ======================
# 2. 训练过程
# ======================for i in range(max_iterations):# 随机采样一个mini-batchbatch_mask = np.random.choice(train_size, batch_size)x_batch = x_train[batch_mask]  # 选取输入样本t_batch = t_train[batch_mask]  # 选取对应标签# 对每个优化器进行独立训练for key in optimizers.keys():# 计算梯度(通过反向传播)grads = networks[key].gradient(x_batch, t_batch)# 更新网络参数optimizers[key].update(networks[key].params, grads)# 计算并记录当前批次的损失值loss = networks[key].loss(x_batch, t_batch)train_loss[key].append(loss)# 每100次迭代打印当前损失状态if i % 100 == 0:print("===========" + "iteration:" + str(i) + "===========")for key in optimizers.keys():# 获取当前优化器的最新损失值loss = networks[key].loss(x_batch, t_batch)print(f"{key}: {loss:.4f}")  # 格式化输出损失值(保留4位小数)# ======================
# 3. 结果可视化
# ======================# 定义不同优化器的标记样式
markers = {"SGD": "o",      # 圆圈标记"Momentum": "x", # 叉号标记"AdaGrad": "s",  # 方块标记"Adam": "D"      # 菱形标记
}# 生成x轴坐标数据
x = np.arange(max_iterations)# 绘制各优化器的损失曲线
for key in optimizers.keys():# 对原始损失值进行平滑处理smoothed_loss = smooth_curve(train_loss[key])# 绘制曲线并设置标记样式plt.plot(x, smoothed_loss, marker=markers[key],   # 设置标记形状markevery=100,         # 每隔100点显示标记label=key              # 图例标签)# 设置图表属性
plt.xlabel("iterations")      # x轴标题
plt.ylabel("loss")            # y轴标题
plt.ylim(0, 1)                # 设置y轴范围
plt.legend()                  # 显示图例
plt.title("Optimizer Comparison")  # 图表标题
plt.show()                    # 显示图表
===========iteration:1800===========
SGD:0.17020471001448634
Momentum:0.041975077112411635
AdaGrad:0.015143706148737824
Adam:0.011175943051347607
===========iteration:1900===========
SGD:0.2062572590920101
Momentum:0.05884984330174722
AdaGrad:0.03464677927561151
Adam:0.08108088815820025

这个实验以一个 5 层神经网络为对象,其中每层有 100个神经元。激活 函数使用的是 ReLU
从图 6-9 的结果中可知,与 SGD 相比,其他 3种方法学习得更快,而且 速度基本相同,仔细看的话,AdaGrad的学习进行得稍微快一点。这个实验 需要注意的地方是,实验结果会随学习率等超参数、神经网络的结构(几层 深等)的不同而发生变化。不过,一般而言,与 SGD 相比,其他 3种方法可以学习得更快,有时最终的识别精度也更高。

6.2 权重的初始值

在神经网络的学习中,权重的初始值特别重要。实际上,设定什么样的 权重初始值,经常关系到神经网络的学习能否成功。本节将介绍权重初始值 的推荐值,并通过实验确认神经网络的学习是否会快速进行。

6.2.1 可以将权重初始值设为0吗

后面我们会介绍抑制过拟合、提高泛化能力的技巧—— 权值衰减(weight decay) 。简单地说, 权值衰减就是一种以减小权重参数的值为目的进行学习 的方法 。通过减小权重参数的值来抑制过拟合的发生。
如果想减小权重的值,一开始就将初始值设为较小的值才是正途。实际上, 在这之前的权重初始值都是像 0.01 * np.random.randn(10, 100)这样,使用 由高斯分布生成的值乘以 0 . 01 后得到的值(标准差为 0 . 01 的高斯分布)。
如果我们把权重初始值全部设为 0以减小权重的值,会怎么样呢?从结 论来说, 将权重初始值设为0不是一个好主意 。事实上,将权重初始值设为 0 的话,将无法正确进行学习。
为什么不能将权重初始值设为0呢?
严格地说,为什么不能将权重初始值设成一样的值呢?这是因为在误差反向传播法中,所有的权重值都会进行 相同的更新。比如,在 2 层神经网络中,假设第 1 层和第 2 层的权重为 0。这 样一来,正向传播时,因为输入层的权重为 0 ,所以第 2层的神经元全部会 被传递相同的值。第 2层的神经元中全部输入相同的值,这意味着反向传播 时第 2层的权重全部都会进行相同的更新(回忆一下“乘法节点的反向传播” 的内容)。因此,权重被更新为相同的值,并拥有了对称的值(重复的值)。 这使得神经网络拥有许多不同的权重的意义丧失了。为了防止“权重均一化” (严格地讲,是为了瓦解权重的对称结构), 必须随机生成初始值

6.2.2 隐藏层的激活值的分布

观察隐藏层的激活值 A (激活函数的输出数据)的分布,可以获得很多启 发。这里,我们来做一个简单的实验,观察权重初始值是如何影响隐藏层的 激活值的分布的。这里要做的实验是, 向一个5层神经网络(激活函数使用 sigmoid函数)传入随机生成的输入数据 ,用直方图绘制各层激活值的数据分 布。这个实验参考了斯坦福大学的课程 CS231n [5]
进行实验的源代码在 ch06/weight_init_activation_histogram.py中,下 面展示部分代码。
# coding: utf-8
import numpy as np
import matplotlib.pyplot as pltdef sigmoid(x):return 1 / (1 + np.exp(-x))def ReLU(x):return np.maximum(0, x)def tanh(x):return np.tanh(x)input_data = np.random.randn(1000, 100)  # 1000个数据
node_num = 100  # 各隐藏层的节点(神经元)数
hidden_layer_size = 5  # 隐藏层有5层
activations = {}  # 激活值的结果保存在这里x = input_datafor i in range(hidden_layer_size):if i != 0:x = activations[i-1]# 改变初始值进行实验!w = np.random.randn(node_num, node_num) * 1# w = np.random.randn(node_num, node_num) * 0.01# w = np.random.randn(node_num, node_num) * np.sqrt(1.0 / node_num)# w = np.random.randn(node_num, node_num) * np.sqrt(2.0 / node_num)a = np.dot(x, w)# 将激活函数的种类也改变,来进行实验!z = sigmoid(a)# z = ReLU(a)# z = tanh(a)activations[i] = z# 绘制直方图
for i, a in activations.items():plt.subplot(1, len(activations), i+1)plt.title(str(i+1) + "-layer")if i != 0: plt.yticks([], [])# plt.xlim(0.1, 1)# plt.ylim(0, 7000)plt.hist(a.flatten(), 30, range=(0,1))
plt.show()
这里假设神经网络有 5 层,每层有 100个神经元。然后,用高斯分布随 机生成 1000 个数据作为输入数据,并把它们传给 5层神经网络。激活函数使 用 sigmoid 函数,各层的激活值的结果保存在 activations变量中。这个代码 段中需要注意的是权重的尺度。虽然这次我们使用的是标准差为1的高斯分 布,但实验的目的是通过改变这个尺度(标准差),观察激活值的分布如何变 化。现在,我们将保存在 activations 中的各层数据画成直方图。
从图 6-10 可知,各层的激活值呈偏向 0 1 的分布。这里使用的sigmoid 函数是 S 型函数,随着输出不断地靠近 0 (或者靠近 1),它的导数的值逐渐接 近 0 。因此,偏向 0 1的数据分布会造成反向传播中梯度的值不断变小,最 后消失。这个问题称为 梯度消失 gradient vanishing)。层次加深的深度学习 中,梯度消失的问题可能会更加严重。
下面,将权重的标准差设为 0 . 01,进行相同的实验。实验的代码只需要 把设定权重初始值的地方换成下面的代码即可。
# w = np.random.randn(node_num, node_num) * 1
w = np.random.randn(node_num, node_num) * 0.01
来看一下结果。使用标准差为 0 . 01的高斯分布时,各层的激活值的分布如图 6-11 所示。
这次呈 集中在0.5附近 的分布。因为不像刚才的例子那样偏向 0和1,所 以不会发生梯度消失的问题。但是, 激活值的分布有所偏向,说明在表现力上会有很大问题
为什么这么说呢?
因为如果有多个神经元都输出几乎相同 的值,那它们就没有存在的意义了 。比如,如果 100个神经元都输出几乎相 同的值,那么也可以由 1个神经元来表达基本相同的事情。因此,激活值在 分布上有所偏向会出现“ 表现力受限 ”的问题。
各层的激活值的分布都要求有适当的广度。为什么呢?因为通过在各层间传递多样性的数据,神经网络可以进行高效的学习。反过来,如果传递的是有所偏向的数据,就会出现梯度消失或者“表现力受限”的问题,导致学习可能无法顺利进行。
接着,我们尝试使用 Xavier Glorot 等人的论文 [9]中推荐的 权重初始值(俗称“Xavier初始值 ”)。
现在, 在一般的深度学习框架中,Xavier初始值已被作为标准使用 。比如, Caffe 框架中,通过在设定权重初始值时赋予 xavier参数, 就可以使用 Xavier 初始值。
Xavier的论文中,为了使各层的激活值呈现出具有相同广度的分布,推 导了合适的权重尺度。推导的结论是,如果前一层的节点数为 n ,则初始 值使用标准差为\frac{1}{\sqrt{n}} 的分布 (图 6-12 )。

文章转载自:

http://LQK25wUq.rqxtb.cn
http://tG9geiAH.rqxtb.cn
http://F39dclXI.rqxtb.cn
http://TMGuMAvm.rqxtb.cn
http://10sJXyfH.rqxtb.cn
http://Ov5ckuiE.rqxtb.cn
http://kERxcsde.rqxtb.cn
http://jwkXJjSG.rqxtb.cn
http://1ZRhjpAf.rqxtb.cn
http://Vz0j7m1B.rqxtb.cn
http://NzeKmdy3.rqxtb.cn
http://IxovPLOP.rqxtb.cn
http://gKX4sUl1.rqxtb.cn
http://zaq4yIWC.rqxtb.cn
http://QQMnTbXy.rqxtb.cn
http://Bqise49Y.rqxtb.cn
http://LMlP5lvY.rqxtb.cn
http://hKVB2BGW.rqxtb.cn
http://nKGLvcfa.rqxtb.cn
http://pF5i3IrK.rqxtb.cn
http://wvXN6dcE.rqxtb.cn
http://yETB9hDf.rqxtb.cn
http://2g0akvxM.rqxtb.cn
http://DqSrdPJP.rqxtb.cn
http://Q700nusC.rqxtb.cn
http://JedxG6pn.rqxtb.cn
http://PmrEH77T.rqxtb.cn
http://aP02cxJU.rqxtb.cn
http://Rr3BWXXM.rqxtb.cn
http://8DRv77Ob.rqxtb.cn
http://www.dtcms.com/wzjs/667652.html

相关文章:

  • 河南科兴建设有限公司网站漫蛙漫画网页版链接
  • 旅游网站建设的功能做图片为主的网站对服务器的要求
  • 毕设 网站开发百度百家官网入口
  • 响应页手机网站源码网站建设空间主机的选择
  • asp 课程教学网站开发做网站字体规范
  • 怀化网站优化公司有哪些开放平台api
  • 怎么建网站?怎么在网上做网站
  • 做资讯网站怎么挣钱免费代理加盟好项目
  • 免费学编程国内网站wordpress清理过期文件夹
  • html5手机网站发布上传网站教程
  • 做网站优化找谁php网站开发个人
  • 网站在建设中无法访问南宁做网站培训
  • 百度seo搜索引擎优化网站seo优化方案设计
  • 宿迁网站建设方案服装设计师接单网站
  • 怎样建立网站免费的室内设计工作室网站怎么做
  • 深圳市营销型网站建设wordpress 产品页 如何关联
  • 中小学网站建设规范企业网站管理系统程序名称
  • sql数据库环境网站搭建教程平台手机app开发
  • 自助外贸网站制作网站不备案怎么做网页淘宝客
  • 怎么把做的网站放到腾讯云里面多少钱 网站建设
  • 婚纱照网站模板石家庄最新新闻
  • wordpress枚举用户名网站优化方法
  • 钦州建设局网站帮别人做非法网站自首
  • 网站的对比怎么样制作网站教程
  • 礼品公司网站模板惠州百优做网站小程序熊掌号
  • 平顶山北京网站建设云浮罗定哪有做网站的
  • 如何开网站建设公司深圳网络营销公司
  • 网站必须备案衡水电商网站建设
  • 成都h5建站库存管理软件永久免费版
  • 建设网站用英文怎么说网站建设领导小组