让数值网络学起来

01|神经元:模型接着写字,底下先算什么?

手写小模型,看懂大模型 · 第 01 讲

输入“早上,小丁喜欢”,我们自己训练的小语言模型会接着生成“红色的苹果。”

生成程序里没有为这半句话单独写一条续写规则。几百条人物、水果和颜色短句参与了训练,改变了它保存的参数。它能续写熟悉的句子,换个说法也会错,实验记录保留了这些结果。

计算步骤不变,只改参数,为什么就能改变输出?先不追整句话,把输入缩成两个数,看看怎样让一个结果从 4 变成 5。

结果要变,先找出哪些数能调

  • 输入 [2, 1]: 本次送进来的两项数据。
  • 权重 [1, 3]: 两项输入各自配上的乘数。
  • 偏置 −1: 乘积相加之后,再加上的一个数。

权重和偏置合起来,叫作参数。接收输入、按这些参数算出一个数,是人工神经元的基本工作。

输入随数据变化;参数由模型保存,决定怎样处理数据。这里先手工指定参数,后面训练时根据错误调整;生成文字时参数固定。

输入与参数分别进入计算单元,得到一个数值输出

先算出这个 4

把两项输入记作 x₁、x₂,对应权重记作 w₁、w₂。下标只是编号:第一项输入配第一项权重,第二项配第二项。

第一条路径算 2 × 1 = 2;第二条路径算 1 × 3 = 3。

两个输入沿各自路径乘权重,分别得到乘积2和3

权重就是乘数,可以是小数或负数,用来放大、缩小或改变这一项贡献的正负号。

接着,把两个乘积相加:2 + 3 = 5。

再加偏置 −1:5 + (−1) = 4。

把偏置记作 b,把目前这个计算结果记作 z,就得到:

z = x₁ × w₁ + x₂ × w₂ + b = 4

为什么还需要偏置?输入全为 0 时,乘积之和一定是 0。偏置让这个结果也能独立调整。

允许随便调参数,也有做不到的事

上面的输出能靠参数改变,但有些要求,怎样调参数也做不到。换成单个输入 x,要求不超过 1 时输出 0,超过 1 时只输出超出的部分:

输入 x 需要的输出
0 0
1 0
2 1

只用 y = w × x + b,能同时满足吗?

输入 0 要输出 0,迫使 b = 0。接着,输入 1 也要输出 0,又迫使 w = 0。

两个参数确定后,输入 2 只能得到 0 × 2 + 0 = 0,无法得到要求的 1。换别的参数,就会破坏前两条要求。

调整参数,让输出接近目标,叫作拟合。这三个目标无法同时精确拟合,限制来自函数形式。

再接一个函数,能绕过这个限制吗?假设先算 a=x−1,再算 y=2×a+1。展开后:

y = 2 × (x − 1) + 1 = 2 × x − 1

仍然是“输入乘一个数,再加一个数”。换参数只会改变合并后的乘数和加数,继续堆叠也无法满足这三个目标。

这里的乘加指输入乘固定权重,再求和、加偏置。我们还需要让不同区间的输入得到不同处理。

让负数停在 0,三个目标就接上了

缺少的变化很具体:前半段要一直为 0,后半段才开始增长。对乘加结果 z 增加这条规则:

ReLU(z) = max(0, z)

max(0, z) 取 0 和 z 中较大的数:负数变成 0,非负数保留。这个函数叫 ReLU,是一种激活函数。

ReLU以z为输入:负1变成0,正1保留为1,在z等于0处转折

折线无法用一条直线表示,这就是所需的非线性。它也可以来自平滑曲线;这里用折线便于手算。

对刚才三个目标,取权重 w=1、偏置 b=−1:

z = 1 × x − 1

再把 z 交给 ReLU:

y = ReLU(z) = ReLU(x − 1)

输入 x z=x−1 输出 y
0 −1 0
1 0 0
2 1 1

整个神经元以x为输入:纯乘加不能满足三个目标,ReLU加偏置后在x等于1处转折

两张图的横轴不同:前图是乘加后的 z,纵轴是 ReLU 输出,转折在 z=0;后图是原始输入 x,纵轴是整个神经元输出。因为先算 z=x−1,转折就落在 x=1。沿横轴找输入,向上到曲线即可读输出;偏置移动了转折位置,ReLU 规则没变。

后图圆点是目标。蓝线由前两个目标确定,一直输出 0;加上 ReLU 后,紫色折线经过了三个点。这次参数是手工挑出的,后面再让训练程序来寻找它们。

回到那个 4,把它变成能改的代码

原来 [2, 1] 的乘加结果 z=4 为正,经过 ReLU 仍然是 4。

展开观看动态过程主算例逐步经过乘法、汇总、偏置和ReLU

需要停下来核对,可以打开完整静态图,或在逐步演示里前进、后退。

