【调参】Cyclic Learning Rates和One Cycle Policy-Keras

传统的网络训练过程中,一般学习率都是逐渐减小的,像keras可以使用keras.callbacks.ReduceLROnPlateau对学习率进行调整,例如:
函数:

keras.callbacks.ReduceLROnPlateau(monitor='val_loss', 
								factor=0.1, 
								patience=10, 
								verbose=0, 
								mode='auto', 
								min_delta=0.0001, 
								cooldown=2, 
								min_lr=0)

回调函数将会监视其中的一个metrics,在上面的例子中,metrics为val_loss,同时设置patience,如果监视的metrics超过10个eopch都没有任何提升,那么调整学习率—往小的方向进行调整。得到新的学习率,new_lr = lr * factor。cooldown参数值得是在lr改变之后,等待2个eopch之后回复正常的操作(?)。min_delta阈值为衡量新的最优值,只关注显著变化(?)。

直观地说,将学习率向更高的学习率振荡是有帮助的。因为较高的学习率可能有助于摆脱鞍点。如果鞍点是复杂的高原,较低的学习率可能无法得到鞍点以外的梯度。

Cyclic Learning Rates

熟悉几个概念:
base_lr : 下界学习率。
max_lr : 上界学习率。
cycle: 学习率从下界学习率(base_lr)到上界学习率(max_lr)再到下界学习率(base_lr),所经历的迭代次数iterations。
stepsize: cycle迭代次数的一半。

在这里插入图片描述

代码:https://github.com/bckenstler/CLR

One Cycle Policy

在论文[“A disciplined approach to neural network hyper-parameters: Part 1 — learning rate, batch size, momentum, and weight decay”](A disciplined approach to neural network hyper-parameters: Part 1 — learning rate, batch size, momentum, and weight decay)中,Leslie Smith描述了设置超参数(即学习率、动量和重量衰减)和批大小的方法。他特别建议采用1 Cycle policy来调整学习率。

前提,先找到最大的学习速率max_lr,使用LRFinder-for-Keras中的方法。
我们使用较低的学习速度作为最大学习速度的1/5或1/10。
我们在步骤1中从较低的学习率到较高的学习率,然后在步骤2中回到较低的学习率。我们选择这个周期长度略小于要训练的周期总数。在最后的迭代中,我们将学习率大大低于较低的学习率值(1/10或1/100)。
在这里插入图片描述
其背后的动机是,在学习过程中,当学习速率较高时,学习速率作为正则化方法发挥作用,防止网络过度拟合。

代码:

import numpy as np 
import keras 
from keras import backend as K
from keras.callbacks import *

class CyclicLR(keras.callbacks.Callback):
    
    def __init__(self,base_lr, max_lr, step_size, base_m, max_m, cyclical_momentum):
 
        self.base_lr = base_lr
        self.max_lr = max_lr
        self.base_m = base_m
        self.max_m = max_m
        self.cyclical_momentum = cyclical_momentum
        self.step_size = step_size
        
        self.clr_iterations = 0.
        self.cm_iterations = 0.
        self.trn_iterations = 0.
        self.history = {}
        
    def clr(self):
        
        cycle = np.floor(1+self.clr_iterations/(2*self.step_size))
        
        if cycle == 2:
            x = np.abs(self.clr_iterations/self.step_size - 2*cycle + 1)          
            return self.base_lr-(self.base_lr-self.base_lr/100)*np.maximum(0,(1-x))
        
        else:
            x = np.abs(self.clr_iterations/self.step_size - 2*cycle + 1)
            return self.base_lr + (self.max_lr-self.base_lr)*np.maximum(0,(1-x))
    
    def cm(self):
        
        cycle = np.floor(1+self.clr_iterations/(2*self.step_size))
        
        if cycle == 2:
            
            x = np.abs(self.clr_iterations/self.step_size - 2*cycle + 1) 
            return self.max_m
        
        else:
            x = np.abs(self.clr_iterations/self.step_size - 2*cycle + 1)
            return self.max_m - (self.max_m-self.base_m)*np.maximum(0,(1-x))
        
        
    def on_train_begin(self, logs={}):
        logs = logs or {}

        if self.clr_iterations == 0:
            K.set_value(self.model.optimizer.lr, self.base_lr)
        else:
            K.set_value(self.model.optimizer.lr, self.clr())
            
        if self.cyclical_momentum == True:
            if self.clr_iterations == 0:
                K.set_value(self.model.optimizer.momentum, self.cm())
            else:
                K.set_value(self.model.optimizer.momentum, self.cm())
            
            
    def on_batch_begin(self, batch, logs=None):
        
        logs = logs or {}
        self.trn_iterations += 1
        self.clr_iterations += 1

        self.history.setdefault('lr', []).append(K.get_value(self.model.optimizer.lr))
        self.history.setdefault('iterations', []).append(self.trn_iterations)
        
        if self.cyclical_momentum == True:
            self.history.setdefault('momentum', []).append(K.get_value(self.model.optimizer.momentum))

        for k, v in logs.items():
            self.history.setdefault(k, []).append(v)
        
        K.set_value(self.model.optimizer.lr, self.clr())
        
        if self.cyclical_momentum == True:
            K.set_value(self.model.optimizer.momentum, self.cm())

