第六章 网络学习相关技巧2(权重设置)

6.1简述

神经网络的学习中,权重的初始值特别重要。设定什么样的权重初始值,经常关系到神经网络的学习能否成功。且会影响到神经网络学习的速度。

权值衰减:就是一种以减小权重参数的值为目的进行学习的方法。通过减小权重参数的值来抑制过拟合的发生。

因此,我们在对权值进行初始化的时候,一开始便可以将初始值设置较小,使用Gauss分布生成的值。但是权重的值也不能全部设置为0(或者权值全部相同),将权重初始值设为0的话,将无法正确进行学习。这是因为在误差反向传播法中,所有的权重值都会进行相同的更新,没有意义。

6.2sigmiod权重初始值

下面使用sigmoid函数来举例,观察权重初始值是如何影响隐藏层的激活值的分布的。

目的:通过改变标准差,观察激活函数的变化

例:向一个5层神经网络(激活函数使用sigmoid函数)传入随机生成的输入数据,用直方图绘制各层激活值的数据分布。高斯分布的标准差分别为1, 0.01, 1/sqrt(n)。假设神经网络有5层,每层100个神经元。

1、当标准差为1时的直方图

img

【注】随着输出不断地靠近0(或者靠近1),它的导数的值逐渐接近0。因此,偏向0和1的数据分布会造成反向传播中梯度的值不断变小,最后消失。这个问题称为梯度消失(gradient vanishing)。层次加深的深度学习中,梯度消失的问题可能会更加严重。

2、当标准差为0.01时的直方图

img

【注】这次呈集中在0.5附近的分布。因为不像刚才的例子那样偏向0和1,所以不会发生梯度消失的问题。但是,激活值的分布有所偏向,说明在表现力上会有很大问题。为什么这么说呢?因为如果有多个神经元都输出几乎相同的值,那它们就没有存在的意义了。比如,如果100个神经元都输出几乎相同的值,那么也可以由1个神经元来表达基本相同的事情。因此,激活值在分布上有所偏向会出现“表现力受限”的问题。

3、当标准差为1/sqrt(n)时的直方图(如果前一层的节点数为n,则初始值使用标准差为 1/sqrt(n)的分布)

img

【注】从这个结果可知,越是后面的层,图像变得越歪斜,但是呈现了比之前更有广度的分布。因为各层间传递的数据有适当的广度,所以sigmoid函数的表现力不受限制,有望进行高效的学习。后面的层的分布呈稍微歪斜的形状。如果用 tanh函数(双曲线函数)代替 sigmoid 函数,这个稍微歪斜的问题就能得到改善。

代码实现如下:

import numpy as np
import matplotlib.pyplot as plt
 
 
def relu(x):
    return np.maximum(0, x)
 
 
def sigmoid(x):
    return 1/(1 + np.exp(-x))
 
 
def tanh(x):
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
 
 
x = np.random.randn(1000, 100)  # 1000个数据  # (1000, 100)
node_num = 100  # 各隐藏层的节点(神经元)数
hidden_layer_size = 5  # 隐藏层有5层
activations = {}  # 保存激活值的结果
 
for i in range(hidden_layer_size):  # 5
    if i != 0:
        x = activations[i - 1]
    # w = np.random.randn(node_num, node_num) * 1  # (100, 100)
    # w = np.random.randn(node_num, node_num) * 0.01
    w = np.random.randn(node_num, node_num)/np.sqrt(node_num)
    z = np.dot(x, w)  # (1000, 100)
    a = sigmoid(z)  # sigmoid函数
    activations[i] = a
# 绘制直方图
for i, a in activations.items():
    plt.subplot(1, len(activations), i+1)
    plt.title(str(i + 1)+"-layer")
    plt.hist(a.flatten(), 30, range=(0, 1))
 
plt.show()

6.3relu权重初始值

当激活函数使用ReLU时,一般推荐使用ReLU专用的初始值,也就是Kaiming He等人推荐的初始值,也称为“He初始值”。当前一层的节点数为n时,He初始值使用标准差为 的高斯分布。当Xavier初始值是 时,(直观上)可以解释为,因为ReLU的负值区域的值为0,为了使它更有广度,所以需要2倍的系数。

1、权重初始值为标准差是0.01的高斯分布

img

2、初始值为Xavier初始值时

img

3、ReLU专用–“He初始值”

img

【注】1、当“std = 0.01”时,各层的激活值非常小。神经网络上传递的是非常小的值,说明逆向传播时权重的梯度也同样很小。2、初始值为Xavier初始值时的结果。在这种情况下,随着层的加深,偏向一点点变大。实际上,层加深后,激活值的偏向变大,学习时会出现梯度消失的问题。3、而当初始值为He初始值时,各层中分布的广度相同。由于即便层加深,数据的广度也能保持不变,因此逆向传播时,也会传递合适的值。

代码实现如下:

import numpy as np
import matplotlib.pyplot as plt
import math
 
 
def relu(x):
    return np.maximum(0, x)
 
 
def sigmoid(x):
    return 1/(1 + np.exp(-x))
 
 
def tanh(x):
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
 
 
x = np.random.randn(1000, 100)  # 1000个数据  # (1000, 100)
node_num = 100  # 各隐藏层的节点(神经元)数
hidden_layer_size = 5  # 隐藏层有5层
activations = {}  # 保存激活值的结果
 
