9 Adam

发布时间 2023-10-07 08:53:51作者: 王哲MGG_AI
import numpy as np
import matplotlib.pyplot as plt
import scipy.io
import math
import sklearn
import sklearn.datasets

from opt_utils import load_params_and_grads, initialize_parameters, forward_propagation, backward_propagation
from opt_utils import compute_cost, predict, predict_dec, plot_decision_boundary, load_dataset
from testCases import *

%matplotlib inline
plt.rcParams['figure.figsize'] = (7.0, 4.0) 
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'

用于导入一些必要的库和设置一些图形参数

  1. import numpy as np: 这行代码导入了NumPy库,并将其命名为np,这是Python中常用的数值计算库。它用于处理数组和数值运算。

  2. import matplotlib.pyplot as plt: 这行代码导入了Matplotlib库的pyplot模块,并将其命名为plt,用于创建和显示图形。

  3. import scipy.io: 这行代码导入了SciPy库,它是一个科学计算库,用于加载和保存MATLAB格式的数据文件。

  4. import math: 这行代码导入了Python的数学库,以便在后续代码中进行数学运算。

  5. import sklearnimport sklearn.datasets: 这两行代码导入了scikit-learn库,它是一个用于机器学习和数据分析的库。datasets模块包含了一些用于加载示例数据集的工具。

  6. from opt_utils import ...: 这些行代码导入了自定义的模块或函数,它们包含了一些与优化算法和神经网络相关的工具函数。具体的函数和模块可以在opt_utils文件中找到。

  7. %matplotlib inline: 这是一个Jupyter Notebook特定的命令,它用于在Notebook中内联显示图形,而不是在外部窗口中打开。

  8. plt.rcParams['figure.figsize']plt.rcParams['image.interpolation'] 以及 plt.rcParams['image.cmap']: 这些行代码设置了Matplotlib的参数,包括图形的大小和图像的显示方式。这些参数设置将影响之后使用Matplotlib绘制的图形的外观。

这段代码的主要目的是为了准备后续的数据加载和可视化工作,以及导入优化算法和神经网络相关的自定义工具函数。

# 初始化指数加权平均值变量

def initialize_adam(parameters) :    
    L = len(parameters) // 2 
    v = {}
    s = {}
    
    for l in range(L):
        v["dW" + str(l + 1)] = np.zeros_like(parameters["W" + str(l + 1)])
        v["db" + str(l + 1)] = np.zeros_like(parameters["b" + str(l + 1)])

        s["dW" + str(l+1)] = np.zeros_like(parameters["W" + str(l + 1)])
        s["db" + str(l+1)] = np.zeros_like(parameters["b" + str(l + 1)])
    
    return v, s

这段代码是用于初始化Adam优化算法所需的指数加权平均值(Exponentially Weighted Averages)的函数。Adam是一种用于优化神经网络训练的算法,它使用指数加权平均值来更新参数。

  • def initialize_adam(parameters) :: 这是一个名为initialize_adam的函数,它接受一个参数parameters,该参数是一个包含神经网络权重和偏置的字典。

  • L = len(parameters) // 2: 这里计算了神经网络的层数,parameters字典中的键按照"W1", "b1", "W2", "b2"等命名,每个层都有一个权重矩阵W和一个偏置向量b。

  • v = {}s = {}: 这两行代码分别初始化两个字典vs,它们将用于存储Adam算法中的指数加权平均值。

  • for l in range(L):: 这是一个循环,遍历神经网络的每一层。

    • v["dW" + str(l + 1)]v["db" + str(l + 1)]: 这两行代码初始化了权重和偏置的梯度的指数加权平均值,初始值都为零。

    • s["dW" + str(l+1)]s["db" + str(l+1)]: 这两行代码初始化了权重和偏置的平方梯度的指数加权平均值,初始值也都为零。

  • 最后,函数返回了两个字典vs,它们包含了所有层的权重和偏置的指数加权平均值,这些值将在Adam优化算法中用于参数更新。

这个函数的目的是为了初始化Adam算法所需的变量,以便在后续的训练中使用。Adam算法使用这些变量来自适应地调整学习率以提高优化效果。

parameters = initialize_adam_test_case()

v, s = initialize_adam(parameters)
print("v[\"dW1\"] = " + str(v["dW1"]))
print("v[\"db1\"] = " + str(v["db1"]))
print("v[\"dW2\"] = " + str(v["dW2"]))
print("v[\"db2\"] = " + str(v["db2"]))
print("s[\"dW1\"] = " + str(s["dW1"]))
print("s[\"db1\"] = " + str(s["db1"]))
print("s[\"dW2\"] = " + str(s["dW2"]))
print("s[\"db2\"] = " + str(s["db2"]))