使用:

batch_size = train_config.BATCH_SIZE
epochs = train_config.NB_EPOCHS
max_lr = 0.01 ##
base_lr = max_lr/10
max_m = 0.98
base_m = 0.85

cyclical_momentum = True
augment = True
cycles = 2.35

iterations = round(len(train)/batch_size*epochs)
iterations = list(range(0,iterations+1))
step_size = len(iterations)/(cycles)


clr =  CyclicLR(base_lr=base_lr,
                max_lr=max_lr,
                step_size=step_size,
                max_m=max_m,
                base_m=base_m,
                cyclical_momentum=cyclical_momentum)
callbacks_list = [clr]    

参考

  1. The 1cycle policy
  2. Finding Good Learning Rate and The One Cycle Policy
  3. github1
  4. github2
  5. kaggle
  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CP-OFDM (正交频分多址,Cyclic Prefix Orthogonal Frequency Division Multiplexing) 是一种带循环前缀的 OFDM 技术,用于减少频偏导致的信道失真。 DFT-S-OFDM (正交频分多址,Discrete Fourier Transform Spread Orthogonal Frequency Division Multiplexing) 是一种基于 DFT (离散傅里叶变换) 的 OFDM 技术,可以支持更高的带宽效率和抗干扰能力。 ### 回答2: CP-OFDM(循环前缀正交频分复用)和DFT-S-OFDM(离散傅里叶变换序列正交频分复用)都是OFDM技术的变种,用于数字通信系统中,它们的主要区别在于它们试图解决不同的问题。 CP-OFDM是OFDM技术的标准实现形式,它采用循环前缀技术解决了信道失真带来的码间干扰(ICI)问题。当信道失真导致码间干扰的时候,循环前缀可以提供保护,将发送的符号码分为若干个长度相同的块,每个码块后添加一段循环前缀,再将它们串接起来发送,接收器根据自己知道的循环前缀长度来将码块分离并去掉前缀,从而消除了ICI问题。 而DFT-S-OFDM则采用了离散傅里叶变换(DFT)代替了循环前缀,在传输信号矩阵的每一列上执行DFT,由于DFT是正交的,可以保证由不同输入产生的输出彼此正交,从而减少了ICI。此外,DFT-S-OFDM还可以通过增加间隔的DFT长度来实现高灵敏度,DFT长度越大,相邻子载波之间的差异也就越大,因此它对于理论上的通道模型要求低,能够适用于更广泛的情况。 综上所述,CP-OFDM和DFT-S-OFDM都是OFDM技术的重要变种,它们的特点和优缺点有所不同,适用于不同的场景和应用需求。在选择哪种技术时,需要根据具体的通信系统需求和实际环境来进行选择。 ### 回答3: CP-OFDM和DFT-S-OFDM是两种用于数字通信的OFDM技术,在5G等网络中被广泛使用。两者有着不同的特点和应用场景。 CP-OFDM(Cyclic Prefix OFDM)是OFDM技术中最常用的一种类型,它通过添加循环前缀(CP)来解决多径效应带来的因为符号间干扰而引起的信号失真问题。CP是由扩展OFDM符号前面一小段数据组成的,并复制到了OFDM符号序列的末尾,因此发送时会将OFDM符号序列扩展一倍。这么做的好处是可以为符号间消除干扰,使得接收端可以更好地恢复信号。然而CP-OFDM也存在一些缺陷,例如需要额外的发送时间、功耗较高等。 DFT-S-OFDM(Discrete Fourier Transform Spread OFDM)也被称为FBMC (Filtered Bank Multicarrier)。它是一种基于OFDM的子载波调制技术,它利用快速傅里叶变换(FFT)和滤波器银行,使数据能够平稳地分布在原始频率上,从而在不同频带上实现更好的系统性能。另外,DFT-S-OFDM具有下行波束成形的优点,即可以对用户进行动态的波束成形,提高频率复用,从而提高无线电频谱利用率。 总结来看,CP-OFDM和DFT-S-OFDM各自具有自己的优点和缺点,应用场景也不同。如果需要在对多径效应时进行抗干扰,则CP-OFDM是一个比较好的选择。而如果需要实现波束成形和提高频谱利用率,那么DFT-S-OFDM更为适合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值