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大小、参数更新时的学习率或者权值衰减。
    如果超参数没有设置合适的值,模型的性能会变得很差。
    验证数据:用于调整超参数的数据,用它来评估超参数的好坏。
    不能使用测试数据评估超参数的性能。

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

  • 相关阅读:
    std thread
    windows更新包发布地址
    How to set up logging level for Spark application in IntelliJ IDEA?
    spark 错误 How to set heap size in spark within the Eclipse environment?
    hadoop 常用命令
    windows 安装hadoop 3.2.1
    windows JAVA_HOME 路径有空格,执行软连接
    day01MyBatisPlus条件构造器(04)
    day01MyBatisPlus的CRUD 接口(03)
    day01MyBatisPlus入门(02)
  • 原文地址:https://www.cnblogs.com/AKsnoopy/p/13566724.html
Copyright © 2011-2022 走看看