定义域与陪域:每个 AI 函数都需要的输入契约
学习定义域和陪域如何规定有效的模型输入与承诺的输出类型,然后诊断形状、范围和未定义运算导致的失败。
第 2 课把函数描述为一条为每个允许输入指定一个输出的规则。“允许”一词的分量比初看起来更重。
如果文本分类器期待词元 ID,就不能安全地接收任意字节块。矩阵乘法不能接受不兼容的形状。对负输入取对数不能产生实数值。规则只是函数契约的一部分;有效输入集合和承诺的输出集合是另外两部分。
学完本课后,你将能够连同定义域和陪域写出函数,区分陪域与实际到达的值,并把常见的 AI 输入失败解释为违反数学契约。
箭头携带类型信息
一个简洁的函数声明如下:
读作“ 从 映射到 ”。
- 是定义域,即允许的输入集合。
- 是陪域,即承诺所有输出都属于其中的集合。
- 规则告诉我们, 的每个元素被分配到 的哪个元素。
记号 表示“ 是 的一个元素”。它让我们可以把契约和计算写在一起:
| 输入 | 有效? | 输出 |
|---|---|---|
| 0.1 | 是 | 0.18 |
| 0.5 | 是 | 0.50 |
| 0.9 | 是 | 0.82 |
| “high” | 否——输入类型错误 | 未计算 |
图中的文本输入 “high” 并不是失败的数值预测。它不是这个数值函数允许的输入,因此不应开始计算。
陪域是承诺,而不是观察到的输出列表
考虑实数上的平方函数:
这里的 表示实数集合。每个实数输入都可以平方,结果也都是实数,所以这个声明有效。
但 从不会为负。函数实际到达的值集合是
这个到达集合称为像或值域。它可以小于声明的陪域。
| 概念 | 对于 、 |
|---|---|
| 定义域 | 所有实数 |
| 陪域 | 所有实数 |
| 像 | 非负实数 |
改变定义域可以修复未定义的规则
表达式
在 时没有定义实数输出。我们可以排除零来声明有效函数:
符号 表示集合差。定义域就是“不含零的实数”。同样,
的实值定义域限制为正输入:
这些不是吹毛求疵的装饰,而是在告诉实现:计算前必须检查什么。
AI 定义域还包括形状和结构
到目前为止,定义域看起来像数字区间。模型输入通常是向量或矩阵,它们的形状也属于契约。
令
记号 表示由三个实坐标组成的有序列表, 表示由两个实坐标组成的有序列表。一个有效输入是
含两个坐标的向量不在声明的定义域内。它的各个元素都可能是实数,但对象的形状错误。
这就是常见张量错误的数学版本:
def project_three_features(x):
if x.shape != (3,):
raise ValueError("expected exactly three features")
return [x[0] + x[1], x[2] - x[1]]
这个检查保护了定义域。函数返回两个数字,与陪域的形状相符。
对于基于词元的模型,完整定义域还可能更加严格。输入可能需要:
- 整数词元 ID,而不是任意实数;
- 位于固定词表范围内的 ID;
- 最大序列长度;
- 相互一致的批次形状与注意力掩码形状;以及
- 该模型所要求的图像、音频或文本编码。
说“模型接受一个张量”会隐藏这些约束。好的数学接口和软件接口会把它们显露出来。
输出承诺会约束下游代码
假设一个分类器声明为
它接受 个实特征,并返回 个介于零和一之间的数字。仅凭这个陪域,不能保证 个数字的和为一。如果预期输出是 个互斥类别上的概率分布,陪域需要额外条件:
这个集合称为概率单纯形。我们稍后会学习它。现在只需注意,更丰富的陪域如何向下游代码传达更强的承诺。
阅读模型函数的检查清单
遇到新的数学映射时,问自己四个问题:
- 哪些对象属于定义域?
- 哪些对象被明确排除或未定义?
- 陪域承诺了什么输出集合?
- 规则是否实际到达整个陪域,还是只到达更小的像?
这些问题能把许多模糊的“形状不匹配”“无效概率”和“未定义损失”错误变成精确的契约违反。下一课将使用集合来更系统地描述数据集合和事件。
检查你的理解
问题 1
对于声明为 q: R → R 的 q(x) = x²,指出定义域、陪域和像。
显示分步解答
声明说明定义域是 ,陪域也是 。任意实数输入都可以计算平方,并返回实数。
由于对每个实数 都有 ,实际到达的值恰好是非负实数:
因此,像是陪域的真子集。
问题 2
为什么 0 不在 r(x) = 1/x 的实值定义域内?
显示分步解答
代入零要求计算
不存在满足 的实数 ,所以这个除法没有实值。正确的声明排除零:
问题 3
一个函数期待 R³ 的元素。如果 [1, 2] 的两个元素都是实数,它有效吗?请解释。
显示分步解答
属于 要求恰好三个有序实坐标。向量 属于 ,而不是 。
单个值的类型正确,但形状不正确。值类型和形状都是定义域契约的一部分。
问题 4
分类器返回 [0.6, 0.6]。每个元素都在 [0, 1] 内。为什么它仍可能违反陪域?
显示分步解答
如果分类器只承诺 ,这个向量满足较弱的契约。但如果它承诺两个互斥类别上的概率分布,数值的和还必须为一。
这里 ,所以该向量不在概率单纯形内。是否违反陪域取决于实际声明了哪一个输出集合。
问题 5
某实现把 log(p) 替换为 log(max(p, 0.000001))。它是否对每个实数 p 计算完全相同的函数?
显示分步解答
不是。对于 ,两个表达式相同;对于更小的正 ,截断实现返回常数 ,而不是 。对于零或负 ,它还会在原始实对数未定义的地方产生有限值。
截断可以是有意的数值保护措施,但它会改变一致区域之外的函数。精确的解释应说明这个约定及其原因。