时间可能不存在

没有追求的灵魂会很无趣

用户工具

站点工具


neuralnetwork

神经网络到底在算什么?

很多 AI 教程一上来就:

“这是神经网络,这是神经元,这是激活函数……”

然后画一张蜘蛛网一样的图。

看起来很高级。

实际上拆开以后,核心就是:

snippet.text
乘法
+
加法
+
一个函数

就这么朴素。


1. 先做一个最简单的“神经元”

假设我们要根据服务器三个指标判断:

**这台服务器是否可能过载?**

输入:

snippet.text
CPU      = 80
Memory   = 70
GPU      = 90

所以:

snippet.text
X = [80, 70, 90]

神经元给三个输入分别一个权重:

snippet.text
CPU      权重 = 0.2
Memory   权重 = 0.5
GPU      权重 = 0.3

于是:

snippet.text
W = [0.2, 0.5, 0.3]

2. 神经元第一步:加权

计算:

snippet.text
80 × 0.2
+
70 × 0.5
+
90 × 0.3

分别算:

snippet.text
16
+
35
+
27

得到:

snippet.text
78

这实际上就是我们刚才学过的:

**向量点积**

也就是:

snippet.text
X · W

3. 再加一个 Bias

神经网络里面通常还有一个:

**偏置 Bias**

假设:

snippet.text
b = -70

于是:

snippet.text
z = X·W + b

也就是:

snippet.text
z = 78 - 70

得到:

snippet.text
z = 8

所以一个神经元最核心的计算就是:

snippet.text
z = XW + b

是不是很眼熟?


4. 但是现在有个问题

得到:

snippet.text
z = 8

然后呢?

神经元需要把这个结果进行一次处理。

于是出现:

Activation Function

激活函数。

可以暂时理解成:

**把神经元计算出来的数字,再通过一个函数处理一下。**

例如最简单的:

ReLU

定义:

snippet.text
ReLU(x) = max(0,x)

意思就是:

snippet.text
如果 x > 0
    返回 x
 
如果 x < 0
    返回 0

例如:

snippet.text
ReLU(8) = 8

而:

snippet.text
ReLU(-5) = 0

5. 所以一个神经元完整流程是

snippet.text
输入
 ↓
加权
 ↓
加 Bias
 ↓
Activation
 ↓
输出

数学形式:

snippet.text
z = XW + b
 
y = ReLU(z)

也就是:

snippet.text
X
 ↓
XW+b
 ↓
ReLU
 ↓
y

这就是一个最基本的神经元。


6. 现在把一个神经元变成两个

刚才我们只有一个输出:

snippet.text
过载概率/评分

但是假设我们希望同时预测:

snippet.text
① 是否 CPU 过载
② 是否 GPU 过载

那么就需要两个神经元。

于是:

snippet.text
输入:
 
CPU
Memory
GPU
 
      ↓
 
Neuron 1
Neuron 2
 
      ↓
 
输出:
 
CPU Score
GPU Score

7. 这时候矩阵就出现了

两个神经元分别有自己的权重。

例如:

snippet.text
W =
[
  0.2  0.1
  0.5  0.4
  0.3  0.6
]

注意这个矩阵:

snippet.text
3 × 2

为什么?

因为:

snippet.text
3 个输入
2 个神经元

输入:

snippet.text
X = [80,70,90]

计算:

snippet.text
X × W

就是:

snippet.text
[80,70,90]
 
×
 
[
  0.2  0.1
  0.5  0.4
  0.3  0.6
]

8. 第一列是什么?

第一列:

snippet.text
[0.2, 0.5, 0.3]

对应:

Neuron 1 的权重

所以:

snippet.text
[80,70,90]
·
[0.2,0.5,0.3]

就是:

snippet.text
80×0.2
+
70×0.5
+
90×0.3

得到:

snippet.text
78

9. 第二列是什么?

第二列:

snippet.text
[0.1,0.4,0.6]

对应:

Neuron 2 的权重

所以:

snippet.text
[80,70,90]
·
[0.1,0.4,0.6]

计算:

snippet.text
80×0.1
+
70×0.4
+
90×0.6

得到:

snippet.text
8 + 28 + 54
= 90

所以:

snippet.text
XW = [78,90]

这就是两个神经元的输出。


10. 现在你应该看到一个非常重要的东西

我们之前学矩阵的时候:

snippet.text
(1×3) × (3×2)
=
(1×2)

现在:

snippet.text
输入:
1×3
 
权重:
3×2
 
输出:
1×2

这不是巧合。

它就是:

**一个最简单的全连接神经网络层。**

所以:

snippet.text
数学:
 
X × W
 
↓
 
神经网络:
 
输入 × 权重
 
↓
 
结果:
 
神经元输出

11. 这就是为什么“权重矩阵”那么重要

假设:

snippet.text
W =
[
  0.2  0.1
  0.5  0.4
  0.3  0.6
]

这些数字:

snippet.text
0.2
0.1
0.5
0.4
0.3
0.6

就是模型的:

**参数 Parameters**

或者:

**Weights**

