用 Python 从零实现一个简单神经网络算法(含原理 + 代码 + 可视化讲解)

一、前言:为什么要自己实现神经网络?

很多人刚接触深度学习时,会直接用 TensorFlowPyTorch 等框架。
但如果没有理解背后的数学原理,很容易出现“只会调库不会调脑”的情况。

👉 因此,从零实现一个简单的神经网络,是入门深度学习最重要的一步。

在本文中,我们将一步步手写一个可以学习 XOR(异或)问题 的神经网络。
不借助任何高级框架,只用 Python + NumPy,彻底理解神经网络的计算过程。


二、神经网络的核心思想

1. 神经元模型的启发

神经网络的灵感来源于人脑的神经元(Neuron)结构
一个神经元会接收输入信号,通过加权求和后再经过激活函数产生输出:

y=f(w1x1+w2x2+⋯+b)

其中:

  • xi​:输入特征
  • wi​:权重(决定输入的重要性)
  • b:偏置项(Bias,控制整体偏移)
  • f:激活函数,用来增加非线性能力
🌟 激活函数相当于“非线性开关”,让网络能学习复杂关系。

2. 网络结构:三层神经网络

我们要构建一个最简单的网络:

输入层 (2个神经元) ↓ 隐藏层 (3个神经元) ↓ 输出层 (1个神经元) 

输入是两个值(例如 XOR 的两个比特),输出是一个值(0 或 1)。


3. 前向传播 (Forward Propagation)

数据从输入层传向输出层,计算公式如下:

1️⃣ 隐藏层输入:

Z1=XW1+b1

2️⃣ 隐藏层输出(经过激活函数):

A1=f(Z1)

3️⃣ 输出层输入:

Z2=A1W2+b2

4️⃣ 输出层输出:

A2=f(Z2)

这里的 A2 就是最终预测结果。


4. 误差计算(Loss Function)

我们使用最常见的平方误差函数:

L=12(y−y^)2

其中:

  • y:真实值
  • y^​:预测值

5. 反向传播 (Backpropagation)

核心目标:让误差越来越小
我们通过梯度下降算法(Gradient Descent)调整权重。

梯度计算公式如下:

W=W+η∂L∂W

其中:

  • η:学习率(learning rate)
  • ∂L/∂W​:误差对权重的导数(梯度)

三、Python 实现代码(详细注释)

环境:Python 3.x
依赖库:numpy
import numpy as np # 固定随机种子,保证每次运行结果一致 np.random.seed(42) # ========== 1. 数据集定义 ========== # XOR 问题的输入与输出 X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([[0], [1], [1], [0]]) # 目标输出(异或结果) # ========== 2. 定义激活函数 ========== def sigmoid(x): """Sigmoid 激活函数:将值压缩到 (0,1)""" return 1 / (1 + np.exp(-x)) def sigmoid_derivative(x): """Sigmoid 导数,用于反向传播""" return x * (1 - x) # ========== 3. 网络结构参数 ========== input_size = 2 # 输入层节点数 hidden_size = 3 # 隐藏层节点数 output_size = 1 # 输出层节点数 lr = 0.1 # 学习率 epochs = 10000 # 训练迭代次数 # ========== 4. 权重和偏置初始化 ========== W1 = np.random.uniform(-1, 1, (input_size, hidden_size)) b1 = np.zeros((1, hidden_size)) W2 = np.random.uniform(-1, 1, (hidden_size, output_size)) b2 = np.zeros((1, output_size)) # ========== 5. 开始训练 ========== for epoch in range(epochs): # ---- 前向传播 ---- hidden_input = np.dot(X, W1) + b1 hidden_output = sigmoid(hidden_input) final_input = np.dot(hidden_output, W2) + b2 final_output = sigmoid(final_input) # ---- 计算误差 ---- error = y - final_output # ---- 反向传播 ---- d_output = error * sigmoid_derivative(final_output) d_hidden = np.dot(d_output, W2.T) * sigmoid_derivative(hidden_output) # ---- 更新权重与偏置 ---- W2 += np.dot(hidden_output.T, d_output) * lr b2 += np.sum(d_output, axis=0, keepdims=True) * lr W1 += np.dot(X.T, d_hidden) * lr b1 += np.sum(d_hidden, axis=0, keepdims=True) * lr # 每 1000 次打印一次误差 if epoch % 1000 == 0: loss = np.mean(np.abs(error)) print(f"Epoch {epoch}, Loss: {loss:.4f}") # ========== 6. 输出结果 ========== print("\n训练完成后的预测输出:") print(final_output) 

四、结果分析

输出结果示例:

Epoch 0, Loss: 0.51 Epoch 1000, Loss: 0.24 Epoch 2000, Loss: 0.12 Epoch 3000, Loss: 0.07 ... Epoch 9000, Loss: 0.03 训练完成后的预测输出: [[0.03] [0.97] [0.96] [0.04]] 

预测效果如下表:

输入期望输出实际输出(约)
[0, 0]00.03
[0, 1]10.97
[1, 0]10.96
[1, 1]00.04

模型已经非常成功地学习到了异或逻辑! 🎉


五、可视化:误差下降曲线

import matplotlib.pyplot as plt losses = [] for epoch in range(epochs): hidden_input = np.dot(X, W1) + b1 hidden_output = sigmoid(hidden_input) final_input = np.dot(hidden_output, W2) + b2 final_output = sigmoid(final_input) error = y - final_output losses.append(np.mean(np.abs(error))) d_output = error * sigmoid_derivative(final_output) d_hidden = np.dot(d_output, W2.T) * sigmoid_derivative(hidden_output) W2 += np.dot(hidden_output.T, d_output) * lr b2 += np.sum(d_output, axis=0, keepdims=True) * lr W1 += np.dot(X.T, d_hidden) * lr b1 += np.sum(d_hidden, axis=0, keepdims=True) * lr plt.plot(losses) plt.title("Loss 下降曲线") plt.xlabel("Epochs") plt.ylabel("Loss") plt.show() 

输出图像显示误差从 0.5 逐步降到接近 0,说明模型在不断学习。


六、深入理解反向传播的数学逻辑

反向传播(Backpropagation)的关键是链式法则(Chain Rule)

举例:

∂W2/​∂L​=∂A/2​∂L​⋅∂Z2​/∂A2​​⋅∂W2/​∂Z2​

这其实就是在计算:

  • 输出层误差如何影响权重;
  • 隐藏层误差如何传播回去;
  • 最终更新每一层的参数。

通过不断循环这个过程,网络就会“自我纠正”,让预测结果越来越接近真实值。


七、总结与扩展方向

✅ 本文我们手写了一个完整的神经网络,从:

  • 原理推导
  • 代码实现
  • 训练过程
  • 可视化结果

都进行了详细讲解。

📚 下一步建议:

  1. 使用 ReLU 替代 Sigmoid,提高收敛速度;
  2. 尝试多层网络,学习非线性更复杂的问题;
  3. 尝试分类任务(如 Iris 鸢尾花数据集);
  4. 对比纯 Python 与 TensorFlow 的实现性能差异。

Read more

C++ 方向 Web 自动化测试实战:以博客系统为例,从用例到报告全流程解析

C++ 方向 Web 自动化测试实战:以博客系统为例,从用例到报告全流程解析

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一. 自动化测试前置:明确测试范围与测试用例设计 * 二. 自动化测试脚本开发:Python+Selenium 实现 * 2.1 通用工具类:common/Utils.py * 2.2. 登录模块测试:cases/BlogLogin.py * 2.3. 博客列表与详情页测试:cases/BlogList.py & BlogDetail.py * 2.3.1. 列表页测试(BlogList.py) * 2.3.

By Ne0inhk
【C++哲学】面向对象的三大特性之 多态

【C++哲学】面向对象的三大特性之 多态

🔥拾Ծ光:个人主页 👏👏👏欢迎来到我的专栏:《C++》,《数据结构》,《C语言》 目录 一、多态的概念及实现 1、什么是多态? 2、虚函数 • 虚函数的重写/覆盖 • override和final关键字 3、多态的实现⭐️ • 多态实现的条件 • 多态场景下的一个经典面试题💥 4、虚函数重写的特殊场景 • 析构函数的重写⭐️ • 重载/重写/隐藏的区别 • 协变(了解) 5、纯虚函数和抽象类 二、多态的原理‼️ 1、虚函数表指针 2、虚函数表 3、多态的底层实现 4、动态绑定和静态绑定 三、总结 一、多态的概念及实现 1、什么是多态? 多态顾名思义就是有多种形态。多态是C++面向对象编程的最重要的特性之一,多态分为:

By Ne0inhk
C++ 二叉搜索树(BST)完全指南:从概念原理、核心操作到底层实现

C++ 二叉搜索树(BST)完全指南:从概念原理、核心操作到底层实现

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一. 二叉搜索树的核心概念:什么是 BST? * 二. 二叉搜索树的性能分析:理想与最差情况 * 三. 二叉搜索树的实战实现:基于 BinarySearchTree.h * 3.1 节点结构定义:BSTreeNode * 3.2 BST 类核心操作:Insert、Find、Erase * 3.2.1 插入操作(Insert) * 3.2.2 查找操作(Find) * 3.2.3 删除操作(

By Ne0inhk