【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现

这篇具有很好参考价值的文章主要介绍了【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

目录

🌞一、实验目的

🌞二、实验准备

🌞三、实验内容

🌼1. 认识RMSProp算法

🌼2. 在optimizer_compare_naive.py中加入RMSProp

🌼3. 在optimizer_compare_mnist.py中加入RMSProp

🌼4. 问题的解决

🌞四、实验心得


🌞一、实验目的

  1. 深入学习RMSProp算法的原理和工作机制;

  2. 根据RMSProp算法的原理,设计并实现一个RMSProp优化器;

  3. 在optimizer_compare_naive.py中加入RMSProp做比较分析;

  4. 在optimizer_compare_mnist.py中加入RMSProp做比较分析。


🌞二、实验准备

  1. 根据GPU安装pytorch版本实现GPU运行实验代码;

  2. 配置环境用来运行 Python、Jupyter Notebook和相关库等相关库。


🌞三、实验内容

资源获取:关注公众号【科创视野】回复  深度学习

🌼1. 认识RMSProp算法

RMSProp(Root Mean Square Propagation)算法是由Geoffrey Hinton在2012年提出的,是对传统的梯度下降算法的改进。它是一种常用的优化算法,用于在深度学习中更新神经网络的参数。

RMSProp算法的基本原理和工作机制如下:

1.基本原理:

RMSProp算法旨在解决传统梯度下降算法中学习率选择的问题。传统梯度下降算法使用固定的学习率,在不同参数上可能导致收敛速度过慢或不收敛。RMSProp通过自适应调整学习率来解决这个问题,对于每个参数使用不同的学习率,根据历史梯度的信息来自动调整。

2.工作机制:

RMSProp使用指数加权平均来计算梯度的平方的移动平均值。对于每个参数的梯度g,计算平方梯度的移动平均值s:

s = β * s + (1 - β) * g^2

其中,β是一个衰减因子,控制历史梯度对当前梯度影响的权重,一般取值范围在0到1之间。然后,更新参数时使用调整后的学习率。对于每个参数的学习率η,计算调整后的学习率:

η' = η / (√(s) + ε)

其中,ε是一个很小的常数,用于避免除以零的情况。最后,使用调整后的学习率更新参数:

参数 = 参数 - η' * 梯度

在每次迭代中,RMSProp算法会根据历史梯度的信息调整学习率,使得对于梯度较大的参数,学习率较小,对于梯度较小的参数,学习率较大,从而更好地适应不同参数的更新需求。

RMSProp算法通过自适应调整学习率,可以提高神经网络的收敛速度和性能。与其他自适应学习率算法(如AdaGrad和Adam)相比,RMSProp在一些情况下可能更稳定和有效。然而,选择合适的学习率和衰减因子对于算法的性能仍然很重要,需要通过实验来确定最佳的超参数设置。

🌼2. 在optimizer_compare_naive.py中加入RMSProp

分析optimizer_compare_naive.py源码如下:

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from collections import OrderedDict
from common.optimizer import *


def f(x, y):
    return x**2 / 20.0 + y**2


def df(x, y):
    return x / 10.0, 2.0*y

init_pos = (-7.0, 2.0)
params = {}
params['x'], params['y'] = init_pos[0], init_pos[1]
grads = {}
grads['x'], grads['y'] = 0, 0


optimizers = OrderedDict()
optimizers["SGD"] = SGD(lr=0.95)
optimizers["Momentum"] = Momentum(lr=0.1)
optimizers["AdaGrad"] = AdaGrad(lr=1.5)
optimizers["Adam"] = Adam(lr=0.3)

idx = 1

for key in optimizers:
    optimizer = optimizers[key]
    x_history = []
    y_history = []
    params['x'], params['y'] = init_pos[0], init_pos[1]
    
    for i in range(30):
        x_history.append(params['x'])
        y_history.append(params['y'])
        
        grads['x'], grads['y'] = df(params['x'], params['y'])
        optimizer.update(params, grads)
    
    x = np.arange(-10, 10, 0.01)
    y = np.arange(-5, 5, 0.01)
    
    X, Y = np.meshgrid(x, y) 
    Z = f(X, Y)
    
    # for simple contour line  
    mask = Z > 7
    Z[mask] = 0
    
# plot 
fig, axs = plt.subplots(2, 2, figsize=(10, 10), sharey=True, tight_layout=True)
idx = 0