这段代码用于测试刚刚实现的initialize_adam函数,以确保它正确地初始化了vs两个字典,包含了梯度和平方梯度的指数加权平均值。

  1. parameters = initialize_adam_test_case(): 这行代码调用了一个测试用例函数initialize_adam_test_case(),它返回一个包含一些示例参数的字典parameters,这些参数将用于测试initialize_adam函数。

  2. v, s = initialize_adam(parameters): 这行代码调用了initialize_adam函数,传入了示例参数parameters,并将返回的vs两个字典分配给了变量。

  3. 接下来,代码打印了每个字典中的各个键对应的值,以检查初始化是否正确。

# 使用adam来更新参数

def update_parameters_with_adam(parameters, grads, v, s, t, learning_rate=0.01,
                                beta1=0.9, beta2=0.999, epsilon=1e-8):
    
    L = len(parameters) // 2                 
    v_corrected = {} # 修正后的值
    s_corrected = {}                        
    
    for l in range(L):
        # 算出v值
        v["dW" + str(l + 1)] = beta1 * v["dW" + str(l + 1)] + (1 - beta1) * grads['dW' + str(l + 1)]
        v["db" + str(l + 1)] = beta1 * v["db" + str(l + 1)] + (1 - beta1) * grads['db' + str(l + 1)]
        

        # 对v值进行修正
        v_corrected["dW" + str(l + 1)] = v["dW" + str(l + 1)] / (1 - np.power(beta1, t))
        v_corrected["db" + str(l + 1)] = v["db" + str(l + 1)] / (1 - np.power(beta1, t))
        

        # 算出s值
        s["dW" + str(l + 1)] = beta2 * s["dW" + str(l + 1)] + (1 - beta2) * np.power(grads['dW' + str(l + 1)], 2)
        s["db" + str(l + 1)] = beta2 * s["db" + str(l + 1)] + (1 - beta2) * np.power(grads['db' + str(l + 1)], 2)
    

        # 对s值进行修正
        s_corrected["dW" + str(l + 1)] = s["dW" + str(l + 1)] / (1 - np.power(beta2, t))
        s_corrected["db" + str(l + 1)] = s["db" + str(l + 1)] / (1 - np.power(beta2, t))
 

        # 更新参数
        parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - learning_rate * v_corrected["dW" + str(l + 1)] / np.sqrt(s_corrected["dW" + str(l + 1)] + epsilon)
        parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - learning_rate * v_corrected["db" + str(l + 1)] / np.sqrt(s_corrected["db" + str(l + 1)] + epsilon)


    return parameters, v, s

这段代码实现了使用Adam优化算法来更新神经网络参数的函数。Adam是一种自适应学习率的优化算法,它使用梯度的一阶和二阶矩估计来调整每个参数的学习率,以便更有效地进行训练。

  • def update_parameters_with_adam(parameters, grads, v, s, t, learning_rate=0.01, beta1=0.9, beta2=0.999, epsilon=1e-8):

    • 这是一个名为update_parameters_with_adam的函数,它接受以下参数:
      • parameters: 包含神经网络权重和偏置的字典。
      • grads: 包含梯度信息的字典,这是通过反向传播计算得到的。
      • v: 包含梯度一阶矩估计的字典,这是Adam算法中的一阶动量。
      • s: 包含梯度二阶矩估计的字典,这是Adam算法中的二阶动量。
      • t: 当前迭代的次数(用于修正动量的偏差)。
      • learning_rate: 学习率,用于控制参数更新的步长,默认为0.01。
      • beta1beta2: 用于控制一阶和二阶动量的指数衰减率,默认分别为0.9和0.999。
      • epsilon: 用于避免除以零的小常数,以稳定计算,默认为1e-8。
  • L = len(parameters) // 2: 这里计算了神经网络的层数,parameters字典中的键按照"W1", "b1", "W2", "b2"等命名,每个层都有一个权重矩阵W和一个偏置向量b。

  • v_corrected = {}s_corrected = {}: 这两行代码分别初始化两个字典v_correcteds_corrected,它们将用于存储修正后的动量值。

接下来,代码使用循环遍历每一层的权重和偏置,执行以下步骤:

  • 计算一阶动量v(指数加权平均值):

    • v["dW" + str(l + 1)]v["db" + str(l + 1)] 计算了权重和偏置的梯度的一阶动量。
  • 修正一阶动量v:

    • v_corrected["dW" + str(l + 1)]v_corrected["db" + str(l + 1)] 对一阶动量v进行修正,以校正动量的偏差。
  • 计算二阶动量s(指数加权平均值):

    • s["dW" + str(l + 1)]s["db" + str(l + 1)] 计算了权重和偏置的梯度的二阶动量。
  • 修正二阶动量s:

    • s_corrected["dW" + str(l + 1)]s_corrected["db" + str(l + 1)] 对二阶动量s进行修正,以校正动量的偏差。
  • 使用修正后的动量来更新参数:

    • parameters["W" + str(l + 1)]parameters["b" + str(l + 1)] 使用Adam算法的参数更新规则,根据一阶和二阶动量来更新权重和偏置。

最后,函数返回更新后的参数parameters,以及修正后的动量vs,这些值将在下一次迭代中用于继续优化。

这个函数的主要目的是实现Adam优化算法的参数更新步骤,以提高神经网络的训练效果。