当前位置: 首页 > news >正文

别再死记硬背公式了!用Python手把手实现吴恩达浅层神经网络(附完整代码)

用Python从零实现吴恩达浅层神经网络:告别公式恐惧的实战指南

当你第一次接触神经网络时,是否曾被那些复杂的数学符号和层层嵌套的公式吓到?本文将通过Python代码,带你一步步构建一个完整的浅层神经网络,让抽象的理论变得触手可及。我们将使用NumPy实现前向传播、反向传播和参数更新的全过程,并在每个步骤中解释代码背后的数学原理。

1. 神经网络基础架构搭建

在开始编码前,我们需要明确浅层神经网络的基本结构。一个典型的单隐藏层网络包含输入层、隐藏层和输出层三部分。输入层的节点数由特征维度决定,隐藏层节点数可自由设定,输出层节点数则由任务类型决定(如二分类问题通常为1个节点)。

首先导入必要的库并初始化参数:

import numpy as np def initialize_parameters(n_x, n_h, n_y): """ 初始化神经网络参数 参数: n_x -- 输入层节点数 n_h -- 隐藏层节点数 n_y -- 输出层节点数 返回: parameters -- 包含初始化参数的字典: W1 -- 隐藏层权重矩阵 (n_h, n_x) b1 -- 隐藏层偏置向量 (n_h, 1) W2 -- 输出层权重矩阵 (n_y, n_h) b2 -- 输出层偏置向量 (n_y, 1) """ np.random.seed(1) 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)) parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2} return parameters

注意:权重初始化为小随机数而非零值非常重要,这可以打破对称性,使不同神经元学习到不同的特征。偏置项则可以初始化为零。

2. 前向传播实现细节

前向传播是神经网络预测的核心过程,包含线性变换和激活函数两个关键步骤。我们将实现sigmoid和ReLU两种常用激活函数:

def sigmoid(z): return 1 / (1 + np.exp(-z)) def relu(z): return np.maximum(0, z) def forward_propagation(X, parameters): """ 实现前向传播 参数: X -- 输入数据 (n_x, m) parameters -- 包含参数的字典 返回: A2 -- 第二层激活值 (输出层) cache -- 包含中间值的字典 (Z1, A1, Z2, A2) """ W1 = parameters["W1"] b1 = parameters["b1"] W2 = parameters["W2"] b2 = parameters["b2"] # 第一层计算 Z1 = np.dot(W1, X) + b1 A1 = relu(Z1) # 隐藏层使用ReLU # 第二层计算 Z2 = np.dot(W2, A1) + b2 A2 = sigmoid(Z2) # 输出层使用sigmoid cache = {"Z1": Z1, "A1": A1, "Z2": Z2, "A2": A2} return A2, cache

维度检查表

变量维度说明
W1(n_h, n_x)隐藏层权重矩阵
b1(n_h, 1)隐藏层偏置向量
W2(n_y, n_h)输出层权重矩阵
b2(n_y, 1)输出层偏置向量
Z1, A1(n_h, m)隐藏层线性输出和激活值
Z2, A2(n_y, m)输出层线性输出和激活值

3. 成本函数计算与验证

成本函数衡量预测值与真实值的差距,对于二分类问题通常使用交叉熵损失:

def compute_cost(A2, Y): """ 计算交叉熵成本 参数: A2 -- 输出层激活值 (n_y, m) Y -- 真实标签 (n_y, m) 返回: cost -- 交叉熵成本 """ 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) # 确保cost是标量而非数组 return cost

提示:在实现成本函数时,常会遇到数值不稳定的问题。可以添加一个极小值(如1e-15)防止log(0)的情况。

4. 反向传播与参数更新

反向传播是神经网络学习的核心,通过链式法则计算梯度并更新参数。下面是完整的实现:

def backward_propagation(parameters, cache, X, Y): """ 实现反向传播 参数: parameters -- 包含参数的字典 cache -- 包含中间值的字典 X -- 输入数据 (n_x, m) Y -- 真实标签 (n_y, m) 返回: grads -- 包含各参数梯度的字典 """ m = X.shape[1] W1 = parameters["W1"] W2 = parameters["W2"] A1 = cache["A1"] A2 = cache["A2"] # 输出层梯度 dZ2 = A2 - Y dW2 = np.dot(dZ2, A1.T) / m db2 = np.sum(dZ2, axis=1, keepdims=True) / m # 隐藏层梯度 dA1 = np.dot(W2.T, dZ2) dZ1 = np.multiply(dA1, np.int64(A1 > 0)) # ReLU导数 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 def update_parameters(parameters, grads, learning_rate=0.01): """ 使用梯度下降更新参数 参数: parameters -- 包含参数的字典 grads -- 包含梯度的字典 learning_rate -- 学习率 返回: parameters -- 更新后的参数字典 """ 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