for key in optimizers:
    optimizer = optimizers[key]
    x_history = []
    y_history = []
    params['x'], params['y'] = init_pos[0], init_pos[1]

    for i in range(30):
        x_history.append(params['x'])
        y_history.append(params['y'])

        grads['x'], grads['y'] = df(params['x'], params['y'])
        optimizer.update(params, grads)

    x = np.arange(-10, 10, 0.01)
    y = np.arange(-5, 5, 0.01)

    X, Y = np.meshgrid(x, y) 
    Z = f(X, Y)

    # for simple contour line  
    mask = Z > 7
    Z[mask] = 0

    ax = axs[idx//2, idx%2]
    ax.plot(x_history, y_history, 'o-', color="red")
    ax.contour(X, Y, Z)
    ax.set_ylim(-10, 10)
    ax.set_xlim(-10, 10)
    ax.plot(0, 0, '+')
    ax.set_title(key)
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    idx += 1

plt.subplots_adjust(hspace=0.5, wspace=0.5)
plt.show()

分析:

该源码主要是用来展示不同优化器在二维空间中的优化效果。

1.首先是导入必要的库:

  1. sys、os:用于操作系统相关功能。
  2. numpy:用于进行数值计算。
  3. matplotlib.pyplot:用于绘图。
  4. collections.OrderedDict:有序字典,用于存储优化器。

2.定义函数f(x, y)和df(x, y):

  1. f(x, y):定义了一个简单的二维函数,即 f(x, y) = x^2 / 20 + y^2。
  2. df(x, y):计算函数f(x, y)在(x, y)点处的偏导数,即 (f/x, f/y) = (x/10, 2y)

3.初始化参数和梯度:

  1. init_pos:初始位置,为(-7.0, 2.0)。
  2. params:存储优化器中使用的参数,包括x和y。
  3. grads:存储梯度,包括x和y的偏导数。

4.定义优化器:

  1. 使用collections.OrderedDict()创建了一个有序字典optimizers,用于存储不同的优化器。
  2. 分别添加了"SGD"、"Momentum"、"AdaGrad"和"Adam"四种优化器,并给定了不同的学习率。

5.迭代优化器并绘制图形:

  1. 使用for循环遍历optimizers中的每个优化器。
  2. 初始化空列表x_history和y_history,用于存储参数更新的历史轨迹。
  3. 在每个优化器下进行30次迭代:
  4. 将当前参数位置params['x']和params['y']添加到x_history和y_history中。
  5. 计算当前位置的梯度grads['x']和grads['y']。
  6. 调用优化器的update方法,更新参数params。
  7. 生成x和y的取值范围,用于绘制等高线图。
  8. 绘制当前优化器的参数更新轨迹、等高线图和起点位置。
  9. 设置标题、坐标轴等信息。

6.显示图形:

  1. 使用plt.show()显示绘制的图形。

以上代码展示了四种不同的优化器在二维空间中的优化过程。通过迭代更新参数,每个优化器根据自己的更新策略不断优化目标函数,并绘制出参数更新轨迹和等高线图,以便比较不同优化器的效果。

源码运行结果为:

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

这里其实我们很容易可以发现在头文件处导入了from common.optimizer import *,而这个库是书籍提供的因此我们打开后查看其目录层级如下图:

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

由于使用了其中的optimizer因此查看其内容如下:

# coding: utf-8
import numpy as np

class SGD:
    """随机梯度下降法(Stochastic Gradient Descent)"""
    def __init__(self, lr=0.01):
        self.lr = lr
        
    def update(self, params, grads):
        for key in params.keys():
            params[key] -= self.lr * grads[key] 

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]

class Nesterov:
    """Nesterov's Accelerated Gradient (http://arxiv.org/abs/1212.0901)"""
    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.momentum * self.momentum * self.v[key]
            params[key] -= (1 + self.momentum) * self.lr * grads[key]

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)


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)
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)

Common分析:

1.这里定义了几种优化算法,包括随机梯度下降法(SGD)、动量法(Momentum)、Nesterov加速梯度法(Nesterov)、AdaGrad、RMSprop和Adam。这些优化算法用于在机器学习和深度学习中更新模型参数以最小化损失函数。

2.SGD(随机梯度下降法):每次迭代时,通过乘以学习率(lr)和梯度值更新参数。即 params[key] -= lr * grads[key]。