模型训练的过程,本质上就是:

**不断调整这些数字。**

—

12. 为什么要调整?

假设真实答案是:

snippet.text
CPU过载 = 1
GPU过载 = 0

但是模型输出:

snippet.text
[78,90]

显然不是我们想要的结果。

于是需要一个东西衡量:

**模型到底错得有多离谱?**

这就是:

Loss

损失函数。


13. Loss 可以先简单理解成“错误分数”

例如:

snippet.text
真实值:
10
 
预测值:
8

误差:

snippet.text
2

如果:

snippet.text
真实值:
10
 
预测值:
2

误差:

snippet.text
8

所以:

**Loss 越大 → 模型越差**

text Loss ↑ 越大 = 越差 Loss ↓ 越小 = 越好

训练模型就是想办法:

snippet.text
Loss
100
 ↓
80
 ↓
50
 ↓
20
 ↓
5
 ↓
1

不断降低。


14. 这时候导数终于登场了

我们之前讲过:

导数 = 变化率。

现在问题来了:

假设某个权重:

snippet.text
W = 0.3

如果稍微修改:

snippet.text
W = 0.31

Loss 是:

snippet.text
10

变成:

snippet.text
8

说明:

调整这个权重以后,Loss 下降了。

那么我们就希望:

**继续往这个方向调整。**

反过来,如果:

snippet.text
W = 0.3
→
W = 0.31

结果:

snippet.text
Loss
10
→
15

说明:

这个方向走错了。

—

15. 梯度就是告诉我们“往哪边走”

所以训练过程:

snippet.text
当前参数
 ↓
计算 Loss
 ↓
计算 Gradient
 ↓
根据 Gradient 调整参数
 ↓
重新计算 Loss
 ↓
继续调整

这就是:

Gradient Descent

梯度下降。


16. 现在把整个神经网络串起来

你现在已经可以看懂最基本的神经网络训练:

snippet.text
               输入
                │
                ↓
          ┌───────────┐
          │  Matrix   │
          │    ×      │
          │  Weight   │
          └─────┬─────┘
                ↓
              + Bias
                ↓
          Activation
                ↓
              输出
                ↓
              Loss
                ↓
            Gradient
                ↓
         修改 Weight
                │
                └───────────→ 再来一次

你会发现:

神经网络没有想象中那么神秘。

—

17. 但是为什么要很多层?

一个神经元只能做很简单的事情。

所以我们可以:

snippet.text
输入
 ↓
Layer 1
 ↓
Layer 2
 ↓
Layer 3
 ↓
输出

例如:

snippet.text
3个输入
 ↓
10个神经元
 ↓
20个神经元
 ↓
5个神经元
 ↓
2个输出

于是就形成:

**Deep Neural Network**

深度神经网络。

“深度”主要就是:

**层比较多。**

—

18. 这里你应该注意一个很有意思的事情

每一层本质上都在做:

snippet.text
XW + b

再经过:

snippet.text
Activation

所以:

snippet.text
Layer 1
=
XW1+b1
 
Layer 2
=
XW2+b2
 
Layer 3
=
XW3+b3

然后一层接一层。

所以神经网络其实就是:

**大量矩阵运算 + 非线性函数。**

这句话非常值得记住。


19. 为什么一定要 Activation?

这是一个非常重要的问题。

如果没有 Activation:

snippet.text
X
 ↓
XW1+b1
 ↓
XW2+b2
 ↓
XW3+b3

虽然看起来有三层。

但是数学上最终仍然可以合并成:

snippet.text
XW+b

也就是说:

**没有非线性激活函数,堆再多层,本质上还是一个线性变换。**

而有了:

snippet.text
ReLU
GELU
SiLU

之后,网络才能表达非常复杂的关系。


20. 这就引出一个非常重要的概念:非线性

例如:

snippet.text
y = 2x

这是线性的。

但:

snippet.text
y = max(0,x)

就是 ReLU。

它改变了函数的形状:

snippet.text
       /
      /
     /
────●────────

负数全部变成 0。

这种非线性让神经网络能够学习复杂模式。


21. 和你未来学 Transformer 的关系

现在你已经有了一条路线:

snippet.text
向量
 ↓
矩阵
 ↓
矩阵乘法
 ↓
神经网络
 ↓
Activation
 ↓
Loss
 ↓
Gradient

再往后:

snippet.text
神经网络
 ↓
Attention
 ↓
Transformer
 ↓
LLM

而 Transformer 最核心的东西之一:

snippet.text
Q = XWq
K = XWk
V = XWv

你现在看到:

snippet.text
XW

应该已经不陌生了。

这就是为什么我不建议你直接上来学 Transformer。


22. 今天我们真正要掌握的不是神经网络,而是这句话

**神经网络的一层,本质上就是“输入向量和权重矩阵进行矩阵乘法,再加 Bias,然后经过激活函数”。**

写成:

snippet.text
Y = Activation(XW + b)

这是非常重要的一条公式。

你以后看到很多神经网络代码,实际上都在围绕这个东西展开。


neuralnetwork.txt · 最后更改: 由 chenyang