反向传播关键点解析

  1. 输出层梯度计算:直接由预测值与真实值的差异开始
  2. 隐藏层梯度计算:需要考虑激活函数的导数
    • 对于ReLU,导数为1(当输入>0)或0(当输入≤0)
  3. 参数更新:使用学习率控制更新步长

5. 整合模型训练流程

将上述组件整合成一个完整的神经网络模型:

def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False): """ 神经网络模型 参数: X -- 输入数据 (n_x, m) Y -- 真实标签 (n_y, m) n_h -- 隐藏层节点数 num_iterations -- 迭代次数 print_cost -- 是否每1000次打印成本 返回: parameters -- 学习后的参数 """ np.random.seed(3) n_x = X.shape[0] n_y = Y.shape[0] parameters = initialize_parameters(n_x, n_h, n_y) for i in range(num_iterations): # 前向传播 A2, cache = forward_propagation(X, parameters) # 成本计算 cost = compute_cost(A2, Y) # 反向传播 grads = backward_propagation(parameters, cache, X, Y) # 参数更新 parameters = update_parameters(parameters, grads) if print_cost and i % 1000 == 0: print(f"迭代次数 {i}: 成本 {cost}") return parameters

训练过程可视化

随着迭代次数的增加,成本函数应该呈现下降趋势。如果成本没有下降或波动剧烈,可能表明:

  • 学习率设置不当(过大或过小)
  • 网络结构存在问题(如隐藏层节点数过少)
  • 梯度计算有误(需要仔细检查反向传播实现)

6. 模型预测与性能评估

训练完成后,我们可以使用学习到的参数进行预测:

def predict(parameters, X): """ 使用学习到的参数进行预测 参数: parameters -- 包含参数的字典 X -- 输入数据 (n_x, m) 返回: predictions -- 预测结果 (n_y, m) """ A2, _ = forward_propagation(X, parameters) predictions = (A2 > 0.5).astype(int) return predictions

评估指标

对于分类问题,常用的评估指标包括:

  • 准确率(Accuracy)
  • 精确率(Precision)
  • 召回率(Recall)
  • F1分数

可以计算这些指标来全面评估模型性能:

def evaluate_model(parameters, X, Y): """ 评估模型性能 参数: parameters -- 包含参数的字典 X -- 测试数据 (n_x, m) Y -- 真实标签 (n_y, m) 返回: accuracy -- 分类准确率 """ predictions = predict(parameters, X) accuracy = np.mean((predictions == Y).all(axis=0)) return accuracy

7. 实战技巧与常见问题

在实现神经网络时,经常会遇到各种问题。以下是一些常见问题及其解决方案:

维度不匹配错误

  • 检查每一层的输入输出维度
  • 使用printassert语句验证维度
  • 特别注意矩阵乘法的顺序和转置

梯度消失/爆炸

  • 使用适当的权重初始化方法
  • 考虑使用批量归一化
  • 尝试不同的激活函数

过拟合

  • 增加训练数据
  • 使用L2正则化
  • 尝试dropout技术

学习率选择

  • 从较大的学习率开始尝试(如0.1)
  • 如果成本波动剧烈,降低学习率
  • 可以考虑学习率衰减策略

调试技巧

  1. 梯度检查:实现数值梯度计算并与解析梯度比较
  2. 小数据集测试:先在少量数据上训练,确保成本下降
  3. 可视化:绘制成本曲线和参数分布
def gradient_check(parameters, gradients, X, Y, epsilon=1e-7): """ 实现梯度检查 参数: parameters -- 包含参数的字典 gradients -- 包含梯度的字典 X -- 输入数据 Y -- 真实标签 epsilon -- 微小变化量 返回: difference -- 数值梯度与解析梯度的差异 """ parameters_values = parameters_to_vector(parameters) grad = gradients_to_vector(gradients) num_parameters = parameters_values.shape[0] J_plus = np.zeros((num_parameters, 1)) J_minus = np.zeros((num_parameters, 1)) gradapprox = np.zeros((num_parameters, 1)) for i in range(num_parameters): theta_plus = np.copy(parameters_values) theta_plus[i][0] = theta_plus[i][0] + epsilon A2, _ = forward_propagation(X, vector_to_parameters(theta_plus)) J_plus[i] = compute_cost(A2, Y) theta_minus = np.copy(parameters_values) theta_minus[i][0] = theta_minus[i][0] - epsilon A2, _ = forward_propagation(X, vector_to_parameters(theta_minus)) J_minus[i] = compute_cost(A2, Y) gradapprox[i] = (J_plus[i] - J_minus[i]) / (2 * epsilon) numerator = np.linalg.norm(grad - gradapprox) denominator = np.linalg.norm(grad) + np.linalg.norm(gradapprox) difference = numerator / denominator if difference > 1e-7: print("梯度检查警告: 差异过大!") return difference