3.Momentum(动量法):引入动量(momentum)的概念,通过累积之前的速度来决定当前的更新方向。在每次迭代中,更新速度和参数值。速度(self.v)初始化为零,然后根据当前梯度和动量参数更新速度和参数。更新速度的公式为 self.v[key] = self.momentumself.v[key] - self.lrgrads[key],更新参数的公式为 params[key] += self.v[key]。

4.Nesterov's Accelerated Gradient(Nesterov加速梯度法):与Momentum类似,但在更新参数之前使用了动量的“预期”位置。在每次迭代中,先根据当前速度和动量参数更新速度和参数的“预期”位置,然后再根据当前梯度更新速度和参数的值。更新速度的公式为 self.v[key] *= self.momentum,self.v[key] -= self.lr * grads[key],更新参数的公式为 params[key] += self.momentum * self.momentum * self.v[key],params[key] -= (1 + self.momentum) * self.lr * grads[key]。

5.AdaGrad:针对不同参数的梯度值进行归一化处理,对于每个参数,根据梯度平方的累积和和学习率更新参数。归一化的方式是除以历史梯度平方的平方根加上一个很小的数(1e-7)以避免除以零。更新参数的公式为 params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7),其中 self.h[key] 为历史梯度平方的累积和。

6.RMSprop与AdaGrad类似,但不是累积所有历史梯度平方的和,而是通过指数加权平均的方式计算历史梯度平方的累积和。在每次迭代中,更新参数的方式与AdaGrad相同,只是累积和的计算方式不同。更新参数的公式为 params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7),其中 self.h[key] *= self.decay_rate,self.h[key] += (1 - self.decay_rate继续解释Adam算法:

7.Adam:结合了动量法和RMSprop的优点。它使用两个动量参数(beta1和beta2)和一个迭代计数器(iter)来更新参数。初始化时,将动量(m)和二阶矩估计(v)初始化为零。在每次迭代中,更新动量和二阶矩估计的值,然后根据当前的学习率计算修正后的学习率。最后,根据修正后的学习率和二阶矩估计来更新参数。更新动量和二阶矩估计的公式为:

self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])

self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])

修正后的学习率(lr_t)计算公式为:

lr_t = self.lr * np.sqrt(1.0 - self.beta2self.iter) / (1.0 - self.beta1self.iter)

最终,根据修正后的学习率和二阶矩估计来更新参数的公式为:

params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)

根据上述的common分析,为了添加RMSProp优化器,还需进行以下步骤:

1. 导入RMSProp优化器类:

  1. 在代码开头导入RMSProp类, from common.optimizer import RMSProp

2.在优化器字典中添加RMSProp优化器:

  1. 在optimizers字典中添加RMSProp优化器,类似于其他优化器的添加方式,指定合适的学习率:
optimizers["RMSProp"] = RMSProp(lr=0.1, decay_rate=0.99)

3.在循环中使用RMSProp优化器更新参数:

  1. 在循环迭代的部分,根据当前优化器选择RMSProp进行参数更新。
  2. 在每次迭代时,调用RMSProp优化器的update方法更新参数。
for i in range(30):
    x_history.append(params['x'])
    y_history.append(params['y'])

    grads['x'], grads['y'] = df(params['x'], params['y'])
    optimizer.update(params, grads)

4. 最后,运行代码并观察RMSProp优化器的效果。

  1. 当运行代码时,RMSProp优化器将被迭代,并在绘图中显示其参数更新轨迹。

添加RMSProp后代码为:

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from collections import OrderedDict
from common.optimizer import *

def f(x, y):
    return x**2 / 20.0 + y**2

def df(x, y):
    return x / 10.0, 2.0*y

init_pos = (-7.0, 2.0)
params = {}
params['x'], params['y'] = init_pos[0], init_pos[1]
grads = {}
grads['x'], grads['y'] = 0, 0

optimizers = OrderedDict()
optimizers["SGD"] = SGD(lr=0.95)
optimizers["Momentum"] = Momentum(lr=0.1)
optimizers["AdaGrad"] = AdaGrad(lr=1.5)
optimizers["Adam"] = Adam(lr=0.3)
optimizers["RMSProp"] = RMSprop(lr=0.1, decay_rate=0.99)  # 添加RMSProp优化器

idx = 1

