2.浅层神经网络
import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.datasets
import sklearn.linear_model
from planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset, load_extra_datasets
from testCases import *
%matplotlib inline
np.random.seed(1)
#################################################
-
import numpy as np
: 导入NumPy库,用于处理和执行数值计算。通常,它被重命名为np
,以减少代码中的重复输入。 -
import matplotlib.pyplot as plt
: 导入Matplotlib库,用于绘制图表和可视化数据。通常,它被重命名为plt
,以减少代码中的重复输入。 -
import sklearn
: 导入Scikit-Learn库,这是一个用于机器学习和数据分析的强大工具。 -
import sklearn.datasets
: 导入Scikit-Learn的datasets模块,用于加载一些内置的数据集。 -
import sklearn.linear_model
: 导入Scikit-Learn的linear_model模块,该模块包含线性模型的实现。 -
from planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset, load_extra_datasets
: 从自定义模块planar_utils
中导入一些函数和工具,包括绘制决策边界的函数、S型激活函数、加载平面数据集的函数以及加载额外数据集的函数。 -
from testCases import *
: 从testCases
模块导入所有内容。这通常用于加载测试用例,以确保代码的正确性。 -
%matplotlib inline
: 这是一个Jupyter Notebook的魔法命令,它告诉Jupyter在notebook中直接显示Matplotlib图形,而不是将它们保存到文件中。 -
np.random.seed(1)
: 设置NumPy的随机种子为1。这将确保在代码中使用随机数生成器时,得到的随机数是可重现的,即多次运行代码时生成的随机数相同
#################################################
X, Y = load_planar_dataset()
plt.scatter(X[0, :], X[1, :],c=Y.ravel(), s=40, cmap=plt.cm.Spectral)
#################################################
这部分代码执行了以下操作:
-
X, Y = load_planar_dataset()
: 这行代码调用了之前从planar_utils
模块导入的load_planar_dataset
函数,用于加载一个平面数据集。数据集被加载到两个变量中,X
和Y
。X
包含了数据点的特征,Y
包含了每个数据点的标签(0或1)。 -
plt.scatter(X[0, :], X[1, :], c=Y.ravel(), s=40, cmap=plt.cm.Spectral)
: 这行代码使用Matplotlib库绘制散点图,将数据集的数据点可视化出来。具体来说:X[0, :]
和X[1, :]
表示数据集中所有数据点的 x 和 y 坐标。c=Y.ravel()
指定了每个数据点的颜色,Y.ravel()
将Y
的二维数组转换为一维数组,以便与散点的颜色对应。在这个数据集中,Y
的值是0或1,通常用颜色来表示不同的类别。s=40
指定了散点的大小为40。cmap=plt.cm.Spectral
指定了使用"Spectral"颜色地图来着色散点,这是一种在可视化中常用的颜色映射。
这段代码的结果是绘制了一个散点图,其中的数据点以不同的颜色表示,每种颜色对应一个类别(0或1),并且数据点的位置由 X[0, :]
和 X[1, :]
定义。
#################################################
shape_X = X.shape
shape_Y = Y.shape
m = Y.shape[1]
print ('X的维度是: ' + str(shape_X))
print ('Y的维度: ' + str(shape_Y))
print ('训练样本的个数是:' + str(m))
#################################################
这部分代码执行了以下操作:
-
shape_X = X.shape
: 这行代码计算了数组X
的形状(维度)。X
包含了数据点的特征,通常是一个二维数组,其中每一列代表一个特征,每一行代表一个数据点。shape_X
将包含一个元组,其中第一个元素是行数,第二个元素是列数,这将提供有关数据集维度的信息。 -
shape_Y = Y.shape
: 同样,这行代码计算了数组Y
的形状。Y
包含了数据点的标签,通常是一个一维数组,其中每个元素是一个标签。shape_Y
也将包含一个元组,其中第一个元素是行数,第二个元素是列数。在这种情况下,由于Y
是一个行向量,它的形状将是 (1, 数据点个数)。 -
m = Y.shape[1]
: 这行代码计算了数据集中的样本数。由于Y
是一个包含标签的数组,Y.shape[1]
返回的是Y
的第二维的大小,即数据点的个数。 -
最后,
print
语句用于打印出数据集X
和Y
的维度以及数据点的个数。
#################################################
clf = sklearn.linear_model.LogisticRegressionCV();
clf.fit(X.T, Y.T.ravel());
#################################################
这部分代码使用了Scikit-Learn库中的LogisticRegressionCV模型来训练一个逻辑回归模型。
-
clf = sklearn.linear_model.LogisticRegressionCV()
: 这行代码创建了一个名为clf
的逻辑回归分类器对象。LogisticRegressionCV
是Scikit-Learn中的一个类,它实现了逻辑回归模型,并且具有交叉验证功能,可以自动选择正则化参数。这可以帮助提高模型的性能。 -
clf.fit(X.T, Y.T.ravel())
: 这行代码使用训练数据来训练逻辑回归模型。具体来说:X.T
和Y.T
分别表示输入特征矩阵X
和标签向量Y
的转置。逻辑回归模型通常期望特征矩阵的每一列表示一个特征,而每个样本位于行中,因此这里进行了转置。.ravel()
函数用于将Y
的二维数组转换为一维数组,以确保输入的标签数据的形状与逻辑回归模型的期望形状相匹配。clf.fit(...)
用于将模型拟合到训练数据上,学习模型的参数,以使其能够进行二分类任务(在这种情况下,0或1)的预测。
一旦模型被训练,clf
对象就包含了已经学习到的逻辑回归模型的参数。您可以使用这个模型来进行预测,评估模型的性能,或者用于其他任务。
#################################################
LR_predictions = clf.predict(X.T)
print ('预测准确度是: %d ' % float((np.dot(Y, LR_predictions) + np.dot(1 - Y,1 - LR_predictions)) / float(Y.size) * 100) + '% ')
plot_decision_boundary(lambda x: clf.predict(x), X, Y.ravel())
#################################################
这部分代码执行了以下操作:
-
LR_predictions = clf.predict(X.T)
: 这行代码使用已经训练好的逻辑回归模型clf
对训练数据X.T
进行预测,并将预测结果存储在LR_predictions
变量中。这将包含每个数据点的二元分类预测结果(0或1)。 -
print ('预测准确度是: %d ' % float((np.dot(Y, LR_predictions) + np.dot(1 - Y,1 - LR_predictions)) / float(Y.size) * 100) + '% ')
: 这行代码计算和打印出了逻辑回归模型的预测准确度。具体来说:np.dot(Y, LR_predictions)
计算了正确分类的数据点的数量。Y
是实际标签,LR_predictions
是模型的预测结果。np.dot(1 - Y, 1 - LR_predictions)
计算了错误分类的数据点的数量。Y.size
计算了总的数据点数量。- 这些数量被用于计算准确度,并将结果以百分比的形式打印出来。
-
plot_decision_boundary(lambda x: clf.predict(x), X, Y.ravel())
: 这行代码调用了之前从planar_utils
模块导入的plot_decision_boundary
函数,用于绘制决策边界。这个函数接受一个用于进行预测的函数作为参数(在这里是clf.predict(x)
),然后绘制决策边界,将数据点分成不同的类别,并显示它们的分布。
这段代码的结果是打印出模型的预测准确度,并绘制出决策边界,以可视化地表示模型对数据的分类能力。
#################################################
def initialize_parameters(n_x, n_h, n_y):
np.random.seed(2)
W1 = np.random.randn(n_h, n_x) * 0.01
b1 = np.zeros(shape=(n_h, 1))
W2 = np.random.randn(n_y, n_h) * 0.01
b2 = np.zeros(shape=(n_y, 1))
parameters = {"W1": W1,
"b1": b1,
"W2": W2,
"b2": b2}
return parameters
#################################################
这段代码定义了一个函数 initialize_parameters
,用于初始化神经网络的参数。
-
def initialize_parameters(n_x, n_h, n_y):
: 这是函数的定义行,它接受三个参数n_x
、n_h
和n_y
,它们分别代表输入层的大小、隐藏层的大小和输出层的大小。 -
np.random.seed(2)
: 这行代码设置了随机种子,以确保每次运行程序时生成的随机数是一致的。这有助于使结果可重现。 -
W1 = np.random.randn(n_h, n_x) * 0.01
: 这行代码初始化了第一层的权重矩阵W1
。使用np.random.randn
函数生成一个均值为0、标准差为1的随机数组成的矩阵,然后乘以0.01以缩小权重的范围。这是一种常见的权重初始化方法,有助于确保权重初始值不会太大,避免梯度爆炸的问题。 -
b1 = np.zeros(shape=(n_h, 1))
: 这行代码初始化了第一层的偏差(偏置)矩阵b1
,它是一个大小为(n_h, 1)
的全零列向量。 -
W2 = np.random.randn(n_y, n_h) * 0.01
: 这行代码初始化了第二层(输出层)的权重矩阵W2
,使用了与初始化W1
相同的方法。 -
b2 = np.zeros(shape=(n_y, 1))
: 这行代码初始化了第二层的偏差(偏置)矩阵b2
,它是一个大小为(n_y, 1)
的全零列向量。 -
最后,这个函数将初始化的参数以字典的形式存储在
parameters
变量中,并返回parameters
。
这个函数的作用是为神经网络的每一层(输入层、隐藏层和输出层)初始化权重和偏差,以便开始训练神经网络。这些初始化参数是神经网络训练的起点。
#################################################
n_x, n_h, n_y = initialize_parameters_test_case()
parameters = initialize_parameters(n_x, n_h, n_y)
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
print("--------------------------------------------")
print("nn dim(" + str(n_x) + "," + str(n_h) + "," + str(n_y) + ")");
print("W1 dim:" + str(parameters["W1"].shape))
print("b1 dim:" + str(parameters["b1"].shape))
print("W2 dim:" + str(parameters["W2"].shape))
print("b2 dim:" + str(parameters["b2"].shape))
#################################################
这部分代码执行了以下操作:
-
n_x, n_h, n_y = initialize_parameters_test_case()
: 这行代码从测试用例中获取了三个值n_x
、n_h
和n_y
,它们分别代表输入层的大小、隐藏层的大小和输出层的大小。这些值是用于初始化神经网络参数的。 -
parameters = initialize_parameters(n_x, n_h, n_y)
: 这行代码调用了之前定义的initialize_parameters
函数,使用n_x
、n_h
和n_y
来初始化神经网络的参数,并将初始化后的参数存储在parameters
字典中。 -
print("W1 = " + str(parameters["W1"]))
: 这一系列的print
语句用于打印出初始化后的参数值,包括权重矩阵W1
、偏差b1
、权重矩阵W2
和偏差b2
。 -
print("--------------------------------------------")
: 这行代码用于在输出中添加一个分隔线,以便更清晰地区分不同的输出部分。 -
print("nn dim(" + str(n_x) + "," + str(n_h) + "," + str(n_y) + ")");
: 这行代码打印出神经网络的维度信息,即输入层、隐藏层和输出层的大小。 -
最后,这一系列
print
语句分别打印出每个参数的维度信息,以确保它们与期望的维度相匹配。
这段代码的主要目的是验证参数初始化函数是否按预期工作,并确保参数的维度正确。
#################################################
def forward_propagation(X, parameters):
m = X.shape[1]
print("样本数:" + str(m))
W1 = parameters['W1']
b1 = parameters['b1']
W2 = parameters['W2']
b2 = parameters['b2']
Z1 = np.dot(W1, X) + b1
A1 = np.tanh(Z1)
Z2 = np.dot(W2, A1) + b2
A2 = sigmoid(Z2)
cache = {"Z1": Z1,
"A1": A1,
"Z2": Z2,
"A2": A2}
return A2, cache
#################################################
这段代码定义了前向传播(Forward Propagation)函数 forward_propagation
,用于计算神经网络的前向传播过程。
-
def forward_propagation(X, parameters):
: 这是函数的定义行,它接受输入数据X
和神经网络的参数parameters
作为输入。 -
m = X.shape[1]
: 这行代码计算了样本的数量,存储在变量m
中。X.shape[1]
返回X
矩阵的第二维度的大小,即样本数量。 -
print("样本数:" + str(m))
: 这行代码用于打印出样本的数量,以便在执行时查看。 -
接下来的代码块获取了神经网络的参数,包括权重矩阵
W1
、偏差b1
、权重矩阵W2
和偏差b2
,这些参数是从输入的parameters
字典中获取的。 -
Z1 = np.dot(W1, X) + b1
: 这行代码计算了第一层的线性组合,即加权和,其中np.dot(W1, X)
表示权重矩阵W1
与输入数据X
的点积,然后加上偏差b1
。 -
A1 = np.tanh(Z1)
: 这行代码对第一层的线性组合应用了双曲正切激活函数tanh
,得到激活值A1
。 -
Z2 = np.dot(W2, A1) + b2
: 这行代码计算了第二层的线性组合,其中np.dot(W2, A1)
表示权重矩阵W2
与第一层的激活值A1
的点积,然后加上偏差b2
。 -
A2 = sigmoid(Z2)
: 这行代码对第二层的线性组合应用了 S 型激活函数sigmoid
,得到输出层的激活值A2
,它表示神经网络的最终预测。 -
最后,函数返回输出层的激活值
A2
和一个包含中间计算结果的缓存字典cache
,这个缓存将在后续的反向传播中使用。
这个函数执行了一次完整的前向传播,从输入数据开始,通过网络的各个层,最终得到神经网络的预测输出。
#################################################
def compute_cost(A2, Y, parameters):
m = Y.shape[1]
logprobs = np.multiply(np.log(A2), Y) + np.multiply((1 - Y), np.log(1 - A2))
cost = - np.sum(logprobs) / m
return cost
#################################################
这段代码定义了计算神经网络成本函数(cost function)的函数 compute_cost
,它用于计算神经网络的成本。
-
def compute_cost(A2, Y, parameters):
: 这是函数的定义行,它接受三个参数:A2
表示神经网络的输出(预测),Y
表示实际标签,以及神经网络的参数parameters
。 -
m = Y.shape[1]
: 这行代码计算了样本的数量,存储在变量m
中。Y.shape[1]
返回Y
矩阵的第二维度的大小,即样本数量。 -
logprobs = np.multiply(np.log(A2), Y) + np.multiply((1 - Y), np.log(1 - A2))
: 这行代码计算了成本函数的一部分,即交叉熵损失(cross-entropy loss)。具体来说:np.log(A2)
计算了神经网络输出A2
中每个样本的对数概率。np.log(1 - A2)
计算了神经网络输出的补集的对数概率。np.multiply(..., ...)
执行逐元素的乘法,将对数概率与实际标签Y
相乘,并将对数概率的补集与(1 - Y)
相乘。
-
cost = - np.sum(logprobs) / m
: 这行代码计算了最终的成本。它将逐元素乘法的结果求和,然后取负数,最后除以样本数量m
,以计算平均成本。这是典型的二分类问题的成本函数,用于衡量预测值A2
与实际标签Y
之间的差异。 -
最后,函数返回计算得到的成本值
cost
。
这个函数的目的是为了评估神经网络的性能,通过计算预测值与实际标签之间的差异来衡量模型的准确性。
#################################################
A2, Y_assess, parameters = compute_cost_test_case()
print("cost = " + str(compute_cost(A2, Y_assess, parameters)))
#################################################
这段代码执行了以下操作:
-
A2, Y_assess, parameters = compute_cost_test_case()
: 这行代码从测试用例中获取了三个值,分别是神经网络的预测值A2
、实际标签Y_assess
,以及神经网络的参数parameters
。这些值将用于测试计算成本的函数compute_cost
。 -
compute_cost(A2, Y_assess, parameters)
: 这行代码调用了compute_cost
函数,将预测值A2
、实际标签Y_assess
和神经网络参数parameters
作为输入,计算神经网络的成本。 -
print("cost = " + str(compute_cost(A2, Y_assess, parameters)))
: 这行代码将计算得到的成本值打印出来,以评估神经网络的性能。成本值衡量了神经网络的预测与实际标签之间的差异,成本越低表示预测越准确。
这段代码的目的是验证 compute_cost
函数是否按预期工作,以及在给定一组测试数据后计算出的成本是否合理
#################################################
def backward_propagation(parameters, cache, X, Y):
m = X.shape[1]
W1 = parameters['W1']
W2 = parameters['W2']
A1 = cache['A1']
A2 = cache['A2']
dZ2= A2 - Y
dW2 = (1 / m) * np.dot(dZ2, A1.T)
db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)
dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.power(A1, 2))
dW1 = (1 / m) * np.dot(dZ1, X.T)
db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True)
print("W1 dim:" + str(W1.shape))
print("W2 dim:" + str(W2.shape))
print("------------------------------")
print("dZ2 dim:" + str(dZ2.shape))
print("dZ1 dim:" + str(dZ1.shape))
print("------------------------------")
grads = {"dW1": dW1,
"db1": db1,
"dW2": dW2,
"db2": db2}
return grads
#################################################
这段代码定义了反向传播(Backward Propagation)函数 backward_propagation
,用于计算神经网络的梯度。
-
def backward_propagation(parameters, cache, X, Y):
: 这是函数的定义行,它接受四个参数:parameters
包含了神经网络的参数,cache
包含了前向传播过程中的中间计算结果,X
是输入数据,Y
是实际标签。 -
m = X.shape[1]
: 这行代码计算了样本的数量,存储在变量m
中。X.shape[1]
返回X
矩阵的第二维度的大小,即样本数量。 -
接下来的代码块获取了神经网络的参数,包括权重矩阵
W1
和W2
,以及前向传播过程中计算得到的激活值A1
和A2
。 -
dZ2= A2 - Y
: 这行代码计算了输出层的激活值A2
与实际标签Y
之间的差异,存储在dZ2
中。 -
dW2 = (1 / m) * np.dot(dZ2, A1.T)
: 这行代码计算了输出层权重矩阵W2
的梯度,用于更新参数。dW2
是通过将dZ2
与A1
的转置相乘,然后除以样本数量得到的。 -
db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)
: 这行代码计算了输出层偏差b2
的梯度,也用于参数更新。它是将dZ2
按列求和,并除以样本数量得到的。 -
dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.power(A1, 2))
: 这行代码计算了隐藏层的激活值A1
的梯度dZ1
。它使用了链式法则,通过将输出层的梯度dZ2
与权重矩阵W2
相乘,然后乘以(1 - np.power(A1, 2))
,其中(1 - np.power(A1, 2))
是双曲正切激活函数的导数。 -
dW1 = (1 / m) * np.dot(dZ1, X.T)
: 这行代码计算了隐藏层权重矩阵W1
的梯度,用于参数更新。dW1
是通过将dZ1
与输入数据X
的转置相乘,然后除以样本数量得到的。 -
db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True)
: 这行代码计算了隐藏层偏差b1
的梯度,也用于参数更新。它是将dZ1
按列求和,并除以样本数量得到的。 -
grads = {"dW1": dW1, "db1": db1, "dW2": dW2, "db2": db2}
: 这行代码将计算得到的梯度存储在一个字典grads
中,以便后续的参数更新步骤使用。 -
最后,函数返回梯度字典
grads
,这些梯度将用于更新神经网络的参数。
这个函数的作用是计算神经网络中各个参数的梯度,以便在训练过程中使用梯度下降或其他优化算法来更新参数,从而不断优化神经网络的性能。
#################################################
parameters, cache, X_assess, Y_assess = backward_propagation_test_case()
grads = backward_propagation(parameters, cache, X_assess, Y_assess)
print("dW1 dim:" + str(grads["dW1"].shape))
print("db1 dim:" + str(grads["db1"].shape))
print("dW2 dim:" + str(grads["dW2"].shape))
print("db2 dim:" + str(grads["db2"].shape))
print("------------------------------")
print ("dW1 = "+ str(grads["dW1"]))
print ("db1 = "+ str(grads["db1"]))
print ("dW2 = "+ str(grads["dW2"]))
print ("db2 = "+ str(grads["db2"]))
#################################################
def update_parameters(parameters, grads, learning_rate=1.2):
W1 = parameters['W1']
b1 = parameters['b1']
W2 = parameters['W2']
b2 = parameters['b2']
dW1 = grads['dW1']
db1 = grads['db1']
dW2 = grads['dW2']
db2 = grads['db2']
W1 = W1 - learning_rate * dW1
b1 = b1 - learning_rate * db1
W2 = W2 - learning_rate * dW2
b2 = b2 - learning_rate * db2
parameters = {"W1": W1,
"b1": b1,
"W2": W2,
"b2": b2}
return parameters
#################################################
这段代码定义了更新神经网络参数的函数 update_parameters
,它使用梯度下降算法来更新神经网络的参数。
-
def update_parameters(parameters, grads, learning_rate=1.2):
: 这是函数的定义行,它接受三个参数:parameters
包含了神经网络的参数,grads
包含了参数的梯度,learning_rate
是学习率,它控制了参数更新的步长,默认值为1.2。 -
接下来的代码块获取了神经网络的参数,包括权重矩阵
W1
和W2
,以及偏差b1
和b2
,同时也获取了参数的梯度,包括dW1
、db1
、dW2
和db2
。 -
W1 = W1 - learning_rate * dW1
: 这行代码使用梯度下降算法来更新权重矩阵W1
。新的W1
值等于旧的W1
减去学习率乘以dW1
,这将使权重朝着减小成本的方向更新。 -
b1 = b1 - learning_rate * db1
: 同样,这行代码使用梯度下降来更新偏差b1
。 -
W2 = W2 - learning_rate * dW2
: 这行代码使用梯度下降来更新权重矩阵W2
。 -
b2 = b2 - learning_rate * db2
: 同样,这行代码使用梯度下降来更新偏差b2
。 -
最后,函数将更新后的参数以字典的形式存储在
parameters
变量中,并返回parameters
。
这个函数的作用是在训练过程中根据梯度信息更新神经网络的参数,以不断减小成本并提高模型性能。学习率 learning_rate
决定了每一次参数更新的步长,它是一个重要的超参数,需要进行调整以获得最佳的训练效果。
#################################################
# 单元测试
parameters, grads = update_parameters_test_case()
parameters = update_parameters(parameters, grads)
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
#################################################
这段代码执行了以下操作:
-
parameters, grads = update_parameters_test_case()
: 这行代码从测试用例中获取了两个值,分别是神经网络的参数parameters
和参数的梯度grads
。这些值将用于测试参数更新函数update_parameters
。 -
parameters = update_parameters(parameters, grads)
: 这行代码调用了update_parameters
函数,传入参数和梯度,执行参数的更新操作。新的参数存储在parameters
变量中。 -
接下来的一系列
print
语句用于打印更新后的参数parameters
,包括权重矩阵W1
、偏差b1
、权重矩阵W2
和偏差b2
的值。
这段代码的目的是验证 update_parameters
函数是否按预期工作,以及参数是否正确更新。参数更新是深度学习训练过程中的关键步骤,它通过梯度下降来不断调整参数,以使成本函数最小化。
#################################################
def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False):
np.random.seed(3)
n_x = X.shape[0]
n_y = Y.shape[0]
parameters = initialize_parameters(n_x, n_h, n_y)
W1 = parameters['W1']
b1 = parameters['b1']
W2 = parameters['W2']
b2 = parameters['b2']
for i in range(0, num_iterations):
A2, cache = forward_propagation(X, parameters)
cost = compute_cost(A2, Y, parameters)
grads = backward_propagation(parameters, cache, X, Y)
parameters = update_parameters(parameters, grads)
if print_cost and i % 1000 == 0:
print ("在训练%i次后,成本是: %f" % (i, cost))
return parameters
#################################################
这段代码定义了一个神经网络模型的训练函数 nn_model
,用于训练一个两层的神经网络。让我逐行解释这个函数的功能:
-
def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False):
: 这是函数的定义行,它接受输入数据X
、实际标签Y
、隐藏层的大小n_h
、迭代次数num_iterations
和是否打印成本的标志print_cost
作为参数。 -
np.random.seed(3)
: 这行代码设置了随机种子,以确保每次运行程序时生成的随机数是一致的。这有助于使结果可重现。 -
n_x = X.shape[0]
和n_y = Y.shape[0]
:这两行代码分别获取输入特征的维度n_x
和输出标签的维度n_y
。 -
parameters = initialize_parameters(n_x, n_h, n_y)
: 这行代码调用了之前定义的initialize_parameters
函数,初始化神经网络的参数,并将参数存储在parameters
字典中。 -
这个函数包含一个循环,迭代次数为
num_iterations
,在每次迭代中执行以下步骤:A2, cache = forward_propagation(X, parameters)
: 调用前向传播函数forward_propagation
,计算神经网络的预测值A2
和缓存结果,缓存结果将在后续的反向传播中使用。cost = compute_cost(A2, Y, parameters)
: 调用成本计算函数compute_cost
,计算当前预测值A2
与实际标签Y
之间的成本。grads = backward_propagation(parameters, cache, X, Y)
: 调用反向传播函数backward_propagation
,计算参数的梯度。parameters = update_parameters(parameters, grads)
: 调用参数更新函数update_parameters
,使用梯度下降来更新参数。
-
如果
print_cost
为True
且迭代次数可以被1000整除,那么会打印出当前迭代次数和成本。 -
最后,函数返回训练完成后的参数
parameters
。
这个函数的作用是构建、训练和优化一个两层的神经网络模型。它包括前向传播、成本计算、反向传播和参数更新等步骤,通过多次迭代来不断调整参数,以最小化成本函数。
#################################################
# 单元测试
X_assess, Y_assess = nn_model_test_case()
parameters = nn_model(X_assess, Y_assess, 4, num_iterations=10000, print_cost=False)
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
#################################################
这段代码执行了以下操作:
-
X_assess, Y_assess = nn_model_test_case()
: 这行代码从测试用例中获取了输入数据X_assess
和实际标签Y_assess
,这些数据将用于测试神经网络模型。 -
parameters = nn_model(X_assess, Y_assess, 4, num_iterations=10000, print_cost=False)
: 这行代码调用了nn_model
函数,传入输入数据X_assess
、实际标签Y_assess
,指定了隐藏层大小为4,迭代次数为10000,且不打印成本。该函数会训练一个神经网络模型,并返回训练后的参数parameters
。 -
接下来的一系列
print
语句用于打印训练后的参数parameters
,包括权重矩阵W1
、偏差b1
、权重矩阵W2
和偏差b2
的值。
这段代码的目的是测试神经网络模型的训练过程,以及查看训练后的参数值。在这个测试中,您使用了测试用例的数据来训练模型。
#################################################
def predict(parameters, X):
A2, cache = forward_propagation(X, parameters)
predictions = np.round(A2)
return predictions
#################################################
这段代码定义了一个用于进行预测的函数 predict
,它使用训练好的神经网络参数来进行预测。让我逐行解释这个函数的功能:
-
def predict(parameters, X):
: 这是函数的定义行,它接受两个参数:parameters
包含了训练好的神经网络参数,X
是待预测的输入数据。 -
A2, cache = forward_propagation(X, parameters)
: 这行代码调用了前向传播函数forward_propagation
,使用输入数据X
和训练好的参数parameters
来计算神经网络的预测值A2
。cache
变量包含了前向传播过程中的中间计算结果,但在这里没有使用。 -
predictions = np.round(A2)
: 这行代码将预测值A2
中的每个元素四舍五入到最接近的整数,得到二分类的预测结果。通常,如果A2
大于等于0.5,预测结果会被四舍五入为1,否则会被四舍五入为0。 -
最后,函数返回包含预测结果的数组
predictions
。
这个函数的作用是使用训练好的神经网络来对输入数据进行预测,返回二分类的预测结果。这对于评估模型在新数据上的性能非常有用。
#################################################
parameters, X_assess = predict_test_case()
predictions = predict(parameters, X_assess)
print("predictions mean = " + str(np.mean(predictions)))
#################################################
这段代码执行了以下操作:
-
parameters, X_assess = predict_test_case()
: 这行代码从测试用例中获取了两个值,分别是训练好的神经网络参数parameters
和用于测试的输入数据X_assess
。 -
predictions = predict(parameters, X_assess)
: 这行代码调用了predict
函数,传入参数parameters
和输入数据X_assess
,进行预测操作。函数返回的predictions
是包含了预测结果的数组。 -
print("predictions mean = " + str(np.mean(predictions)))
: 这行代码计算了预测结果predictions
的平均值,以评估预测的准确性。如果模型的预测准确,那么平均值应该接近期望的标签分布(例如,如果有70%的正样本和30%的负样本,那么平均值应该接近0.7)。
这段代码的目的是测试 predict
函数,看看模型在测试数据上的平均预测值是否合理。
#################################################
parameters = nn_model(X, Y, n_h = 4, num_iterations=10000, print_cost=True)
predictions = predict(parameters, X)
print ('预测准确率是: %d' % float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%')
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y.ravel())
#################################################
这段代码执行了以下操作:
-
parameters = nn_model(X, Y, n_h=4, num_iterations=10000, print_cost=True)
: 这行代码调用了nn_model
函数来训练一个神经网络模型。它传入输入数据X
、实际标签Y
,指定隐藏层大小为4,迭代次数为10000,并设置print_cost=True
来打印训练过程中的成本。 -
predictions = predict(parameters, X)
: 这行代码使用训练好的模型参数parameters
对输入数据X
进行预测,得到预测结果predictions
。 -
print ('预测准确率是: %d' % float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%')
: 这行代码计算并打印了模型的预测准确率。它将预测结果predictions
与实际标签Y
进行比较,计算准确率并打印出来。 -
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y.ravel())
: 这行代码用于绘制决策边界。它通过调用plot_decision_boundary
函数,传入一个函数lambda x: predict(parameters, x.T)
,这个函数用于根据输入x
预测分类结果,并将结果与输入数据X
和实际标签Y
一起传递给plot_decision_boundary
函数以绘制决策边界。
这段代码的目的是训练一个神经网络模型,评估其在训练数据上的预测准确率,并可视化决策边界,以便观察模型的分类效果。
#################################################
plt.figure(figsize=(16, 32))
hidden_layer_sizes = [1, 2, 3, 4, 5, 20, 50]
for i, n_h in enumerate(hidden_layer_sizes):
plt.subplot(5, 2, i + 1)
plt.title('Hidden Layer of size %d' % n_h)
parameters = nn_model(X, Y, n_h, num_iterations=5000)
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y.ravel())
predictions = predict(parameters, X)
accuracy = float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100)
print ("{}个隐藏层神经元时的准确度是: {} %".format(n_h, accuracy))
#################################################
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)