for i in range(hidden_layer_size):  # 5
    if i != 0:
        x = activations[i - 1]
    # w = np.random.randn(node_num, node_num) * 1  # (100, 100)
    # w = np.random.randn(node_num, node_num) * 0.01  # 使用标准差为0.01
    # w = np.random.randn(node_num, node_num)/np.sqrt(node_num)  # 使用Xavier初始值作为权重初始值
    w = math.sqrt(2) * np.random.randn(node_num, node_num)/ np.sqrt(node_num)
    z = np.dot(x, w)  # (1000, 100)
    # if i <= 1:
    #     a = sigmoid(z)  # sigmoid函数
    # else:
    #    a = tanh(z)
    a = relu(z)
    activations[i] = a
 
for i, a in activations.items():
    plt.subplot(1, len(activations), i+1)
    plt.title(str(i + 1)+"-layer")
    # flatten是numpy.ndarray.flatten的一个函数,即返回一个一维数组。默认按行的方向降维
    # 参数range的类型为tuple型,指定全局间隔(min,max),分为30个条状图
    plt.hist(a.flatten(), 30, range=(0, 1))
 
plt.show()

6.4案例:不同初始值比较

基于std = 0.01、Xavier初始值、He初始值等不同的权值对MNIST手写数字进行比较

目录结构:

img

6.4.1common文件夹

(funtions.py, gradient.py, layers.py, multi_layer_net.py, optimizer.py, util.py)见前面博文

6.4.2ch06文件夹

6.4.2.1weight_init_compare.py
# coding: utf-8
import os
import sys
 
sys.path.append(os.pardir)
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.util import smooth_curve
from common.multi_layer_net import MultiLayerNet
from common.optimizer import SGD
 
 
# 0:读取数据
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
 
train_size = x_train.shape[0]
batch_size = 128
 
max_iterations = 2000
 
 
# 1:设置权重初始值的方式
weight_init_types = {'std=0.01': 0.01, 'Xavier': 'sigmoid', 'He': 'relu'}
optimizer = SGD(lr=0.01)
 
networks = {}
train_loss = {}
# 初始化网络
for key, weight_type in weight_init_types.items():
    networks[key] = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100],
                                  output_size=10, weight_init_std=weight_type)
    train_loss[key] = []
 
 
# 2:训练2000次
for i in range(max_iterations):
    # 批处理
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
 
    # 梯度更新
    for key in weight_init_types.keys():
        grads = networks[key].gradient(x_batch, t_batch)
        optimizer.update(networks[key].params, grads)
    
        loss = networks[key].loss(x_batch, t_batch)
        train_loss[key].append(loss)
    
    if i % 100 == 0:  # 20次
        print("===========" + "iteration:" + str(i) + "===========")
        for key in weight_init_types.keys():
            loss = networks[key].loss(x_batch, t_batch)
            print(key + ": " + str(loss))
 
 
# 3.绘图
markers = {'std=0.01': 'o', 'Xavier': 's', 'He': 'D'}
x = np.arange(max_iterations)
for key in weight_init_types.keys():
    plt.plot(x, smooth_curve(train_loss[key]), marker=markers[key], markevery=100, label=key)
plt.xlabel("iterations")
plt.ylabel("loss")
plt.ylim(0, 2.5)
plt.legend()
plt.show()

6.4.3结果

这个实验中,神经网络有5层,每层有100个神经元,激活函数使用的是ReLU。

img

【注】从上图的结果可知,当std = 0.01时完全无法进行学习。这和刚才观察到的激活值的分布一样,是因为正向传播中传递的值很小(集中在0附近的数据)。因此,逆向传播时求到的梯度也很小,权重几乎不进行更新。相反,当权重初始值为Xavier初始值和He初始值时,学习进行得很顺利。并且,我们发现He初始值时的学习进度更快一些。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
GRNN(General Regression Neural Network)神经网络是一种基于概率密度函数的回归神经网络,其权重设置通常包括以下几个方面: 1. 确定输入层节点数和输出层节点数 在确定输入层节点数和输出层节点数时,需要考虑输入数据的维度和预测目标的维度。输入层节点数应当等于输入数据的维度,输出层节点数应当等于预测目标的维度。 2. 确定隐层节点数 隐层节点数的设置通常是一个经验性的问题,可以通过试验不同隐层节点数的表现来确定最优值。一般来说,隐层节点数越多,网络的拟合能力越强,但也容易过拟合。建议隐层节点数不要超过输入层节点数的两倍。 3. 初始化权重 权重的初始化可以采用随机初始化或者预先训练好的权重进行初始化。随机初始化可以通过随机数生成器生成,而预先训练好的权重可以使用已有的模型进行初始化。 4. 训练网络 训练网络的过程通常是通过迭代优化损失函数来完成的。损失函数的选择可以根据预测目标的不同而变化。在训练过程中,可以采用梯度下降等优化算法来更新权重,并根据训练集和验证集的表现来调整网络结构和超参数。 需要注意的是,在进行权重设置和训练网络时,应当避免过拟合和欠拟合的情况。可以通过交叉验证等技术来评估网络的表现,并采取相应的措施来解决这些问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

追寻远方的人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值