点积
点积把两个向量变成一个数,回答一个简单的问题:这两支箭头有多同向?正数表示大致同向,零表示垂直,负数表示相反。障碍物在前还是在后,目标在不在视野里,速度有多少真正朝着目标,一个力做了多少功,甚至一句话和一张图像配不配,用的都是这一个运算。
1为什么机器人需要它
机器人每时每刻都在回答一类很小的问题:
- 前方检测到一个障碍物,它在我的前面还是后面?
- 那个人在不在我的相机视野里?
- 我现在的速度,有多少是真正朝着目标的?
- 机械臂推着一个箱子,我的力里有多少在做功,有多少只是白白顶着墙?
- 这句指令和这张图像不像?(CLIP 这类模型正是这样把语言和图像配对的,见 Part V。)
这些问题看上去毫不相干,答案却都来自同一个运算:点积 (dot product)。它还有一个隐藏身份:1.3 节里矩阵乘向量的"行视角",每一个分量就是一次点积。这一节把它的两种写法、两种读法,以及机器人最常用的几个场景,一次讲清楚。
2直觉:两支箭头有多"一致"
取两支箭头 \(\mathbf a\) 和 \(\mathbf b\),夹角为 \(\theta\)。把 \(\mathbf b\) 垂直地"投"到 \(\mathbf a\) 所在的直线上,得到一段影子,它的带符号长度是 \(|\mathbf b|\cos\theta\)。再乘上 \(\mathbf a\) 自己的长度,就是点积:
影子和 \(\mathbf a\) 同向,结果为正;影子反向,结果为负;\(\mathbf b\) 垂直于 \(\mathbf a\) 时,影子缩成一个点,结果为 0。
最具体的例子是推车。小车只能沿导轨走,你推它的力 \(\mathbf F\) 却常常是斜的。真正推动小车的只有沿导轨的那一份,垂直于导轨的那一份只是顶着导轨。物理里"力做的功"正是 \(W = \mathbf F\cdot\mathbf s\),\(\mathbf s\) 是小车的位移。拖动力的箭头,看看什么时候做正功、零功、负功。
- 用一个不小的力(\(|\mathbf F| \ge 2\) N)推车,但让它做的功几乎为 0。力应该朝哪?
- 让这个力做负功(\(W < -2\) J),也就是在给小车刹车。
点积 = 一个向量中沿另一个向量方向的那一部分,乘上另一个向量的长度。符号告诉你方向关系:正(夹角小于 90°)、零(垂直)、负(夹角大于 90°)。它不关心垂直于那个方向的部分。
3动手玩:点积实验室
拖动琥珀色 a 和紫色 b 的箭头尖。紫色虚线从 b 的尖端垂直落到 a 所在的直线上,落点与原点之间的粗线就是 b 的影子:为正时绿色,为负时红色。淡绿、淡红的底色标出 b 落在哪一侧时点积为正、为负。右边用两个公式各算一遍同一个数,看看它们是否永远一致。
- 让 \(\mathbf a\cdot\mathbf b = 0\),而且两个向量都不是零向量。此时影子是什么样?
- 两个向量的长度不变,让点积尽可能小(最负)。这时夹角是多少?
- 让 \(\mathbf a\cdot\mathbf b = |\mathbf a|^2\),但 \(\mathbf b \ne \mathbf a\)。提示:影子要和 \(\mathbf a\) 一样长。
- 打开"等值线",保持 a 不动,把 b 沿那条线拖出至少 1.5 的距离:点积一动不动。为什么?
点积只看 b 在 a 方向上的分量(影子)。沿着垂直于 a 的方向移动 b,影子的长度完全不变,所以点积也不变。于是 \(\{\mathbf x : \mathbf a\cdot\mathbf x = c\}\) 是一条垂直于 \(\mathbf a\) 的直线(三维里是垂直于 \(\mathbf a\) 的平面)。"平面方程 \(\mathbf n\cdot\mathbf x = d\)"就是这个事实:\(\mathbf n\) 是法向量。另外两个极端也值得记住:垂直时点积为 0;反向(\(\theta = 180°\))时点积取到最小值 \(-|\mathbf a||\mathbf b|\)。
4第二个视角:两个公式为什么是同一个数
实验室右边有两个公式。代数公式 \(a_1b_1 + a_2b_2\) 要用到坐标,换一套坐标轴,每个分量都变了。几何公式 \(|\mathbf a||\mathbf b|\cos\theta\) 只用到长度和夹角,而把整幅图转个角度,长度和夹角都不会变。两者要想永远相等,分量的乘积就必须"此消彼长",使总和保持不变。
下面把 \(\mathbf a\) 和 \(\mathbf b\) 当作一个刚性的整体一起转动,用三根柱子看这件事。
- 找一个角度,让红柱 \(a_1b_1\) 变成负数,而青柱依然是同一个正数。
- 转到 a 正好躺在 x 轴上(\(a_2 \approx 0\))。这时绿柱消失,点积就只剩 \(a_1b_1\)。
点积是一个不依赖坐标轴朝向的量:它只由两个长度和一个夹角决定。这正是它在机器人里如此好用的原因:不管你用世界坐标系、机器人坐标系还是相机坐标系,只要两个向量在同一个坐标系里写出来,点积都是同一个数(1.10 节会把这一点升级成"正交矩阵保持点积")。
5第三个视角:矩阵乘向量的行视角
1.3 节按列读矩阵乘向量:\(A\mathbf v\) 是 \(A\) 各列的线性组合。同一个乘积还有第二种读法,也是代码里真正在算的那一种:\(A\mathbf v\) 的第 \(i\) 个分量,是 \(A\) 的第 \(i\) 行与 \(\mathbf v\) 的点积。
可以把每一行想成一个"探测器",它有自己的朝向 \(\mathbf r_i\),读出的是 \(\mathbf v\) 在自己方向上有多少。下面左图画出两行 \(\mathbf r_1, \mathbf r_2\) 和 \(\mathbf v\),右图用列视角拼出同一个 \(A\mathbf v\)。两边的结果必须一样。
- 让第一行与 \(\mathbf v\) 垂直。右图里 \(A\mathbf v\) 的 x 分量会变成 0,箭头落到 y 轴上。
- 让 \(A\mathbf v = \mathbf 0\),而 \(\mathbf v \ne \mathbf 0\),两行也都不是零向量。两行之间必须是什么关系?
第二个任务的答案:\(\mathbf v\) 同时垂直于两行,所以两行只能互相平行(在平面里垂直于 \(\mathbf v\) 的方向只有一条线)。这样的 \(\mathbf v\) 被矩阵压成 \(\mathbf 0\),所有这样的 \(\mathbf v\) 组成零空间 (null space),1.6 节会专门讲。行视角还有一个后果:矩阵 \(A^\top A\) 的第 \((i,j)\) 项,是 \(A\) 的第 \(i\) 列与第 \(j\) 列的点积,1.12 和 1.13 节里会反复出现。
6再看数学
提示:把鼠标悬停在公式中带底色的符号上,FIG 2 中对应的元素会被高亮。
定义
两个同维度的向量 \(\mathbf a, \mathbf b\in\R^n\),点积是对应分量乘积之和,也可以写成行向量乘列向量:
例如 \((1,2,3)\cdot(4,-5,6) = 4 - 10 + 18 = 12\)。结果是一个标量,不是向量。
性质
- 对称:\(\mathbf a\cdot\mathbf b = \mathbf b\cdot\mathbf a\)。
- 线性(对每个位置分别线性):\(\mathbf a\cdot(\mathbf b + \mathbf c) = \mathbf a\cdot\mathbf b + \mathbf a\cdot\mathbf c\),\((s\mathbf a)\cdot\mathbf b = s\,(\mathbf a\cdot\mathbf b)\)。
- 与长度的关系:\(\mathbf a\cdot\mathbf a = |\mathbf a|^2\),所以 \(|\mathbf a| = \sqrt{\mathbf a\cdot\mathbf a}\)。
几何形式从哪里来
把差向量 \(\mathbf a-\mathbf b\) 当作三角形的第三条边。几何上,余弦定理说:
代数上,用上面的对称性与线性把同一个量展开:
两式相比,\(|\mathbf a|^2 + |\mathbf b|^2\) 消掉,剩下:
这就是 FIG 3 里"代数 = 几何"的证明。用到了余弦定理,所以它在任意维度都成立:任意两个向量总落在同一个平面里,夹角 \(\theta\) 就是那个平面里的夹角。
夹角、正交与影子长度
"clamp"把括号里的数夹在 \([-1, 1]\) 之内(原因见"常见误区")。例:\(\mathbf a = (3,1)\),\(\mathbf b = (1,2)\),则 \(\mathbf a\cdot\mathbf b = 5\),\(|\mathbf a||\mathbf b| = \sqrt{10}\sqrt{5} = \sqrt{50}\),\(\cos\theta = 5/\sqrt{50} = \tfrac{\sqrt2}{2}\),\(\theta = 45°\)。
当 \(\mathbf u\) 是单位向量时,\(\mathbf u\cdot\mathbf b\) 就是 \(\mathbf b\) 在 \(\mathbf u\) 方向上的带符号长度。把这个长度再乘回 \(\mathbf u\),得到完整的"投影向量" \((\mathbf u\cdot\mathbf b)\,\mathbf u\),那是 1.9 节的主题。
Cauchy–Schwarz 与余弦相似度
因为 \(|\cos\theta|\le 1\),立刻得到
第一个不等式叫 Cauchy–Schwarz 不等式。它回答了"固定长度时点积最大能到多少":当两者同向时取到 \(|\mathbf a||\mathbf b|\)。第二个量是余弦相似度,先把两个向量都除以自己的长度,再做点积:它只比较方向,不受长度影响,是机器学习里比较 embedding 的标准做法。
矩阵写法与旋转不变性
\(\mathbf a^\top\mathbf b\) 是 \(1\times n\) 乘 \(n\times 1\),得到 \(1\times 1\),也就是一个数;反过来 \(\mathbf a\mathbf b^\top\) 是 \(n\times n\) 的矩阵(外积,1.12 节的"一层")。行视角则写成 \((A\mathbf v)_i = \mathbf r_i^\top\mathbf v\)。若 \(R\) 是旋转矩阵,满足 \(R^\top R = I\)(1.10 节),那么 FIG 3 的观察就是一个等式:
7机器人中的它:视野判断与朝向目标的速度
视野判断:目标在不在视野里?
机器人的朝向是单位向量 \(\hat{\mathbf h}\),相机的视野半角是 \(\alpha\)。物体相对机器人的位移是 \(\mathbf d = \mathbf p_{\text{obj}} - \mathbf p_{\text{robot}}\)。物体可见,当且仅当 \(\mathbf d\) 与 \(\hat{\mathbf h}\) 的夹角 \(\varphi\le\alpha\)。因为 \(\cos\) 在 \([0,\pi]\) 上递减,这等价于
右边的 \(\cos\alpha\) 只算一次,每个物体只需要一次点积和一次开方,不需要 \(\operatorname{atan2}\) 或 \(\arccos\)。拖动机器人的朝向(红色箭头尖),再调节视野半角,看看右侧表格里每个物体的"点积 ≥ 阈值"是怎么变的。
- 把视野半角调到 30° 或更小(窄镜头),转动机器人,让至少 3 个物体同时在视野里。
- 让某个物体恰好卡在视野边缘(夹角与 \(\alpha\) 相差不到 1.5°,它的圆环会变成琥珀色)。这时不等式两边几乎相等。
朝向目标的速度:贪心控制器的核心
机器人在原点,目标在 \(\mathbf G\),指向目标的单位向量是 \(\hat{\mathbf g} = \mathbf G/|\mathbf G|\)。速度 \(\mathbf v\) 中朝向目标的那一份,就是逼近速度 \(s = \mathbf v\cdot\hat{\mathbf g}\):每秒大约离目标近多少米。假设速度大小不能超过 \(v_{\max}\),什么方向最好?Cauchy–Schwarz 给出答案:\(s\le|\mathbf v||\hat{\mathbf g}|\le v_{\max}\),当且仅当 \(\mathbf v = v_{\max}\hat{\mathbf g}\) 时取等号。
很多局部规划器的做法与此一脉相承:生成一批候选速度(图中速度圆上的小点),给每个候选打分,选分数最高的。点积 \(\mathbf v\cdot\hat{\mathbf g}\) 就是最基本的"朝向目标"得分。
- 让逼近速度达到上限的 97% 以上(\(s \ge 1.94\) m/s)。v 应该指向哪里?
- 保持几乎全速(\(|\mathbf v| \ge 1.7\)),但让逼近速度几乎为 0(\(|s| < 0.08\))。机器人这时在做什么?
第二个任务的答案:\(\mathbf v\perp\hat{\mathbf g}\),机器人绕着目标转圈,既不靠近也不远离,一直在白费力气。
功率。力与速度的点积 \(P = \mathbf F\cdot\mathbf v\) 是瞬时功率;对关节,\(P = \boldsymbol\tau\cdot\dot{\mathbf q}\),即关节力矩向量与关节速度向量的点积。\(P>0\) 说明电机在向机械臂输出能量,\(P<0\) 说明外力在拖着电机转,能量流回驱动器(再生制动)。能耗估计、电机发热和功率限制都从这个点积出发。
余弦相似度。CLIP 这样的模型把图像和文字都映射成同一空间中的向量(embedding),归一化后,匹配分数就是点积,也就是余弦相似度。机器人用它判断"拿起红色的杯子"这句话和相机画面里哪个区域最匹配。对比学习的细节见 Part V。
8常见误区
点积同时包含长度和夹角。取 \(\mathbf a = (1,0)\),\(\mathbf b = (3,3)\),\(\mathbf c = (1, 0.1)\):\(\mathbf a\cdot\mathbf b = 3\),\(\mathbf a\cdot\mathbf c = 1\),\(\mathbf b\) "得分更高"。但 \(\mathbf b\) 与 \(\mathbf a\) 相差 45°,\(\mathbf c\) 只差约 5.7°。要比较方向,必须先除以长度,用余弦相似度(\(\cos 45° \approx 0.71\),而 \(\cos 5.7° \approx 0.995\))。
数学上 \(\cos\theta\in[-1,1]\),但浮点误差可能让归一化后的点积变成 \(1.0000000000000002\)。例如 NumPy 里 a = np.array([0.4, 0.06, 0.3]),计算 a @ a / (np.linalg.norm(a) * np.linalg.norm(a)),结果就是这个数,np.arccos 对它返回 nan。机器人代码里一个 NaN 会顺着控制链一路传下去。永远写成 np.arccos(np.clip(c, -1.0, 1.0))。
\(\sum a_ib_i\) 只有在标准正交基(轴互相垂直、长度为 1)里写出的坐标上,才等于几何点积。反例:取斜的基 \(\mathbf f_1 = (1,0)\),\(\mathbf f_2 = (1,1)\)。坐标 \((1,1)\) 与 \((1,-1)\) 的"分量乘积和"是 \(1 - 1 = 0\),好像垂直;但真实向量是 \(\mathbf a = \mathbf f_1 + \mathbf f_2 = (2,1)\),\(\mathbf b = \mathbf f_1 - \mathbf f_2 = (0,-1)\),真正的点积是 \(-1 \ne 0\)。同理,不同单位的量不能放在一起点乘:位姿 \((x, y, \theta)\) 里米和弧度混在一起,它的"点积"没有几何意义。
\(\hat{\mathbf h}\cdot\mathbf d>0\) 只说明夹角小于 90°,也就是"在我前方的半个平面里"。真实相机的视野半角通常只有 30° 到 60°,必须和阈值比较:\(\hat{\mathbf h}\cdot\mathbf d\ge|\mathbf d|\cos\alpha\)。把 \(\alpha\) 当成 90° 写代码,会把相机侧面的物体也当成"看得见"。反过来,若 \(\mathbf h\) 没有归一化,阈值那一侧也要乘上 \(|\mathbf h|\)。
9小练习
10延伸阅读
- 3Blue1Brown, Essence of Linear Algebra — 第 9 章(点积与对偶性)
- G. Strang, Introduction to Linear Algebra, Ch. 1.2 — 长度与点积
- J. Ström et al., Immersive Linear Algebra, Ch. 3 — 点积(带交互插图)
- A. Radford et al., Learning Transferable Visual Models From Natural Language Supervision (CLIP), ICML 2021 — 余弦相似度在图文匹配中的应用