for key in optimizers:
    optimizer = optimizers[key]
    x_history = []
    y_history = []
    params['x'], params['y'] = init_pos[0], init_pos[1]
    
    for i in range(30):
        x_history.append(params['x'])
        y_history.append(params['y'])
        
        grads['x'], grads['y'] = df(params['x'], params['y'])
        optimizer.update(params, grads)
    

    x = np.arange(-10, 10, 0.01)
    y = np.arange(-5, 5, 0.01)
    
    X, Y = np.meshgrid(x, y) 
    Z = f(X, Y)
    
    # for simple contour line  
    mask = Z > 7
    Z[mask] = 0
    
# plot 
fig, axs = plt.subplots(3, 2, figsize=(15, 20), sharey=True, tight_layout=True)
idx = 1

for key in optimizers:
    optimizer = optimizers[key]
    x_history = []
    y_history = []
    params['x'], params['y'] = init_pos[0], init_pos[1]

    for i in range(30):
        x_history.append(params['x'])
        y_history.append(params['y'])

        grads['x'], grads['y'] = df(params['x'], params['y'])
        optimizer.update(params, grads)

    x = np.arange(-10, 10, 0.01)
    y = np.arange(-5, 5, 0.01)

    X, Y = np.meshgrid(x, y) 
    Z = f(X, Y)

    # for simple contour line  
    mask = Z > 7
    Z[mask] = 0

    ax = axs[(idx - 1) // 2, (idx - 1) % 2]
    ax.plot(x_history, y_history, 'o-', color="red")
    ax.contour(X, Y, Z)
    ax.set_ylim(-10, 10)
    ax.set_xlim(-10, 10)
    ax.plot(0, 0, '+')
    ax.set_title(key)
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    idx += 1

plt.show()

运行结果为:

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

🌼3. 在optimizer_compare_mnist.py中加入RMSProp

分析optimizer_compare_mnist.py源码如下:

# 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]
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:
        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.数据准备

  1. 通过调用load_mnist函数加载了MNIST数据集,将训练数据集和测试数据集分别赋值给(x_train, t_train)和(x_test, t_test)变量。
  2. train_size记录了训练数据集的样本数量,batch_size定义了每个小批量训练的样本数量,max_iterations定义了训练的迭代次数。

2.实验设置

  1. 定义字典optimizers包含了不同的优化算法对象,包括SGD、Momentum、AdaGrad和Adam。
  2. 定义空的字典networks用于存储不同优化算法下的神经网络模型。
  3. 定义空的字典train_loss用于存储不同优化算法下的训练损失。

3.开始训练

  1. 使用一个循环迭代max_iterations次进行训练。
  2. 在每次迭代中,通过随机选择索引生成一个小批量的训练数据,并根据选择的优化算法计算梯度并更新模型参数。
  3. 计算当前模型在训练数据上的损失,并将其存储到train_loss字典中。
  4. 每隔100次迭代,打印出各个优化算法的损失。

4.绘制图形

  1. 使用smooth_curve函数平滑训练损失曲线。
  2. 使用不同的标记符号和颜色,将各个优化算法的训练损失曲线绘制在同一张图上。
  3. 添加坐标轴标签和图例,并显示图形。
  4. 过比较不同优化算法在训练过程中的损失变化情况,可以对比它们的性能和收敛速度,进而选择最合适的优化算法来训练神经网络模型。

运行结果如下:

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

图4-4

前文的common的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)

为了添加RMSProp优化器,还需进行以下步骤:

1. 取消注释optimizers['RMSprop'] = RMSprop()这一行,以导入RMSprop优化器。

2.在实验设置部分(步骤1)的循环中,为RMSprop优化器添加一个网络和训练损失的条目。修改以下代码段:

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] = []

将其修改为:

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] = []

3.在训练部分(步骤2)的循环中,更新RMSprop优化器的参数。修改以下代码段:

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:
        print( "===========" + "iteration:" + str(i) + "===========")
        for key in optimizers.keys():
            loss = networks[key].loss(x_batch, t_batch)
            print(key + ":" + str(loss))

结果以上详细分析,最终加入的RMSprop的代码为:

# 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]
batch_size = 128
max_iterations = 2000


