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

深度学习:从零开始手搓一个浅层神经网络(Single Hidden Layer Neural Network)

本文带你一步步用 Python 实现一个最基础的神经网络模型,理解前向传播、反向传播、梯度下降等核心概念,真正“动手”掌握深度学习的本质。


🔍 一、引言:为什么我们要自己写神经网络?

在今天,我们有 TensorFlow、PyTorch 等强大的框架可以快速构建复杂的模型。但如果你只是初学者,或者想深入理解神经网络的内部机制,亲手实现一个简单的神经网络是绝佳的学习方式。

本篇博客将带你从头到尾实现一个含有一个隐藏层的神经网络,用于解决二维平面数据分类问题(如非线性可分的数据)。我们将使用 NumPy 和 Matplotlib 手动完成所有计算,不依赖任何高级框架。


🧩 二、整体架构概览

我们构建的是如下结构的神经网络:

输入层 (2个特征) → 隐藏层 (n_h个神经元) → 输出层 (1个神经元)↓                  ↓                   ↓x₁, x₂             tanh(Z₁)           tanh(Z₂)
  • 输入:每个样本有两个特征(横纵坐标)
  • 隐藏层:n_h 个神经元,激活函数为 tanh
  • 输出层:1 个神经元,激活函数也为 tanh(也可改为 sigmoid,这里为了简化)

(注:图中红色椭圆表示输入特征,蓝色箭头表示权重连接)


📦 三、环境准备与数据加载

import matplotlib
matplotlib.use('TkAgg')  # 如果有GUI支持
import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.linear_modelfrom planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset, load_extra_datasets
from testCases import *np.random.seed(1)X, Y = load_planar_dataset()plt.scatter(X[0,:], X[1,:], c=Y.ravel(), s=40, cmap=plt.cm.Spectral)
plt.title("原始数据分布")
plt.show()

✅ 解释:

  • load_planar_dataset() 是一个辅助函数,生成了带有标签的二维点集(通常是环形或花形数据,非线性可分)。
  • 使用 scatter 可视化数据,可以看到颜色不同的两类点无法用直线分开。
  • 这正是神经网络发挥作用的地方!

🛠️ 四、参数初始化

def initialize_parameters(n_x, n_h, n_y):np.random.seed(2)W1 = np.random.randn(n_h, n_x) * 0.01b1 = np.zeros((n_h, 1))W2 = np.random.randn(n_y, n_h) * 0.01b2 = np.zeros((n_y, 1))parameters = {"W1": W1,"b1": b1,"W2": W2,"b2": b2}return parameters

✅ 说明:

  • n_x: 输入维度(这里是 2)
  • n_h: 隐藏层神经元数量(可调参)
  • n_y: 输出维度(这里是 1)
  • 权重 W 用小随机数初始化(乘以 0.01),防止梯度爆炸
  • 偏置 b 初始为 0

⏭️ 五、前向传播(Forward Propagation)

def forward_propagation(X, parameters):m = X.shape[1]W1 = parameters['W1']b1 = parameters['b1']W2 = parameters['W2']b2 = parameters['b2']Z1 = np.dot(W1, X) + b1A1 = np.tanh(Z1)Z2 = np.dot(W2, A1) + b2A2 = np.tanh(Z2)cache = {"Z1": Z1, "A1": A1, "Z2": Z2, "A2": A2}return A2, cache

✅ 数学公式:

  • 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) / mreturn cost

✅ 注意:

  • 这里用了 二元交叉熵损失函数(Binary Cross-Entropy),适用于二分类任务
  • 但注意:由于我们用了 tanh 作为激活函数,其输出范围是 [-1, 1],而标准交叉熵要求 [0,1],所以严格来说应该改用 sigmoid 或调整标签
  • 实际上,在这个练习中,我们更关注流程而非精确性,因此仍可用此形式

🔁 七、反向传播(Backward Propagation)

def backward_promagation(parameters, cache, X, Y):m = X.shape[1]W1 = parameters['W1']W2 = parameters['W2']A1 = cache['A1']A2 = cache['A2']dZ2 = A2 - YdW2 = (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)grads = {"dW1": dW1,"db1": db1,"dW2": dW2,"db2": db2}return grads