8. 扩展与优化

基础实现完成后,可以考虑以下优化方向:

性能优化

  • 使用向量化操作替代循环
  • 考虑使用GPU加速
  • 实现mini-batch梯度下降

功能扩展

  • 添加L2正则化项
  • 实现不同的优化算法(如Adam)
  • 支持多分类问题(使用softmax输出层)

超参数调优

  • 隐藏层节点数
  • 学习率
  • 激活函数选择
  • 正则化参数
def nn_model_with_regularization(X, Y, n_h, lambd=0.7, num_iterations=10000): """ 带L2正则化的神经网络模型 参数: X -- 输入数据 Y -- 真实标签 n_h -- 隐藏层节点数 lambd -- 正则化参数 num_iterations -- 迭代次数 返回: parameters -- 学习后的参数 """ n_x = X.shape[0] n_y = Y.shape[0] parameters = initialize_parameters(n_x, n_h, n_y) for i in range(num_iterations): A2, cache = forward_propagation(X, parameters) cost = compute_cost_with_regularization(A2, Y, parameters, lambd) grads = backward_propagation_with_regularization(X, Y, cache, lambd) parameters = update_parameters(parameters, grads) return parameters
http://www.jsqmd.com/news/929058/

相关文章:

  • 南海区26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • Arduino避障机器人:从硬件选型到代码实现的完整实践指南
  • 基于Transformer与GPT-2的惠特曼风格诗歌生成器实践
  • Veo 2分辨率配置深度解析(行业首发12K超采样白皮书):NVIDIA/AMD/Apple芯片专属优化矩阵
  • 别再死记硬背公式了!用NumPy手写一个神经元,彻底搞懂矩阵运算与并行加速
  • Django搭建的轻量级物业后台系统,含业主管理、报修工单与费用记录功能
  • 集成toxic-comment-model到现有系统:Python API调用与微调实战
  • 【Redis从入门到精通】第23篇:ZSet对象——ziplist和skiplist的完美组合
  • 从零设计电子徽章:EasyEDA实战与PCB制作全流程
  • 蓬江区26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • Zotero-GPT:将AI智能文献分析融入学术工作流的实践指南
  • AMD Ryzen调试完全指南:免费开源SMUDebugTool终极教程
  • 基于可逆数据隐藏的WSNs多项目数据完整性认证方案
  • 基于Arduino与WS2812B的智能助眠氛围灯DIY全攻略
  • leetcode 2126. 摧毁小行星 中等
  • stsb-xlm-r-multilingual应用场景:智能客服、文档检索、内容推荐
  • Sora 2 vs Runway Gen-3 vs Pika 1.5:横向评测8K分辨率下运动连贯性、纹理保真度与时序一致性(附原始测试帧下载链接)
  • 从入门到精通:微软Lens模型完整安装与配置教程
  • 坡头区26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • 2026淋雨试验箱品牌推荐:靠谱品牌筑牢防水测试合规防线 - 资讯速览
  • SY_AICC/gpt2-conversational-retrain模型参数调优指南:温度、top_p、top_k等超参数详解
  • 3分钟掌握Godot PCK文件解包:免费工具一键提取游戏资源
  • AI赋能小企业HR:从招聘到绩效的智能实践指南
  • AI Agent 12 项底层核心原理 + 应用方法
  • 【GitHub】Understand-Anything 深度技术分析:让代码库“开口说话“的交互式知识图谱
  • 终极微信聊天记录导出备份指南:永久保存你的珍贵回忆
  • 一个草根创业者的“最小可行性实践
  • Arduino智能感应骨架:超声波传感器与步进电机联动实现自动惊吓装置
  • 保姆级教程:在Ubuntu 20.04上搞定《视觉SLAM十四讲》第二版所有依赖库(Eigen、Pangolin、Ceres、g2o)
  • 三水区26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化