系列回顾:前两篇我们搞定了符号语言和指数对数。这一篇我们来讲函数——这个概念你从初中就开始学,但神经网络对"函数"的理解方式,和教科书里的完全不是一回事。把这一层想清楚,你对神经网络结构的理解会有一次质的飞跃。
如果你问一个深度学习从业者"神经网络是什么",他可能会说:是一个参数化的函数族。
这句话听起来很学术,但翻译过来其实很朴素:神经网络就是一个函数,只不过这个函数非常复杂,而且它的"样子"是通过数据学出来的,而不是人手工设计的。
输入一段文字,输出下一个词的概率——这是一个函数。输入一张图片,输出"猫"或"狗"的判断——也是一个函数。输入一道数学题,输出解题过程——还是一个函数,只不过极其复杂。
DeepSeek V3 本质上就是这样一个函数:它接受一串 token(文字被切碎后的单元),通过数百层的变换,输出下一个 token 的概率分布。整个 6710 亿参数,都是这个函数的"参数"。
要理解这一切,先要把"函数"这个概念真正想清楚。
高中里学函数,往往是这样讲的:$y = f(x) = x^2 + 1$,给一个 $x$ 算一个 $y$,画出来是一条抛物线。
这没问题,但只揭示了函数的冰山一角。
函数更本质的定义是:一种输入输出的对应规则——给定一个输入,有且只有一个确定的输出。
注意两个关键词:
第一,"给定一个输入"——输入可以是任何东西,不一定是数字,可以是一个向量、一张图片、一段文字、甚至一个函数本身。
第二,"有且只有一个确定的输出"——这是函数区别于"关系"的地方。同一个输入,不能对应两个不同的输出。
理解了这个,你就能理解为什么"神经网络是函数"这个说法是严格的——同样的输入(同样的问题),在参数固定的情况下,神经网络永远给出同样的输出(温度参数为 0 时)。它就是一台确定性的机器。
有一个很好用的直觉模型:把函数想象成一个黑盒子。
输入 ──→ [ 黑盒子:函数 f ] ──→ 输出
你不需要知道盒子里发生了什么,只需要知道:塞进去一个东西,出来一个东西,规则固定。
神经网络就是一个极其复杂的黑盒子,里面有几百层的小黑盒子(每一层就是一个函数),层层嵌套。
在深度学习里,函数的输入和输出不只是单个数字,往往是向量、矩阵甚至更高维的结构。我们先把常见的函数类型捋一遍。
$$f: \mathbb{R} \rightarrow \mathbb{R}$$
比如 $f(x) = x^2$,输入一个实数,输出一个实数。
这是最简单的情况,高中数学讲的主要就是这种。
$$f: \mathbb{R}^n \rightarrow \mathbb{R}$$
输入一个 $n$ 维向量,输出一个数。
损失函数就是这种类型:输入是模型的所有参数(一个巨大的向量),输出是一个表示"有多差"的数字。
DeepSeek V3 大约有 6710 亿个参数,所以它的损失函数是一个从大约 6710 亿维空间到实数轴的映射——输入是那几千亿个参数,输出是一个衡量模型有多差的数。
$$f: \mathbb{R}^m \rightarrow \mathbb{R}^n$$
输入一个 $m$ 维向量,输出一个 $n$ 维向量。
神经网络的大多数层都是这种类型。比如一个全连接层,输入是 512 维的向量,输出是 256 维的向量,这个层就是一个 $f: \mathbb{R}^{512} \rightarrow \mathbb{R}^{256}$ 的映射。
$$f: \mathbb{R}^{m \times n} \rightarrow \mathbb{R}^{p \times q}$$
在 Transformer 里,注意力层接受一个形状为"序列长度 × 维度"的矩阵,输出一个形状相同的矩阵。整个过程就是矩阵到矩阵的映射。
掌握这些类型,看到论文里的函数定义 $f: A \rightarrow B$,你立刻就知道"它在处理什么形状的数据",这对理解模型架构非常重要。
复合函数的意思是:把一个函数的输出,作为另一个函数的输入。
$$h(x) = f(g(x))$$
先算 $g(x)$,把结果记为中间变量,再把这个中间变量塞进 $f$。
举个具体的例子:
$$g(x) = x^2 + 1$$ $$f(y) = \sqrt{y}$$ $$h(x) = f(g(x)) = \sqrt{x^2 + 1}$$
给 $x = 3$:先算 $g(3) = 10$,再算 $f(10) = \sqrt{10} \approx 3.162$。
一个深层神经网络,本质上就是多个函数的复合:
$$\text{神经网络}(x) = f_L(f_{L-1}(\cdots f_2(f_1(x)) \cdots))$$
其中 $f_1, f_2, \ldots, f_L$ 是每一层的变换函数,$L$ 是层数。
以 DeepSeek V3 为例,它有 61 个 Transformer 层,每层都是一个函数,整个网络就是这 61 个函数的复合。输入是 token 的 embedding 向量,经过 61 次变换,最后输出概率分布。
这是理解神经网络最重要的视角:它不是什么神秘的东西,就是很多个函数首尾相接,串联起来。
既然神经网络是函数的复合,那为什么不直接设计一个超大的单层函数呢?
原因有两个:
原因一:表达能力
理论上(有一个叫"通用近似定理"的结论),足够宽的单层神经网络可以近似任意连续函数。但"足够宽"意味着需要天文数字的神经元,实际上不可行。
而多层网络可以用更少的参数达到同样的表达能力——浅层学习低级特征(比如边缘、颜色),深层组合这些特征学习高级概念(比如"猫耳朵"、"眼睛")。层次化的特征提取是深度网络最核心的能力。
原因二:可优化性
多层结构配合激活函数,使得损失函数的梯度可以通过链式法则逐层反传,这是反向传播算法的基础。我们在后面讲梯度和反向传播的时候会详细展开。
线性函数满足两个条件:
可加性:$f(x + y) = f(x) + f(y)$
齐次性:$f(ax) = af(x)$
最典型的线性函数是 $f(x) = wx + b$(一次函数)。在神经网络里,矩阵乘法就是线性变换:
$$f(x) = Wx + b$$
其中 $W$ 是权重矩阵,$b$ 是偏置向量。
这是神经网络设计里最重要的一个问题,很多人没想清楚。
假设你有两个线性层:
$$h_1 = W_1 x + b_1$$ $$h_2 = W_2 h_1 + b_2 = W_2(W_1 x + b_1) + b_2 = (W_2 W_1)x + (W_2 b_1 + b_2)$$
两个线性层叠加,结果还是一个线性层!无论你叠多少层,最终等价于一个单层线性变换。
线性变换只能做一件事:旋转、缩放、平移空间。
但现实中的问题(比如图像识别、语言理解)都是高度非线性的——猫和狗的区别不是简单的线性分隔。如果神经网络只有线性变换,它的能力和一个线性分类器没有本质区别,根本无法解决复杂问题。
解决方案是在每个线性层之后加一个激活函数(Activation Function),它是一个非线性函数:
$$h = \text{activation}(Wx + b)$$
激活函数打破了线性的限制,让多层网络真正具备了拟合复杂函数的能力。
常见的激活函数有 ReLU、Sigmoid、Tanh、GELU、SiLU 等,我们在第22篇会专门讲激活函数。现在只需要记住一点:激活函数的作用是引入非线性,没有它,深度学习不存在。
举个简单的例子,ReLU 的定义:
$$\text{ReLU}(x) = \max(0, x)$$
就是"负数变零,正数保持不变",看起来简单到不像话,但就是这个简单的非线性,撑起了现代深度学习的大半江山。
这一部分我想换一个角度来理解函数:函数是对空间的变换。
考虑一个从 $\mathbb{R}^2$ 到 $\mathbb{R}^2$ 的线性函数(矩阵乘法),它对二维平面做的事情是:
这些操作叠加在一起,就是一个线性变换。
而加上激活函数(非线性)之后,变换就变得更自由——它可以"折叠"空间,把原本不能线性分离的点变得可以分离。
神经网络处理的数据通常是高维的(比如 DeepSeek V3 的 token 维度是 7168 维)。在这么高的维度里,直觉上很难想象,但数学结构是一样的:每一层都在对高维空间做变换,层层变换之后,把复杂的数据关系"展开"成可以线性处理的形式。
这个视角有一个著名的比喻:把一团纠缠在一起的毛线变成整齐摆放的线团。 深度网络通过层层变换,把高维数据的内在结构"理清楚",最后在顶层用一个简单的线性分类器做决策。
前面讲的函数,结构是固定的。但神经网络的函数是参数化的,也就是说,函数的"形状"由一组参数决定,而这些参数是可以调整的。
$$f_\theta(x) = \theta_1 x^2 + \theta_2 x + \theta_3$$
这里 $\theta = (\theta_1, \theta_2, \theta_3)$ 就是参数。不同的 $\theta$ 对应不同形状的函数。
神经网络的每一层都有这样的参数(权重矩阵 $W$ 和偏置 $b$),整个网络的所有参数合在一起,就是那几千亿个数字。
训练一个神经网络,本质上是在解一个优化问题:
$$\theta^* = \arg\min_\theta \mathcal{L}(\theta)$$
在所有可能的参数组合里,找到那组让损失函数 $\mathcal{L}(\theta)$ 最小的参数 $\theta^*$。
这个优化过程就是梯度下降——我们在第17篇会详细讲。现在的关键是理解:学习 = 调整函数的参数,让函数的输出更接近我们想要的答案。
训练完成后,我们得到了一个参数固定的函数 $f_{\theta^*}$。这个函数在训练数据上表现很好,但我们真正关心的是它在没见过的新数据上的表现——这叫做泛化能力。
泛化的本质是:我们希望神经网络学到的不只是"记住训练数据的答案",而是学到数据背后的规律,能够对新的输入做出合理的预测。
DeepSeek V3 在几乎整个互联网的数据上训练,目的就是让它的函数能够近似"人类语言的规律"——在各种各样的新输入上,都能给出有意义的输出。
这一部分稍微往数学深处走一点,因为它是理解梯度下降的前提。
直觉上,连续函数就是"图像不断、不跳跃"的函数。你可以用铅笔一笔画出来,中间不需要抬笔。
正式定义:当输入变化很小时,输出也只变化很小。
大多数激活函数都是连续的。但 ReLU 在 $x = 0$ 处有一个"折点"——虽然是连续的,但不光滑。
可微函数比连续函数要求更高:不仅要连续,还要"光滑",也就是在每个点都有切线。
$$f'(x) = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}$$
这个极限存在,函数就在 $x$ 点可微。
为什么可微性这么重要?因为梯度下降需要计算函数的梯度(导数的推广),而梯度只在可微点才存在。
ReLU 在 $x = 0$ 处不可微(左右导数不相等)。在实际工程里,这个问题用"次梯度"来解决——规定 $x = 0$ 时梯度为 0 或 0.5,反正训练时几乎不会精确落在这个点上。
更光滑的函数(高阶可微)往往更好优化。这也是 DeepSeek V3 用 SiLU 激活函数而不是 ReLU 的原因之一——SiLU 是光滑的,没有 ReLU 那个硬折点,梯度更平滑,训练更稳定。
$$\text{SiLU}(x) = x \cdot \text{Sigmoid}(x) = \frac{x}{1 + e^{-x}}$$
这个函数处处可微,曲线光滑,在大模型训练里表现比 ReLU 更好。
让我们用一个具体的、端到端的例子,把前面讲的所有概念串起来。
输入:一段文字,比如"这部电影太好看了"
输出:一个概率,比如 0.95(95% 是正面情感)
第一步:文字 → 向量(嵌入层)
文字不能直接输入神经网络,需要先转成数字。嵌入层就是一个查表函数:
$$f_{\text{embed}}: \text{词} \rightarrow \mathbb{R}^{512}$$
每个词映射到一个 512 维的向量,这个映射关系是训练出来的。
第二步:向量序列 → 上下文向量(Transformer 层)
这一步的函数接受所有词的向量,通过注意力机制让它们互相"交流",输出包含上下文信息的新向量:
$$f_{\text{attention}}: \mathbb{R}^{n \times 512} \rightarrow \mathbb{R}^{n \times 512}$$
第三步:上下文向量 → 单个向量(池化)
把序列压缩成一个向量(比如取平均):
$$f_{\text{pool}}: \mathbb{R}^{n \times 512} \rightarrow \mathbb{R}^{512}$$
第四步:向量 → 概率(分类层)
最后一层线性变换 + Sigmoid:
$$f_{\text{classify}}: \mathbb{R}^{512} \rightarrow \mathbb{R}$$
完整网络:
$$\text{情感}(x) = f_{\text{classify}}(f_{\text{pool}}(f_{\text{attention}}(f_{\text{embed}}(x))))$$
看!这就是一个四层函数的复合。每一层都是一个函数,层层传递,最终完成任务。这就是神经网络的本质。
有了函数的视角,我们来简单看一下 DeepSeek V3 的整体结构。
DeepSeek V3 的每个 Transformer 块,本质上是这样的函数复合:
$$h' = h + \text{Attention}(h) \quad \text{(注意力层 + 残差连接)}$$ $$h'' = h' + \text{FFN}(h') \quad \text{(前馈网络层 + 残差连接)}$$
其中: - $h$ 是输入的 token 向量序列(形状:序列长度 × 7168) - Attention 是注意力函数($\mathbb{R}^{n \times 7168} \rightarrow \mathbb{R}^{n \times 7168}$) - FFN 是前馈网络函数(每个位置独立,$\mathbb{R}^{7168} \rightarrow \mathbb{R}^{7168}$) - "$+$" 是残差连接,把输入直接加到输出上
这两个函数交替叠加 61 次,就是 DeepSeek V3 的主体。
特别值得注意的是那个"$+$",这就是残差连接(Residual Connection),它的设计思想是:让每一层学"改变量"而不是"新值"。 数学上就是 $h' = h + f(h)$,$f(h)$ 学的是对 $h$ 的修正量。这个小技巧让训练几百层的深度网络变成可能,否则梯度在深层网络里会消失得无影无踪。
最后说一个有趣的视角:生成模型做的事,某种程度上是在"反转"一个函数。
语言模型训练时,是把文字映射到概率(正向函数);推理时,是根据概率生成文字(反向过程)。
但这个"反转"不是严格的数学逆函数,因为概率到文字的映射不是唯一的(同一个概率分布可以采样出很多不同的词)。这就是为什么语言模型每次生成的内容不完全一样——它在做的是带随机性的采样,而不是确定性的逆映射。
温度参数(temperature)就是控制这个随机性的旋钮: - 温度 = 0:完全确定,每次选概率最高的词(argmax) - 温度 = 1:按概率分布采样 - 温度 > 1:把概率分布"压平",增加随机性,输出更多样
这又回到了函数的视角:温度参数改变的是生成时采样函数的形态,而不是模型本身的函数。
这篇文章我们用"函数"这个视角,重新审视了神经网络的本质。
核心结论是几个层层递进的想法:
第一,函数是输入输出的对应规则,神经网络就是一个参数化的复杂函数。输入 token,输出概率分布,这一点没什么神秘的。
第二,神经网络是多个函数的复合。每一层都是一个变换函数,层层嵌套,构成深层结构。这种层次化的特征提取,是深度学习强大表达能力的来源。
第三,全用线性函数行不通——无论叠多少层都等价于单层线性变换。激活函数引入非线性,是神经网络能拟合复杂规律的关键。
第四,训练的本质是在参数空间里找最优参数,让函数的输出尽量接近正确答案。这是一个优化问题,梯度下降是解法。
第五,函数的连续性和可微性是梯度下降的前提。这也解释了为什么大模型偏爱光滑的激活函数(SiLU、GELU),而不是有硬折点的 ReLU。
下一篇预告:
第4篇,我们讲导数。
知道了函数,下一步自然是:怎么知道参数该往哪个方向调?这需要导数。导数衡量的是"函数在某点的变化率",而梯度是导数在多维空间里的推广。理解了导数,才能真正明白梯度下降在做什么。
我们下篇见。
函数是神经网络的语言,导数是训练神经网络的工具。语言学完了,工具来了。
还没有评论,来抢沙发吧!
博客管理员
40 篇文章
还没有评论,来抢沙发吧!