✅ 数学推导简述:

  • $ \frac{\partial L}{\partial Z_2} = A_2 - Y $
  • $ \frac{\partial L}{\partial W_2} = \frac{1}{m} dZ2 \cdot A1^T $
  • $ \frac{\partial L}{\partial Z_1} = W_2^T \cdot dZ2 \cdot (1 - A1^2) $ (因为 $ \frac{d}{dz}\tanh(z) = 1 - \tanh^2(z) $

⬇️ 八、参数更新(梯度下降)

def update_parameters(parameters, grads, learning_rate=1.2):W1 = parameters['W1'] - learning_rate * grads['dW1']b1 = parameters['b1'] - learning_rate * grads['db1']W2 = parameters['W2'] - learning_rate * grads['dW2']b2 = parameters['b2'] - learning_rate * grads['db2']parameters = {"W1": W1,"b1": b1,"W2": W2,"b2": b2}return parameters

✅ 说明:

  • 使用标准梯度下降法更新参数
  • 学习率设为 1.2,可根据训练情况调整

🔄 九、整合训练流程

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)for i in range(num_iterations):A2, cache = forward_propagation(X, parameters)cost = compute_cost(A2, Y, parameters)grads = backward_promagation(parameters, cache, X, Y)parameters = update_parameters(parameters, grads)if print_cost and i % 1000 == 0:print(f"第 {i} 次迭代后,成本为: {cost}")return parameters

✅ 功能:

  • 封装整个训练流程
  • 多次迭代优化参数
  • 打印成本变化趋势

🎯 十、测试与可视化

X_assess, Y_assess = nn_model_test_case()
parameters = nn_model(X_assess, Y_assess, 4, num_iterations=10000, print_cost=False)# 绘制决策边界
plot_decision_boundary(lambda x: predict(x, parameters), X, Y)
plt.title("训练后的决策边界")
plt.show()

✅ 效果:

  • 使用 plot_decision_boundary 绘制出模型划分的区域
  • 可以看到,即使数据是非线性可分的,神经网络也能画出弯曲的边界进行分类

🧠 十一、关键知识点总结

概念作用
前向传播计算预测值
损失函数衡量预测误差
反向传播计算梯度
梯度下降更新参数以最小化损失
隐藏层提供非线性表达能力

💡 十二、常见问题与改进方向

  1. 激活函数选择:建议将 tanh 改为 sigmoidReLU 更符合实际应用
  2. 损失函数:应使用 sigmoid + binary cross entropy 保证数值稳定性
  3. 正则化:可加入 L2 正则项防止过拟合
  4. 优化器:可尝试 Adam、RMSProp 等现代优化算法
  5. 多层网络:扩展为更深的网络(如 2 层隐藏层)

✅ 结语

通过这篇文章,你已经亲手实现了一个完整的浅层神经网络!虽然它简单,但它包含了深度学习的核心思想:

前向传播 → 计算损失 → 反向传播 → 参数更新

这正是所有深度学习框架背后的底层逻辑。


🌱 记住:真正的理解来自于亲手编码。
当你能写出这段代码,并读懂每一行的意义时,你就不再是“黑箱使用者”,而是真正的 AI 探索者。

http://www.dtcms.com/a/593820.html

相关文章:

  • 网站开发 犯法公司起名在线生成器
  • 免费.网站最新域名保定市建设局网站
  • React + TypeScript 笔试题库
  • SpringBoot项目如何使用Log4j2+SLF4J构建日志
  • AI Agent开发实战:基于ReAct范式的智能体构建与优化
  • 一线大厂 Java 岗面试通关指南:笔试题 + 面试题(答案解析)
  • C#高级:使用进程锁语法避免线程竞争资源,做到并发控制(Mutex)
  • 怎么做才能使网站ip增多网站建设哪些好
  • 龙虎榜——20251110
  • web网页开发,在线%就业信息管理%系统,基于idea,html,layui,java,springboot,mysql。
  • 网站换空间 seo西安做网站程序
  • 专为男人做的网站百度明星搜索量排行榜
  • ZSAR配置CANSM模块
  • STM32外设学习--DMA直接存储器读取--学习笔记。
  • 一本通网站1130:找第一个只出现一次的字符
  • 西安做网站那家好诸城做网站收费
  • 写的网站怎么做接口创造网站软件
  • 上海网站建设团队关于网站建设的投标书
  • 软文广告300字范文广西百度seo
  • AI数据库研究:RAG 架构运行算力需求?
  • cookie和session在客户端与服务端交互过程中的作用
  • 浅谈差分算法--区间变化的上佳策略(C++实现,结合lc经典习题讲解)
  • 重组蛋白包涵体形成原因及解决方案
  • 专注高端网站建设服装网站建设策划书论文
  • 网站设计可以用性原则有哪些做任务的网站
  • 沈阳行业网站wordpress 增加域名
  • ChIP-seq
  • 基于 LangGraph 的对话式 RAG 系统实现:多轮检索与自适应查询优化
  • 一步一步学习使用LiveBindings() LiveBindings与具有动态呈现的TListView
  • 14. PLC的编程语言(图形化语言)