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'
这段代码看起来是一个Python程序的一部分,主要包括导入所需的库和模块,以及设置一些Matplotlib的图形参数。
-
导入库和模块:
numpy
:一个用于数值计算的Python库,通常用于处理数组和矩阵操作。matplotlib.pyplot
:Matplotlib库的子模块,用于绘制图形和图表。scipy.io
:SciPy库的一个模块,用于读取和写入各种文件格式,包括MATLAB文件。math
:Python标准库的一部分,提供了数学函数。sklearn
:Scikit-Learn库,用于机器学习和数据分析任务。opt_utils
:可能是一个自定义模块,包含了一些用于优化的工具函数。testCases
:可能是一个自定义模块,包含了一些测试用例。
-
Matplotlib图形参数设置:
%matplotlib inline
:这是一个Jupyter Notebook的魔法命令,用于在Notebook中嵌入Matplotlib图形。plt.rcParams['figure.figsize']
:设置图形的默认尺寸为(7.0, 4.0)英寸。plt.rcParams['image.interpolation']
:设置图像的插值方式为最近邻插值,以使图像更清晰。plt.rcParams['image.cmap']
:设置图像的默认颜色映射为灰度。
这段代码的目的是导入必要的库和设置Matplotlib的参数,以便后续的代码能够顺利运行。
# 初始化指数加权平均值字典
def initialize_velocity(parameters):
L = len(parameters) // 2 # 获取神经网络的层数
v = {}
# 循环每一层
for l in range(L):
# 因为l是从0开始的,所以下面要在l后面加上1
# zeros_like会返回一个与输入参数维度相同的数组,而且将这个数组全部设置为0
# 指数加权平均值字典的维度应该是与梯度字典一样的,而梯度字典是与参数字典一样的,所以zeros_like的输入参数是参数字典
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)])
return v
这段代码定义了一个函数 initialize_velocity(parameters)
,用于初始化指数加权平均值字典,该字典用于在优化算法中保存参数的历史梯度信息。
-
L = len(parameters) // 2
:计算神经网络的层数,这里假设parameters
是一个包含神经网络参数的字典,包括权重矩阵W
和偏置向量b
,每一层都有一个W
和一个b
。 -
v = {}
:创建一个空字典v
,用于存储指数加权平均值。 -
for l in range(L):
:循环遍历神经网络的每一层,l
表示当前层的索引,从 0 到L-1
。 -
v["dW" + str(l + 1)]
和v["db" + str(l + 1)]
:这两行分别初始化权重参数W
和偏置参数b
的历史梯度信息。np.zeros_like(parameters["W" + str(l+1)])
:使用np.zeros_like
函数创建一个与当前层的权重矩阵W
维度相同的全零数组,用于存储权重参数的历史梯度。np.zeros_like(parameters["b" + str(l+1)])
:同样,创建一个与当前层的偏置向量b
维度相同的全零数组,用于存储偏置参数的历史梯度。
-
最后,函数返回初始化后的指数加权平均值字典
v
,其中包含了每一层权重和偏置参数的历史梯度信息。
这个函数的目的是为了在优化算法(如梯度下降、动量法等)中使用,它会在每次迭代中更新参数的历史梯度信息,以帮助调整学习率或加速收敛。
parameters = initialize_velocity_test_case()
v = initialize_velocity(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"]))
这段代码用于测试之前定义的 initialize_velocity
函数,以确保它正确初始化了指数加权平均值字典 v
。
-
parameters = initialize_velocity_test_case()
:这一行调用了initialize_velocity_test_case()
函数,该函数返回了一个包含模拟参数的测试用例字典parameters
。这个测试用例字典包含了权重矩阵W
和偏置向量b
。 -
v = initialize_velocity(parameters)
:这一行调用了之前定义的initialize_velocity
函数,传入参数字典parameters
,并将返回的指数加权平均值字典存储在变量v
中。 -
下面四行代码分别打印了
v
中不同参数的历史梯度信息,以检查是否正确初始化:print("v[\"dW1\"] = " + str(v["dW1"]))
:打印第一层权重参数W1
的历史梯度信息。print("v[\"db1\"] = " + str(v["db1"]))
:打印第一层偏置参数b1
的历史梯度信息。print("v[\"dW2\"] = " + str(v["dW2"]))
:打印第二层权重参数W2
的历史梯度信息。print("v[\"db2\"] = " + str(v["db2"]))
:打印第二层偏置参数b2
的历史梯度信息。
这些打印语句用于验证 initialize_velocity
函数是否按预期工作,是否正确初始化了历史梯度信息的字典 v
。运行这段代码后,您应该能够看到每个参数的历史梯度信息(全零数组),以确认函数的正确性。
# 使用动量梯度下降算法来更新参数
def update_parameters_with_momentum(parameters, grads, v, beta, learning_rate):
L = len(parameters) // 2
# 遍历每一层
for l in range(L):
# 算出指数加权平均值。
# 下面的beta就相当于我们文章中的k。
# 看这段代码时应该回想一下我们文章中学到的“一行代码搞定指数加权平均值”的知识点
v["dW" + str(l + 1)] = beta * v["dW" + str(l + 1)] + (1 - beta) * grads['dW' + str(l + 1)]
v["db" + str(l + 1)] = beta * v["db" + str(l + 1)] + (1 - beta) * grads['db' + str(l + 1)]
# 用指数加权平均值来更新参数
parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - learning_rate * v["dW" + str(l + 1)]
parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - learning_rate * v["db" + str(l + 1)]
return parameters, v
这段代码定义了一个名为 update_parameters_with_momentum
的函数,用于使用动量梯度下降算法来更新神经网络的参数。
-
update_parameters_with_momentum
函数接受以下参数:parameters
:一个包含神经网络参数的字典,包括权重矩阵W
和偏置向量b
。grads
:一个包含梯度信息的字典,包括权重矩阵的梯度dW
和偏置向量的梯度db
。v
:一个包含指数加权平均值的字典,用于存储历史梯度信息。beta
:动量参数,通常取值在 0 到 1 之间,控制历史梯度的权重。learning_rate
:学习率,用于控制参数更新的步长。
-
L = len(parameters) // 2
:计算神经网络的层数,与参数字典的长度相关。 -
循环遍历每一层神经网络,从第 1 层到第 L 层(总共 L 层):
- 计算权重参数
W
的历史梯度信息:v["dW" + str(l + 1)]
,使用指数加权平均值的方法更新历史梯度,其中beta
控制了历史梯度的权重,(1 - beta)
控制了当前梯度的权重。 - 计算偏置参数
b
的历史梯度信息:v["db" + str(l + 1)]
,同样使用指数加权平均值的方法更新历史梯度。
- 计算权重参数
-
使用指数加权平均值来更新参数:
- 更新权重参数
W
:parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - learning_rate * v["dW" + str(l + 1)]
,这里使用了学习率来控制参数的更新步长。 - 更新偏置参数
b
:parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - learning_rate * v["db" + str(l + 1)]
。
- 更新权重参数
-
最后,函数返回更新后的参数字典
parameters
和更新后的历史梯度字典v
。
该函数实现了动量梯度下降算法,通过考虑历史梯度信息,可以更稳定地更新参数,有助于加速收敛和避免陷入局部最优解。
parameters, grads, v = update_parameters_with_momentum_test_case()
parameters, v = update_parameters_with_momentum(parameters, grads, v, beta = 0.9, learning_rate = 0.01)
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
print("v[\"dW1\"] = " + str(v["dW1"]))
print("v[\"db1\"] = " + str(v["db1"]))
print("v[\"dW2\"] = " + str(v["dW2"]))
print("v[\"db2\"] = " + str(v["db2"]))
这段代码用于测试之前定义的 update_parameters_with_momentum
函数,以确保它正确地使用动量梯度下降算法来更新参数。
-
parameters, grads, v = update_parameters_with_momentum_test_case()
:这一行调用了update_parameters_with_momentum_test_case()
函数,该函数返回了一组测试用例,包括参数字典parameters
、梯度字典grads
和历史梯度字典v
。 -
parameters, v = update_parameters_with_momentum(parameters, grads, v, beta = 0.9, learning_rate = 0.01)
:这一行调用了update_parameters_with_momentum
函数,传入参数字典parameters
、梯度字典grads
、历史梯度字典v
,以及动量参数beta
(设置为0.9)和学习率learning_rate
(设置为0.01)。函数会根据动量梯度下降算法更新参数,并将更新后的参数和历史梯度返回,并将它们分别存储在parameters
和v
变量中。 -
下面八行代码分别打印了更新后的参数和历史梯度信息,以验证
update_parameters_with_momentum
函数是否按预期工作:print("W1 = " + str(parameters["W1"]))
:打印第一层权重参数W1
的更新后值。print("b1 = " + str(parameters["b1"]))
:打印第一层偏置参数b1
的更新后值。print("W2 = " + str(parameters["W2"]))
:打印第二层权重参数W2
的更新后值。print("b2 = " + str(parameters["b2"]))
:打印第二层偏置参数b2
的更新后值。print("v[\"dW1\"] = " + str(v["dW1"]))
:打印第一层权重参数W1
的历史梯度信息。print("v[\"db1\"] = " + str(v["db1"]))
:打印第一层偏置参数b1
的历史梯度信息。print("v[\"dW2\"] = " + str(v["dW2"]))
:打印第二层权重参数W2
的历史梯度信息。print("v[\"db2\"] = " + str(v["db2"]))
:打印第二层偏置参数b2
的历史梯度信息。
这些打印语句用于验证动量梯度下降算法是否正确地更新了参数,并且历史梯度信息是否也被正确更新。运行这段代码后,您应该能够看到更新后的参数和历史梯度信息,以确认函数的正确性。