吴恩达-浅层神经网络(week3)课后题

本文详细介绍了如何使用Python中的numpy、sklearn和matplotlib等库构建一个简单的神经网络模型,包括数据加载、前向传播、成本函数计算、反向传播和参数更新。通过实例展示了如何调整隐藏层大小以影响预测准确率,并提供了决策边界可视化。
摘要由CSDN通过智能技术生成

一.所需包

numpy是用于Python科学计算的基础包。
sklearn提供了用于数据挖掘和数据分析的简单高效的工具。
matplotlib是一个用于在Python中绘制图形的库。
testCases提供了一些测试示例,用于评估您的函数的正确性。
planar_utils提供了在这个任务中使用的各种实用函数。

二.总体过程

请添加图片描述
请添加图片描述

  1. 加载数据

  2. 确定网络的输入,隐藏单元和输出大小

  3. 初始化参数请添加图片描述

  4. 前向传播
    请添加图片描述

  5. 计算代价函数请添加图片描述
    请添加图片描述

  6. 反向传播请添加图片描述

  7. 更新参数

请添加图片描述

请添加图片描述

  1. 整合模型
  2. 进行预测
    当模型接收到输入数据时,它会通过前向传播(forward propagation)的过程产生输出,这个输出就是对输入数据的预测结果

三.具体实现

1.导包

# 导入所需的包
import numpy as np  # 用于数值计算
import matplotlib.pyplot as plt  # 用于绘图
from testCases import *  # 用于加载测试用例
import sklearn  # 用于机器学习
import sklearn.datasets  # 用于加载数据集
import sklearn.linear_model  # 用于构建线性模型
from planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset, load_extra_datasets  # 用于绘制决策边界、加载数据集和其他实用函数

%matplotlib inline

np.random.seed(1)  # 设置一个种子以确保结果的一致性

2.加载平面数据

# 加载平面数据集
X, Y = load_planar_dataset()

# 绘制散点图
plt.scatter(X[0, :], X[1, :], c=Y[0, :], s=40, cmap=plt.cm.Spectral)
#这行代码绘制了一个散点图,其中 X[0, :] 是数据集的第一个特征,X[1, :] 是数据集的第二个特征,Y[0, :] 是对应的标签。散点的颜色根据标签的值来确定,使用了Spectral色图。

3.获得训练集的特征数量

# 计算数据集的样本数量和特征维度
m = X.shape[1]  # 样本数量
shape_X = X.shape  # 特征矩阵的形状
shape_Y = Y.shape  # 标签矩阵的形状

4.定义神经网络结构

def layer_sizes(X, Y):
    """
    计算神经网络各层的大小
    
    参数:
    X -- 输入数据集的形状 (输入大小, 样本数量)
    Y -- 标签的形状 (输出大小, 样本数量)
    
    返回:
    n_x -- 输入层的大小
    n_h -- 隐藏层的大小
    n_y -- 输出层的大小
    """
    n_x = X.shape[0]  # 输入层大小为特征数量
    n_h = 4  # 隐藏层大小为4(这里是一个固定值,也可以根据需要进行调整)
    n_y = Y.shape[0]  # 输出层大小为标签数量

    return (n_x, n_h, n_y)

5.模型参数初始化

def initialize_parameters(n_x, n_h, n_y):
    """
    初始化神经网络的参数
    
    参数:
    n_x -- 输入层的大小
    n_h -- 隐藏层的大小
    n_y -- 输出层的大小
    
    返回:
    parameters -- 包含参数的Python字典:
                    W1 -- 形状为 (n_h, n_x) 的权重矩阵
                    b1 -- 形状为 (n_h, 1) 的偏置向量
                    W2 -- 形状为 (n_y, n_h) 的权重矩阵
                    b2 -- 形状为 (n_y, 1) 的偏置向量
    """
    
    np.random.seed(2)  # 设置一个种子以确保输出与我们的匹配,尽管初始化是随机的。
    
    # 初始化参数
    W1 = np.random.randn(n_h, n_x) * 0.01
    b1 = np.zeros((n_h, 1))
    W2 = np.random.randn(n_y, n_h) * 0.01
    b2 = np.zeros((n_y, 1))
    
    # 确保参数的形状正确
    assert (W1.shape == (n_h, n_x))
    assert (b1.shape == (n_h, 1))
    assert (W2.shape == (n_y, n_h))
    assert (b2.shape == (n_y, 1))
    
    # 将参数存储在字典中
    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}
    
    return parameters

6.前向传播

def forward_propagation(X, parameters):
    """
    前向传播
    
    参数:
    X -- 输入数据,大小为 (n_x, m)
    parameters -- 包含参数的Python字典(初始化函数的输出)
    
    返回:
    A2 -- 第二个激活函数的S形输出
    cache -- 包含 "Z1", "A1", "Z2" 和 "A2" 的字典
    """
    # 从字典中获取每个参数
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
  
    # 执行前向传播以计算 A2(概率)
    Z1 = np.dot(W1, X) + b1
    A1 = np.tanh(Z1)
    Z2 = np.dot(W2, A1) + b2
    A2 = sigmoid(Z2)
    
    assert(A2.shape == (1, X.shape[1]))
    cache = {"Z1": Z1,
             "A1": A1,
             "Z2": Z2,
             "A2": A2}
    
    return A2, cache

7.计算成本函数