# 1:进行实验的设置==========
optimizers = {}
optimizers['SGD'] = SGD()
optimizers['Momentum'] = Momentum()
optimizers['AdaGrad'] = AdaGrad()
optimizers['Adam'] = Adam()
optimizers['RMSprop'] = 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)
        
        if key == 'RMSprop':  # 添加RMSProp更新部分
            optimizer = optimizers[key]
            optimizer.lr = 0.01  # 可根据需要设置学习率
            optimizer.decay_rate = 0.99  # 可根据需要设置衰减率
            optimizer.update(networks[key].params, grads)
        else:
            optimizers[key].update(networks[key].params, grads)

        loss = networks[key].loss(x_batch, t_batch)
        train_loss[key].append(loss)

if 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", "RMSprop": "v"}
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()

运行结果:

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

图4-5

🌼4. 问题的解决

1. 如果我们设置γ = 1,实验会发生什么?为什么?

解:如果将RMSprop算法中的decay_rate参数γ设置为1,即self.decay_rate = 1。在RMSprop算法中,decay_rate参数用于控制历史梯度平方和的衰减率。在每次更新参数时,历史梯度平方和会乘以decay_rate,表示旧的历史梯度平方和的贡献在更新中保持不变。当decay_rate等于1时,历史梯度平方和不会被衰减,它将保持不变。这意味着在每次参数更新中,历史梯度平方和的值不会改变,对梯度的调整没有任何影响。

结果是RMSprop算法将变得与普通的梯度下降算法(如SGD)类似,因为历史梯度平方和的衰减不再发挥作用。实验中的网络更新将类似于SGD,不会发生自适应调整学习率的效果。从而导致算法的性能下降,训练过程中的更新步长可能过大,且收敛速度可能变慢。

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

图4-6 设置γ = 1的RMSprop两次结果(右图不显示)

2. 旋转优化问题以最小化f(x) = 0.1*(x1 + x2)**2 + 2(x1 x2)**2。收敛会发生什么?

解:在使用优化算法进行收敛时,不同的优化算法可能表现出不同的收敛行为:

SGD:由于旋转对称性,SGD可能会在搜索空间中震荡并缓慢收敛到最优点。它的收敛速度较慢。

Momentum:具有积累梯度的特性,可以在梯度方向上加速收敛。由于旋转对称性,Momentum算法可能会更快地收敛到最优点。

AdaGrad:通过自适应地调整学习率来处理不同特征的梯度变化。然而,在旋转优化问题中,由于旋转对称性,AdaGrad可能会导致学习率过早地衰减,从而导致收敛速度较慢。

Adam:结合了Momentum和AdaGrad的优点,具有较好的收敛性能。由于旋转对称性,Adam算法可能会更快地收敛到最优点。

RMSProp:自适应学习率的优化算法,通过调整学习率的大小来适应不同特征的梯度变化。在旋转优化问题中,由于函数 f(x) 具有旋转对称性,不同方向上的梯度变化可能会不同。RMSProp算法的自适应学习率机制可以在不同方向上调整学习率的大小,从而有助于更快地收敛到最优点。

3. 随着优化的进展,需要调整γ吗?RMSProp算法对此有多敏感?

解:通常情况下,较小的默认值(例如0.9或0.99)已经可以在许多问题上产生良好的效果,因此通常不需要频繁地调整γ的值。

RMSProp算法在大多数情况下对γ的选择相对不太敏感。


🌞四、实验心得

通过此次实验,我深入学习了RMSProp算法的原理和工作机制,并成功实现了一个RMSProp优化器。RMSProp算法通过自适应地调整学习率和使用梯度平方的指数加权移动平均缓存,可以在训练过程中加速收敛并提高性能。

在实验中,我将RMSProp算法应用于神经网络的训练过程。首先,选择了适当的神经网络模型和训练数据集,然后使用自己实现的RMSProp优化器进行参数更新。通过观察训练过程中的损失函数值和准确率等指标,从而比较使用RMSProp算法和传统梯度下降算法在训练过程中的性能和收敛速度。

在收集实验结果和进行分析时,我记录了训练过程中的损失函数值和准确率,并绘制了曲线图。通过对比使用RMSProp算法和传统梯度下降算法的实验结果,我发现RMSProp算法在加速收敛和提高性能方面表现出色。相较于传统梯度下降算法,使用RMSProp算法的自适应学习率调整和梯度平方的指数加权移动平均缓存机制使得它能够在训练过程中自动调整学习率,并更有效地利用梯度信息,从而加速了模型的收敛速度和提高了性能。并且能够更快地收敛到较低的损失函数值。

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现,# 【深度学习】,人工智能,深度学习,RMSProp算法,优化算法,梯度下降,机器学习文章来源地址https://www.toymoban.com/news/detail-846396.html

