Skip to content

神经网络 (Neural Networks)

一句话定义:神经网络是一种模仿生物神经元连接结构的计算模型,通过层级化的数学变换,从数据中学习复杂的特征表示。

它由神经元 (Neuron) 组成,神经元之间通过权重 (Weights) 连接,并按层 (Layer) 排列。


🎨 交互演示:前向传播 (Interactive)

Section titled “🎨 交互演示:前向传播 (Interactive)”

调整输入值,观察信号如何在神经网络中逐层传播(前向传播)。

🧠 神经网络前向传播

0.5
0.8
输出 y = σ(Σ wᵢhᵢ)
0.6175

💡 调整输入值 x₁ 和 x₂,观察信号如何在网络中传播(前向传播)


在浏览器中直接运行一个微型神经网络!这里使用 TensorFlow.js。 你可以修改输入 x 或权重 w,看看输出 y 会怎么变。

import * as tf from '@tensorflow/tfjs';

// 1. 定义神经元参数
// 权重 w (比如:对 [朋友, 天气, 钱] 的重视程度)
const w = tf.tensor([0.8, 0.1, 0.9]); 
// 偏置 b (决策门槛)
const b = tf.scalar(-0.5);

// 2. 模拟输入数据
// [朋友有空=1, 天气好=1, 没钱=0]
const x = tf.tensor([1.0, 1.0, 0.0]);

// 3. 前向传播计算
// y = sigmoid(w * x + b)
const z = x.dot(w).add(b);
const y = z.sigmoid();

// 4. 输出结果
console.log("Input:", x.toString());
console.log("Weighted Sum (z):", z.toString());
console.log("Output Probability (y):", y.toString());

if (y.dataSync()[0] > 0.5) {
console.log("🎉 决定:去吃火锅!");
} else {
console.log("✋ 决定:还是算了吧。");
}

document.getElementById("app").innerHTML = `
<div style="font-family: sans-serif; padding: 20px;">
  <h3>🧮 神经元计算结果</h3>
  <p>加权和 (z): <strong>${z.dataSync()[0].toFixed(3)}</strong></p>
  <p>激活输出 (y): <strong>${y.dataSync()[0].toFixed(3)}</strong></p>
  <p>结论: ${y.dataSync()[0] > 0.5 ? "🎉 去吃火锅" : "✋ 不去"}</p>
</div>
`;

想象你在决定”今晚是否去吃火锅”。

  • 输入层:影响因素(向量)。
    • 朋友有空吗?(x1x_1)
    • 天气冷吗?(x2x_2)
    • 兜里有钱吗?(x3x_3)
  • 权重 (ww):你对每个因素的重视程度。
    • 你很在意钱,所以 w3w_3 很大。
    • 你不在意天气,所以 w2w_2 很小。
  • 激活函数:决策门槛。
    • 如果 加权总和 > 阈值,就去吃(输出 1)。
    • 否则不去(输出 0)。

神经网络就是成千上万个这样的”微型投票机”串联在一起,第一层的投票结果作为第二层的输入,层层递进,最终做出极其复杂的判断(如:这张图片是猫还是狗)。



单个神经元的计算过程:

神经元公式
y=σ((wixi)+b)=σ(wx+b)y = \sigma(\sum (w_i x_i) + b) = \sigma(\mathbf{w} \cdot \mathbf{x} + b)
  • x\mathbf{x}: 输入向量
  • w\mathbf{w}: 权重向量 (Weights)
  • bb: 偏置 (Bias) - 调整激活阈值
  • σ\sigma: 激活函数 (Activation Function) - 引入非线性(如 ReLU, Sigmoid)

如果没有激活函数(σ\sigma),无论神经网络有多少层,最终都等价于一个单层线性变换(因为线性函数的组合还是线性的)。激活函数让神经网络能够拟合非线性的复杂关系(如曲线、不规则边界)。


import torch
import torch.nn as nn
# 定义一个简单的全连接神经网络
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
# 第一层: 3个输入 -> 5个神经元
self.layer1 = nn.Linear(3, 5)
# 第二层: 5个神经元 -> 1个输出
self.layer2 = nn.Linear(5, 1)
# 激活函数
self.relu = nn.ReLU()
def forward(self, x):
# x: [Batch, 3]
# 第一层计算 + 激活
# z1 = x @ W1.T + b1
# a1 = relu(z1)
x = self.relu(self.layer1(x))
# 第二层计算
# output = a1 @ W2.T + b2
x = self.layer2(x)
return x
# 使用模型
model = SimpleNet()
input_data = torch.randn(2, 3) # 2个样本,每个样本3个特征
output = model(input_data)
print(output.shape) # [2, 1]

亲自动手训练一个神经网络!选择数据集,调整网络结构,观察决策边界如何变化。

🧠神经网络游乐场

网络结构
隐藏层 14
隐藏层 24
激活函数
学习率: 0.10
Epoch:0
Loss:0.0000
网络结构
输入
H1
H2
输出

💡 调整网络结构和超参数,观察决策边界的变化


📉 梯度流动可视化 (Gradient Flow)

Section titled “📉 梯度流动可视化 (Gradient Flow)”

观察梯度如何在神经网络中反向传播,理解梯度消失和爆炸问题。

📉 梯度流动可视化

Loss
输出
L6
0.235
L5
0.053
L4
0.012
L3
0.003
L2
6.1e-4
L1
1.4e-4
Input
输入
最终梯度
1.37e-4
状态
消失
激活函数问题
梯度消失
1.0
正常 (10⁻³~10³)
消失 (<10⁻³)
爆炸 (>10³)
💡 实验建议:
  • Sigmoid + 多层 → 观察梯度消失
  • 权重缩放 > 1.5 → 观察梯度爆炸
  • 开启残差连接 → 观察如何缓解问题
  • ReLU → 导数恒为 1,缓解消失问题

💡 梯度从输出层反向传播到输入层,每层都会乘以局部梯度