【自学】深度学习入门 基于python的理论与实现 LESSON10 <与学习相关的技巧1——权重参数优化方法>

目录

前言

一、参数的更新

1. SGD的缺点

2. Momentum

3. AdaGrad

4. Adam

5. 基于MNIST数据集地更新方法比较

二、权重的初始值

1. 权重初始值不能设为0

 

总结


前言

本节介绍权重参数的优化方法,即寻找最优权重参数的最优化方法。


一、参数的更新

1. SGD的缺点

如果函数的形状飞军向,比如呈延伸状,搜索的路径会非常低效。究其根本原因是梯度的方向并没有指向最小值的方向。

 

2. Momentum

W表示权重参数,yita表示学习率,v表示在梯度上的受力。

av这一项表示在物体不受任何力时,收到的阻力。

代码实现如下:

class Momentum:

    """Momentum SGD"""

    def __init__(self, lr=0.01, momentum=0.9):
        self.lr = lr
        self.momentum = momentum
        self.v = None
        
    def update(self, params, grads):
        if self.v is None:
            self.v = {}
            for key, val in params.items():                                
                self.v[key] = np.zeros_like(val)
                
        for key in params.keys():
            self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] 
            params[key] += self.v[key]

 分析:

(1)初始化时,v中什么都不保存,当第一次调用update()时,v会以字典变量的形式保存与参数结构相同的数据。

(2)np.zeros_like(val):

import numpy as np

a = np.arange(12)
a = a.reshape(2,2,3)
b = np.zeros_like(a)
print(a)
print(b)

结果:

[[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]]

[[[0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]]]

 (3)

这一部分代码的意义是什么?params.items()是什么?此处存疑

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

Momentum的优点 :

与SGD相比,它的“之”字程度减轻了。这是因为虽然x轴上受到的力非常小,但是一直是在同一个方向上,所以会朝一个方向加速;y轴方向虽然受力大,但是交互地受到正反方向的力,积分为0.与SGD相比,可以更快地找到最小值。

 

3. AdaGrad

AdaGrad会为参数的每个元素适当地调整学利率,与此同时进行学习。即随着学习的进行,使学习率逐渐减小。

⚪表示对应矩阵元素地乘积。

参数的元素中变动较大地元素地学习率更小。

代码实现:

class AdaGrad:

    """AdaGrad"""

    def __init__(self, lr=0.01):
        self.lr = lr
        self.h = None
        
    def update(self, params, grads):
        if self.h is None:
            self.h = {}
            for key, val in params.items():
                self.h[key] = np.zeros_like(val)
            
        for key in params.keys():
            self.h[key] += grads[key] * grads[key]
            params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

 权重更新路径如下图所示:

 函数的取值高效地向最小值移动。

4. Adam

Adam是将前两种(AdaGrad和Momentum)融合在一起。

class Adam:

    """Adam (http://arxiv.org/abs/1412.6980v8)"""

    def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
        self.lr = lr
        self.beta1 = beta1
        self.beta2 = beta2
        self.iter = 0
        self.m = None
        self.v = None
        
    def update(self, params, grads):
        if self.m is None:
            self.m, self.v = {}, {}
            for key, val in params.items():
                self.m[key] = np.zeros_like(val)
                self.v[key] = np.zeros_like(val)
        
        self.iter += 1
        lr_t  = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)         
        
        for key in params.keys():
            #self.m[key] = self.beta1*self.m[key] + (1-self.beta1)*grads[key]
            #self.v[key] = self.beta2*self.v[key] + (1-self.beta2)*(grads[key]**2)
            self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])
            self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])
            
            params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)
            
            #unbias_m += (1 - self.beta1) * (grads[key] - self.m[key]) # correct bias
            #unbisa_b += (1 - self.beta2) * (grads[key]*grads[key] - self.v[key]) # correct bias
            #params[key] += self.lr * unbias_m / (np.sqrt(unbisa_b) + 1e-7)

Adam会设置三个超参数:学习率、beta1、beta2.根据论文,beta1 = 0.9, beta2 = 0.999.大多数情况下可以顺利进行。

5. 基于MNIST数据集地更新方法比较

# coding: utf-8
import os
import sys
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
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 *


# 0:读入MNIST数据==========
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)

train_size = x_train.shape[0] #把x_train化成一维
batch_size = 128
max_iterations = 2000


# 1:进行实验的设置==========
optimizers = {}
optimizers['SGD'] = SGD()
optimizers['Momentum'] = Momentum()
optimizers['AdaGrad'] = AdaGrad()
optimizers['Adam'] = Adam()
#optimizers['RMSprop'] = RMSprop()

networks = {}
train_loss = {}
for key in optimizers.keys():
    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):
    batch_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)
    
    if i % 100 == 0: #i与100取余结果等于0
        print( "===========" + "iteration:" + str(i) + "===========")
        for key in optimizers.keys():
            loss = networks[key].loss(x_batch, t_batch)
            print(key + ":" + str(loss))


# 3.绘制图形==========
markers = {"SGD": "o", "Momentum": "x", "AdaGrad": "s", "Adam": "D"}
x = np.arange(max_iterations)
for key in optimizers.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, 1)
plt.legend()
plt.show()

输出结果:

 

分析:

(1)

 np.random.choice():

import numpy as np

a = np.random.choice(10, 8) 
#从[0, 10)内输出8个数字并组成一维数组a
print(a)

b = np.random.choice(a, 5)
#从一维数组a中随意抽取5个数组成一维数组b
#注意:a必须是一维的
print(b)

结果:

[1 3 7 5 7 5 1 7]
[5 7 7 5 1]

二、权重的初始值

设置什么样的初始值关系到神经网络学习能否成功。

1. 权重初始值不能设为0

权重的初始值绝对不能设为0

之前一段时间,权重初始值设为:

import numpy as np

a = 0.01 * np.random.randn(10, 100)

补充:np.random.randn的介绍:

import numpy as np

a = 0.01 * np.random.randn(2, 4, 3)#2*3*4的数组,即表示生成数组的维度
b = np.random.randn(2, 4)
print(f'a is {a}')
print(f'b is {b}')

 结果:

a is [[[-0.01141521  0.00021992 -0.00668211]
  [-0.00799102 -0.01430591  0.00065054]
  [ 0.00253524 -0.01118892 -0.01097236]
  [-0.00580513  0.00963655 -0.00336067]]

 [[ 0.00232957 -0.00983508  0.00066577]
  [-0.01303359  0.02022611 -0.00138892]
  [-0.00026297 -0.00356707 -0.01244644]
  [ 0.00965091  0.00946335  0.00834518]]]
b is [[ 1.3743193  -1.40996427  0.11132154 -0.37661421]
 [ 0.61963745 -0.37448273 -0.69203084 -1.4140828 ]]

 


总结

关于参数更新方法个人而言没有特别理解,但是在具体的应用中似乎不需要明白其机理。因此不再此处过多停留。下一节将重点介绍权重的初始值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Rachel MuZy

你的鼓励是我的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值