def compute_cost(A2, Y, parameters):
    """
    计算交叉熵成本
    
    参数:
    A2 -- 第二个激活函数的S形输出,形状为 (1, 样本数量)
    Y -- "true" 标签向量,形状为 (1, 样本数量)
    parameters -- 包含参数的Python字典(W1, b1, W2 和 b2)
    
    返回:
    cost -- 根据公式 (13) 给出的交叉熵成本
    """
    
    m = Y.shape[1] # 样本数量

    # 计算交叉熵成本
    logprobs = np.multiply(np.log(A2), Y) + np.multiply(np.log(1 - A2), (1 - Y))
    cost = - np.sum(logprobs) / m
    
    cost = np.squeeze(cost)     # 确保成本是我们期望的维度。例如,将 [[17]] 转换为 17 
    assert(isinstance(cost, float))
    
    return cost

8.反向传播

def backward_propagation(parameters, cache, X, Y):
    """
    实现反向传播
    
    参数:
    parameters -- 包含参数的Python字典 
    cache -- 包含 "Z1", "A1", "Z2" 和 "A2" 的字典
    X -- 输入数据,形状为 (2, 样本数量)
    Y -- "true" 标签向量,形状为 (1, 样本数量)
    
    返回:
    grads -- 包含了相对于不同参数的梯度的Python字典
    """
    m = X.shape[1]
    
    # 首先,从字典 "parameters" 中检索 W1 和 W2。
    W1 = parameters["W1"]
    W2 = parameters["W2"]
        
    # 从字典 "cache" 中检索 A1 和 A2。
    A1 = cache["A1"]
    A2 = cache["A2"]
    
    # 反向传播: 计算 dW1, db1, dW2, db2. 
    dZ2 = A2 - Y
    dW2 = np.dot(dZ2, A1.T) / m
    db2 = np.sum(dZ2, axis=1, keepdims=True) / m
    dZ1 = np.dot(W2.T, dZ2) * (1 - np.power(A1, 2))
    dW1 = np.dot(dZ1, X.T) / m
    db1 = np.sum(dZ1, axis=1, keepdims=True) / m
    
    grads = {"dW1": dW1,
             "db1": db1,
             "dW2": dW2,
             "db2": db2}
    
    return grads

9.更新参数

def update_parameters(parameters, grads, learning_rate=1.2):
    """
    使用梯度下降更新参数
    
    参数:
    parameters -- 包含参数的Python字典 
    grads -- 包含梯度的Python字典 
    learning_rate -- 学习率
    
    返回:
    parameters -- 更新后的参数字典
    """
    # 从字典 "parameters" 中检索每个参数
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    
    # 从字典 "grads" 中检索每个梯度
    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

10.建立神经网络模型

def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False):
    """
    构建神经网络模型
    
    参数:
    X -- 数据集,形状为 (2, 样本数量)
    Y -- 标签,形状为 (1, 样本数量)
    n_h -- 隐藏层的大小
    num_iterations -- 梯度下降循环中的迭代次数
    print_cost -- 如果为 True,每1000次迭代打印成本
    
    返回:
    parameters -- 模型学习到的参数,可以用来预测
    """
    
    np.random.seed(3)
    n_x = layer_sizes(X, Y)[0]
    n_y = layer_sizes(X, Y)[2]
    
    # 初始化参数,然后检索 W1, b1, W2, b2。输入: "n_x, n_h, n_y"。输出 = "W1, b1, W2, b2, parameters"。
    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):
         
        # 前向传播。输入: "X, parameters"。输出: "A2, cache"。
        A2, cache = forward_propagation(X, parameters)
        # 成本函数。输入: "A2, Y, parameters"。输出: "cost"。
        cost = compute_cost(A2, Y, parameters)
        # 反向传播。输入: "parameters, cache, X, Y"。输出: "grads"。
        grads = backward_propagation(parameters, cache, X, Y)
        # 梯度下降参数更新。输入: "parameters, grads"。输出: "parameters"。
        parameters = update_parameters(parameters, grads, learning_rate=1.2)
        
        # 每1000次迭代打印成本
        if print_cost and i % 1000 == 0:
            print("迭代次数 %i 次后的成本: %f" % (i, cost))

    return parameters

11.进行预测

def predict(parameters, X):
    """
    使用学习到的参数,在X中预测每个样本的类别
    
    参数:
    parameters -- 包含参数的Python字典 
    X -- 输入数据,大小为 (n_x, m)
    
    返回:
    predictions -- 我们模型的预测向量(红色: 0 / 蓝色: 1)
    """
    
    # 使用前向传播计算概率,并使用0.5作为阈值进行分类为0/1。
    A2, cache = forward_propagation(X, parameters)
    predictions = (A2 > 0.5).astype(int)
    
    return predictions

12.运行模型

# 使用n_h维隐藏层构建模型
parameters = nn_model(X, Y, n_h=4, num_iterations=10000, print_cost=True)

# 绘制决策边界
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y[0, :])
plt.title("隐藏层大小为 " + str(4) + " 时的决策边界")

#输出准确率
predictions = predict(parameters, X)
print ('Accuracy: %d' % float((np.dot(Y,predictions.T) + np.dot(1-Y,1-predictions.T))/float(Y.size)*100) + '%')

13. 隐藏单元的数量对模型预测准确率的影响

# 设置图形大小
plt.figure(figsize=(16, 32))

# 不同的隐藏层大小
hidden_layer_sizes = [1, 2, 3, 4, 5, 10, 20]

# 遍历每个隐藏层大小
for i, n_h in enumerate(hidden_layer_sizes):
    # 在子图中绘制决策边界
    plt.subplot(5, 2, i+1)
    plt.title('隐藏层大小为 %d' % n_h)
    
    # 使用当前隐藏层大小构建模型并训练
    parameters = nn_model(X, Y, n_h, num_iterations=5000)
    
    # 绘制决策边界
    plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y[0, :])
    
    # 进行预测并计算准确率
    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))

四.总结

本文主要记录如何建立一个浅层的神经网络。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值