到了这里,关于【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动力节点|深入浅出Vue框架学习教程,带你快速掌握前端开发核心技能

    Vue是一款流行的JavaScript前端框架,最初由华人开发者尤雨溪创建,并在GitHub上开源发布,它采用MVVM模型的设计思维,专注于UI项目的开发,能够方便地组织和管理页面上的各个组件,大大提高了前端开发的效率。 同时,Vue也具有高度的灵活性和可定制性,使得其在快速开发

    2024年02月13日
    浏览(52)
  • 深入浅出线程池

    线程 (thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际 运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线 程并行执行不同的任务。 既然我们创建了线程,那为何我们直接调用方法和我们调

    2024年02月08日
    浏览(50)
  • 深入浅出 Typescript

    TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准(ES6 教程)。 TypeScript 由微软开发的自由和开源的编程语言。 TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。 TypeScript JavaScript JavaScript 的超集,用于解决大型

    2024年02月14日
    浏览(52)
  • 深入浅出前端本地储存

    2021 年,如果你的前端应用,需要在浏览器上保存数据,有三个主流方案: Cookie Web Storage (LocalStorage) IndexedDB 这些方案就是如今应用最广、浏览器兼容性最高的三种前端储存方案 今天这篇文章就聊一聊这三种方案的历史,优缺点,以及各自在今天的适用场景 文章在后面还会提

    2024年04月17日
    浏览(84)
  • 深入浅出Kafka

    这个主题 武哥漫谈IT ,作者骆俊武 讲得更好 首先我们得去官网看看是怎么介绍Kafka的: https://kafka.apache.org/intro Apache Kafka is an open-source distributed event streaming platform. 翻译成中文就是:Apache Kafka 是一个开源的分布式流处理平台。 Kafka 不是一个消息系统吗?为什么被称为分布式

    2023年04月11日
    浏览(73)
  • 深入浅出IAM(1)

    在本人即将入职的一份基础架构的工作前,我提前联系到了团队leader并跟他进行了一次1-1。谈话中提到了我可能会先上手的一个项目是IAM相关的实现,于是趁着入职前的间隙,我学习了部分优秀开源IAM项目实现思路以及腾讯云开发专家孔老师的专栏。 在反复思考和总结提炼后

    2024年02月05日
    浏览(47)
  • 深入浅出CenterFusion

    自动驾驶汽车的感知系统一般由多种传感器组成,如lidar、carmera、radar等等。除了特斯拉基于纯视觉方案来进行感知之外,大多数研究还是利用多种传感器融合来建立系统,其中lidar和camera的融合研究比较多。 CenterFusion这篇文章基于nuscenes数据集研究camera和radar的特征层融合,

    2024年02月09日
    浏览(50)
  • Llama深入浅出

    前方干货预警:这可能是你能够找到的 最容易懂 的 最具实操性 的 学习开源LLM模型源码 的教程。 本例从零开始基于transformers库 逐模块搭建和解读Llama模型源码 (中文可以翻译成羊驼)。 并且训练它来实现一个有趣的实例:两数之和。 输入输出类似如下: 输入:\\\"12345+54321=\\\"

    2024年02月09日
    浏览(62)
  • 随机森林算法深入浅出

    目录 一 随机森林算法的基本原理 二 随机森林算法的优点 1. 随机森林算法具有很高的准确性和鲁棒性 2. 随机森林算法可以有效地避免过拟合问题 3. 随机森林算法可以处理高维度数据 4. 随机森林算法可以评估特征的重要性 三 随机森林算法的缺点 1. 随机森林算法对于少量数

    2023年04月08日
    浏览(57)
  • 深入浅出理解HTTPS

    1.对称密钥(Symmetric Encryption) 对称密钥加密算法使用相同的 密钥(Symmetric key) 来进行数据 加密(encryption) 和 解密(decryption) 加密和解密过程都使用相同的密钥,因此 加密速度较快 ,适用于大量数据的加密。 问题在于密钥的管理:在通信双方交流之前,需要确保安全地分

    2024年02月10日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包