zoukankan      html  css  js  c++  java
  • 神经网络学习笔记6

    C6 与学习相关

    1、参数的更新
    ①参数的最优化:找到使得损失函数值尽可能小的参数
    SGD:随机梯度下降法,醉着梯度方向更新参数
    缺点:如果函数形状非均向,呈延伸状,搜索的路径就会非常低效

    momentum:动量
    引入一个v
    初始化时,v什么都不保存
    当第一次调用update()时,v会以字典型变量形式保存参数结构相同的数据
    减弱之字形变动程度

     1 class Momentum:
     2 
     3     """Momentum SGD"""
     4 
     5     def __init__(self, lr=0.01, momentum=0.9):
     6         self.lr = lr
     7         self.momentum = momentum
     8         self.v = None
     9         
    10     def update(self, params, grads):
    11         if self.v is None:
    12             self.v = {}
    13             for key, val in params.items():                                
    14                 self.v[key] = np.zeros_like(val)
    15                 
    16         for key in params.keys():
    17             self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] 
    18             params[key] += self.v[key]

    AdaGrad:学习率衰减,随着学习的进行,逐渐减少学习率。一开始多学,逐渐少学;针对一个一个的参数,赋予其定制的值
    新变量h,保存了以前所有梯度值的平方和,表示对应矩阵元素的乘法
    当元素变动较大的元素学习率将逐渐减少

    最后一行加上了微小值le-7,为了防止当self.h[key]中有0的时候,要将0用作除数的情况

    ※防止将0作为除数用,加上le-7

    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)

    Adam:结合momentum和adagrad的方法,组合两个方法的有点实现参数空间的高效搜索,进行超参数的“偏置校正”

    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)


    RMSProp:逐渐遗忘过去的梯度,在做加法运算时候将新梯度信息更多地反应出来。(指数移动平均)

    class RMSprop:
    
        """RMSprop"""
    
        def __init__(self, lr=0.01, decay_rate = 0.99):
            self.lr = lr
            self.decay_rate = decay_rate
            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] *= self.decay_rate
                self.h[key] += (1 - self.decay_rate) * grads[key] * grads[key]
                params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

    2、权重的初始值
    梯度消失:当各层激活值呈0或者1分布,随着输出不断靠近0或者1,导数的值逐渐接近0;会造成反向传播中梯度的值不断减伤,最后消失。
    Xavier初始值:使得各层激活值呈现具有相同广度的分布,推导合适的权重尺度。
    使用Xavier后,前一层节点越多,要设定为目标节点的初始权重尺度就越小。
    ※激活函数最好有关于原点对称的性质。

    He初始值:当前一层节点数为n时,He初始值使用标准差(2/n)^-(1/2)的高斯分布
    ※当激活函数使用ReLU时,权重初始函数值使用He初始值,当激活函数为sigmoid或者tanh等S型曲线函数时,初始值就使用Xavier初始值

    3、Batch Normalization
    优点:可以使得学习快速进行(可以增大学习率)、可以不那么依赖初始值、一直过拟合(降低对Dropout等的必要性)
    思路:调整各层的激活值分布使得其拥有适当的广度。为此,要向神经网络中插入对数据分布进行正规化的层,即Batch Normalization层
    以学习时的mini-batch为单位,按照mini-batch进行正规化。进行使得数据分布的均值为0、方差为1的正规化。
    使用batch norm可以推动学习的进行,并且对于权重初始值变得健壮。

    4、正则化
    过拟合:只能拟合训练数据,不能很好的拟合不包含在训练数据中的其他数据的状态
    产生的原因:①、模型拥有大量的参数、表现力强,②训练数据少

    抑制过拟合的技巧:
    ①权值衰减:通过在学习过程中对大的权重进行惩罚来抑制过拟合。
    ②dropout:抑制过拟合,是一种在学习过程中随机删除神经元的方法。训练时,随机选出隐藏层的神经元,然后将其删除,被删除的神经元不再进行信号的传递。
    测试时,对于各个神经元的输出,要乘上训练时的删除比例后再输出。
    通过使用Dropout,训练数据和测试数据的识别精度差距变小。

    dropout把集成学习的效果模拟地通过一个网络实现了
    5、超参数的验证
    超参数:指各层的神经元数量、batch大小、参数更新时的学习率或者权值衰减。
    如果超参数没有设置合适的值,模型的性能会变得很差。
    验证数据:用于调整超参数的数据,用它来评估超参数的好坏。
    不能使用测试数据评估超参数的性能。

    超参数的最优化:逐渐缩小超参数的好值存在范围。一开始先大致设定一个范围,从这个范围内随机选出一个超参数,用这个采样到的值进行识别精度的评估,然后多次重复该操作,观察识别精度的结果。根据这个结果缩小超参数好值的范围。
    更精炼的方法:贝叶斯最优化

  • 相关阅读:
    bus总线
    vue 动态组件、父子组件传参
    echarts
    记录板
    留言板
    如何移除双系统mac中的windows系统
    Kernel,Shell,Bash 的关系
    zju 校队选拔 被虐记
    COGS 2638. 数列操作ψ 线段树
    退役公告【现已复活】
  • 原文地址:https://www.cnblogs.com/AKsnoopy/p/13566724.html
Copyright © 2011-2022 走看看