动手实验 · 逐步演示逐步核对计算过程,随时前进或后退。

展开大窗口 ↗ · 在新标签页打开 ↗

逐步演示

把最后输出记作 y,公式与数字合起来是:

y = ReLU(x₁w₁+x₂w₂+b) = ReLU(2×1+1×3−1) = 4

逐项相乘再累加,就能处理一项、两项或更多项输入:

def neuron(inputs, weights, bias=0.0):
    """输入列表与权重逐项配对,加偏置、做 ReLU,返回一个数。"""
    if len(inputs) != len(weights) or not inputs:
        raise ValueError("输入与权重必须非空且等长")

    total = 0.0
    # 同一位置的输入乘自己的权重,再把各项贡献加起来。
    for value, weight in zip(inputs, weights):
        total += value * weight
    z = total + bias
    # ReLU 只改变负数;它的规则固定,可调的是 weights 和 bias。
    return max(0.0, z)

# 本次输入为 [2, 1],参数是权重 [1, 3] 和偏置 -1。
print(neuron([2, 1], [1, 3], -1))  # 4.0

inputs、weights、bias 对应 x、w、b。zip 把对应输入和权重配对,循环相乘,total += ... 累加;最后加偏置、做 ReLU。开头的检查防止漏配权重或传入空列表。保存成 neuron.py 即可运行,只需 Python 标准功能。

改一个数,结果怎样变

代码跑出 4 后,先试着只把偏置 −1 改成 0。再改回去,把第二项输入从 1 改成 2。每次只改一处:

改动 乘加计算 输出
原例子 2×1 + 1×3 − 1 4
x₂:1 → 2 2×1 + 2×3 − 1 7
b:−1 → 0 2×1 + 1×3 + 0 5

第二项输入增加 1,输出就增加 3,因为这一份输入要先乘权重 3。三个结果为正,ReLU 都保留原值。

PYTHON · 可编辑实验

改一改,运行看看

把 x2 从 1 改成 2,输出会从 4 变成多少?

修改 Python 代码

Tab 缩进,Shift + Tab 反缩进;按 Esc 后再按 Tab 离开代码框。Ctrl / ⌘ + Enter 运行。

点击运行,结果显示在下面。

等待运行…

一个结果,能不能再交给同一个函数?

把第一个输出 4 再交给 neuron,权重取 0.5,偏置取 1:

# 沿用上一段的 neuron;前一个输出成为后一个神经元的输入。
first = neuron([2, 1], [1, 3], -1)
# 后一个神经元有自己的权重和偏置,并未修改前一个的参数。
second = neuron([first], [0.5], 1)
print(first, second)  # 4.0 3.0

前一个神经元输出4,后一个读取4再计算得到3

第二个仍执行乘加与 ReLU,只是输入变为一项。多个神经元可以各用一组参数,产生一组中间数,常称为特征。它们的作用要放在整个网络中看,不能预先认定某个数代表“苹果”或“语法”。

把两个神经元并排放,它们的输出再交给第三个,就得到下面的网络:

两项输入送到两个独立神经元,它们的输出再成为后一层的输入

  • 输入层: 两个点只放数据,不额外计算。
  • 隐藏层: A、B 位于输入与最终输出之间,读取同一组输入,各用自己的参数计算。
  • 输出层: C 把 A、B 的输出作为两项输入继续计算,图中也采用 ReLU。

每条进入神经元的连线对应一个权重,交叉点不计算。下一讲把 A、B 这样的并排计算写成矩阵,一次得到一层的多个输出。

三道小题

  1. 主算例的输入 [2, 1]、权重 [1, 3] 不变,偏置改成 −6。z 是多少?最后输出是多少?
  2. 单输入反例中,权重仍取 1,偏置从 −1 改成 −2。转折位置移到哪里?输入 2 时输出是多少?
  3. 最后的网络结构图中,有几个权重、几个偏置?两个输入点算不算可调参数?

第一题可在交互演示中把偏置调到 −6;第二题可用 neuron([2], [1], -2) 核对。

参考答案

答案:第一题,z=2×1+1×3−6=−1,输出 0。第二题,z=x−2,转折移到 x=2,输入 2 时输出 0,超过 2 才有正输出。第三题,进入 A、B 各有两条权重,进入 C 有两条,共 6 个权重;A、B、C 各有一个偏置,共 3 个偏置,合计 9 个可调参数。输入点是数据。

想让配套程序打印本讲的计算,进入 code 目录运行:

# 在配套代码目录运行本讲实验,核对正文中的结果。
python -m lessons.l01

macOS 可以用 python3,Windows 也可以用 py -m lessons.l01。完整安装与运行说明见配套代码。

配套入口:运行入口 · 交互演示 · 真实模型实验

源码导航:scalar.py · neuron。

观看配套视频6:19

输入关键词,搜索全部 23 篇文章。

交互实验
独立打开
查看配图
100%