ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

向量运算详解:从几何直观到Python实战

向量运算详解:从几何直观到Python实战 1. 向量是什么——一个不只是“带箭头的线段”的概念很多人第一次接触向量都是从物理课上的“力”开始的。两个力作用在同一个物体上不光要看大小还要看方向——这正是向量最朴素的来源。到了数学里向量被抽象成既有大小又有方向的量它可以是一条带箭头的线段也可以是一组有序的数组还可以是函数空间里的一个点。学懂了向量你就掌握了线性代数的地基后面无论是矩阵、线性变换、特征值还是机器学习里的高维数据表示全都站在这个基石上。1.1 从几何直观到坐标表示向量的两种面孔向量的第一种面孔是几何的在平面或者空间里画一条带箭头的线段箭头的指向就是方向线段的长度就是大小。这种表示很直观画出来就能看懂尤其在解决物理问题、几何问题的时候特别好用。但几何表示有个短板——不方便计算。你不太可能靠尺子量角度和长度去解决一个复杂的力学问题。于是就有了向量的第二种面孔坐标表示。在二维平面上建立直角坐标系后任何一个向量都可以写成两个数的组合比如 v (3, 4)意思是从原点出发沿 x 轴走 3 个单位再沿 y 轴走 4 个单位。到了三维空间就是三个数到了 n 维空间就是 n 个数。这里有一个初学者很容易忽略的关键点向量的坐标是相对于坐标系而言的。同一个向量换一套坐标系坐标值就会变。所以向量本身是客观存在的几何对象但它的“数字身份”是相对的。理解这一点以后学基变换、特征值分解的时候就不会懵。提示区分“点”和“向量”是很多人的第一个坎。点表示位置它没有方向向量表示移动它有大小和方向。虽然写法上都可以用坐标表示但含义完全不同。你可以把向量理解成“从起点到终点的位移”它描述的是怎么走而不是走到哪里。1.2 特殊向量零向量、单位向量、负向量有几个特殊的向量值得单独拿出来说因为它们在后面的运算中经常扮演重要角色。零向量记作 0 或者 (0, 0, ...)长度为 0方向是任意的。它相当于数字 0 在加法中的身份任何向量加上零向量都等于它自己。在物理里零向量对应的就是“合力为零”的状态。单位向量长度为 1 的向量。它的作用是表示“纯方向”。因为长度固定为 1它本身不含大小信息所以可以用来指示方向。把一个向量除以它的长度得到的就是与它同方向的单位向量这个过程叫归一化。在三维图形学里法线向量经常要归一化后再参与光照计算就是这个原因。负向量和原向量大小相同、方向相反记作 -v。代数上就是把每个分量取负几何上就是以起点为中心转 180 度。向量减法 a - b 本质上就是 a 加上 b 的负向量把减法“翻译”成加法之后再套三角形法则就好理解多了。1.3 向量的模长度量向量的大小的唯一标准向量的模长也叫范数记作 |v| 或者 ||v||。在二维坐标里v (x, y) 的模长是 √(x² y²)这其实就是勾股定理。到了三维v (x, y, z) 的模长是 √(x² y² z²)。到了 n 维空间就是所有分量平方和再开根号。模长满足三条基本性质这三条性质既是定义也是检验标准非负性|v| ≥ 0且只有零向量的模长是 0。齐次性|kv| |k| · |v|数乘的模长等于模长的数乘。k 是负数时方向反转但长度按 |k| 倍缩放。三角不等式|a b| ≤ |a| |b|。这个不等式名字听着抽象其实特别直觉——两点之间直线最短绕过中间点走折线路程只会更长。模长的计算在工程里也极其常用。比如机器学习里的 L2 正则化本质上就是在惩罚模型参数的向量模长。图形学里算两个物体之间的距离也是先做向量减法再求模长。2. 向量的基本运算线性组合的核心向量的运算规则和数的四则运算有很多相通之处但又有区别。弄清楚哪些运算能用、哪些不能用、为什么是掌握向量的关键。本节先从最基础的三种运算讲起加法、减法、数乘。2.1 向量加法与减法三角形法则为什么成立向量加法有两种等价的几何描述。第一种是三角形法则把 b 的起点平移到 a 的终点那么从 a 的起点指向 b 的终点的新向量就是 a b。你可以想象成走路先沿 a 的方向走一段再沿 b 的方向走一段最终的结果就是直接从头指到尾。第二种是平行四边形法则把 a 和 b 从同一个起点出发以它们为邻边作一个平行四边形从共同起点指向对角顶点的对角线就是 a b。这两种法则得到的向量是一样的只是构造方式不同——一道“加法”、一道“拼接”而已。在坐标下加法就是对位相加a (x₁, y₁)b (x₂, y₂)则 a b (x₁ x₂, y₁ y₂)。减法是加法的逆运算a - b 的几何意义就是“b 的终点指向 a 的终点”的向量坐标下对位相减a - b (x₁ - x₂, y₁ - y₂)。注意向量减法得到的结果方向是从 b 的终点指向 a 的终点而不是反过来。初学者在这里很容易把方向搞反。你只需要记住“被减数指向”a - b 就是“从 b 指向 a”。这些运算满足交换律 a b b a 和结合律 (a b) c a (b c)和普通数字加法的规律一样所以在做多个向量的加法时可以随便调整运算顺序。但注意向量之间的乘法没有这么简单下面要讲的数乘是第一个特殊之处。2.2 数乘运算当数字和向量相遇数乘就是一个实数 k 乘以一个向量 v结果是 kv。它做的事是把向量的长度缩放 |k| 倍如果 k 是负数就把方向反转。坐标下k(x, y) (kx, ky)即每个分量都乘以 k。数乘有两条重要的分配律k(a b) ka kb数对向量加减法的分配律(k m)a ka ma数之间的加法对向量的分配律这两条分配律就是线性代数里“线性”二字的来源一个运算既要对“数”保持线性又要对“向量”保持线性。你以后会看到矩阵乘法的定义、线性变换的证明本质上都是在维护这两条分配律。数乘几何上最直观的效果是“伸缩”k 1 放大0 k 1 缩小k 0 变成零向量k 0 则是“先反转、再缩放”。一个高频考点是判断两个向量是否平行如果存在非零实数 k 使得 a kb那么 a 和 b 平行共线。2.3 共线向量与共面向量向量关系的基础判断共线向量也叫平行向量指的是方向相同或相反的一组向量。它们在同一条直线上或者说挪到同一个起点后落在同一直线上。比如 (1, 2) 和 (2, 4) 就是共线的因为 (2, 4) 2(1, 2)。共面向量指的是可以平移到同一个平面内的向量组。在三维空间里任意两个向量一定是共面的因为两条相交直线确定一个平面但三个向量就不一定了。判断三个向量是否共面可以通过混合积来判断也可以用“能否由一个向量线性表出另一个或第三个向量”来理解。这些关系在解析几何里非常实用。判断平面内三个点是否共线判断空间中四个点是否共面本质都是在判断向量之间的线性关系。掌握共线共面的判断逻辑后面的线性相关、线性无关概念就好理解得多——那只是把这些几何关系推广到了高维空间。3. 向量的乘积运算点积与叉积两个完全不同的世界向量之间不能“直接相乘”得出一个向量那么简单。严格来说向量乘法有两种常见的定义各有各的适用场景。一个是点积结果是一个数一个是叉积结果是一个向量。它们的性质差异巨大混淆了会出大问题。3.1 点积内积算出“有多同一方向”点积的定义是两个向量对应分量相乘再把积加起来。二维空间里a (x₁, y₁)b (x₂, y₂)则 a · b x₁x₂ y₁y₂。这个定义在几何上等价于a · b |a||b|cosθ其中 θ 是 a 和 b 之间的夹角。这个等价关系极其重要因为它把代数计算和几何意义连接起来了。点积的几何意义是“一个向量在另一个向量方向上的投影长度的乘积”。你可以想象阳光下两根棍子一根棍子在地上的影子长度乘以另一根棍子的长度就是点积。点积可以用来判断垂直如果 a · b 0 且 a、b 都不是零向量那么 a ⊥ b。这是最常用的垂直判定手段。计算夹角cosθ (a · b) / (|a||b|)。不需要知道角本身三个量一除就行。衡量相似度在文本处理、推荐系统里余弦相似度本质就是两个向量的夹角的余弦值夹角越小越相似。点积满足交换律 a · b b · a满足分配律 a · (b c) a · b a · c但不满足结合律——因为两个向量点积后得到的是一个数数和向量没法再点积。这一点初学者很容易踩坑。3.2 叉积外积算出一个“垂直的新向量”叉积只定义在三维空间以及七维但那个太冷门了它的结果是一个新的向量。设 a (x₁, y₁, z₁)b (x₂, y₂, z₂)则a × b (y₁z₂ - z₁y₂, z₁x₂ - x₁z₂, x₁y₂ - y₁x₂)这个公式看着吓人但其实有规律可循——本质上是把两个三维向量“拼”成一个 3×3 的类矩阵后求行列式。如果你熟悉行列式的展开就能记住这个算法。叉积的几何意义新向量的大小 |a||b|sinθ等于以 a、b 为邻边的平行四边形的面积。新向量的方向垂直于 a 和 b 所在的平面具体指向由右手定则确定右手四指从 a 弯向 b转过较小的夹角大拇指指向的就是 a × b 的方向。叉积最重要的应用包括计算平面法向量、判断多边形顶点是顺时针还是逆时针排布图形学中判断面片的正面背面、计算力对某点的力矩τ r × F、在物理学中用叉积表示角动量等等。注意叉积不满足交换律。a × b - (b × a)方向相反、大小相同。它为“反交换”运算。这一点和点积形成了鲜明对比。3.3 点积与叉积的辨析什么时候用哪个很多初学者在解题时纠结这题到底用点积还是叉积我个人的经验是先看你知道什么、想得到什么。如果你关心的是角度、垂直、投影、相似度那就用点积因为点积的核心是 cosθ提供的是“我朝哪个方向走了多远”的标量信息。如果你关心的是面积、法向量、旋转方向、力矩那就用叉积因为叉积的核心是 sinθ 和“垂直方向”提供的是“旋转平面和大小”的向量信息。举个具体例子已知三角形三个顶点坐标求面积。用向量叉积最方便——算出两条边的向量叉积的模长的一半就是三角形面积。把几何问题化成代数运算公式一套比用海伦公式省事得多。这就是向量运算在解析几何中的威力。4. 向量的线性组合、基与坐标变换当你学会向量的几类基本运算之后可以立刻把它们组合起来用。把若干个向量分别乘上系数再相加这个过程叫线性组合。它能描述的东西比“两个向量相加”要丰富得多。4.1 线性组合一个向量如何由其他向量拼出来设 v₁, v₂, ..., vₘ 是一组向量k₁, k₂, ..., kₘ 是一组实数则k₁v₁ k₂v₂ ... kₘvₘ就是一个线性组合。如果组合出来的结果等于零向量而且系数不全是零那就说明这组向量之间存在“冗余”关系如果可以由这组向量表示出空间中的任意向量那它们就是一组“完备”的表达。线性组合的几何直觉是给你一些箭头你允许把它们拉长、缩短、反向然后把它们首尾相接拼成新箭头。解决的问题是用这些原材料我能拼出多少个不同的新向量这个问题直接导向线性代数里最核心的概念——线性相关与线性无关。如果一组向量里至少有一个可以由其他的线性表示它们就线性相关反过来谁都表示不了谁就线性无关。线性无关的向量组是“最小生成单元”线性相关的向量组说明存在“多余”的信息。4.2 基与坐标为什么二维平面用两个向量就够了在二维平面上如果给你两个不共线的向量 e₁ 和 e₂那么平面上任何一个向量都能唯一地写成 k₁e₁ k₂e₂ 的形式。e₁ 和 e₂ 就构成这个平面的一组基(k₁, k₂) 就是这个向量在这组基下的坐标。最常见的基是标准基e₁ (1, 0)e₂ (0, 1)。在这组基下任何向量 v (x, y) 写作 x·e₁ y·e₂坐标写起来最简单。但要注意你完全可以选另外一组不共线的向量作为基同一个向量在不同基下的坐标是不同的。基里的向量个数决定了空间的“维数”。二维平面需要 2 个线性无关的向量作为基三维空间需要 3 个n 维空间需要 n 个。这个个数就是空间的维度。理解了基和维数你就知道为什么 3D 图形学里一个坐标系需要三个互相垂直的基向量也就理解了矩阵的列秩、行秩这些概念为什么和维度直接挂钩。4.3 坐标变换换个基换个视角同一个向量 v在基 B₁ 下的坐标是 (x₁, y₁)在基 B₂ 下的坐标变成 (x₂, y₂)。这两组坐标之间怎么换算答案是用一个过渡矩阵本质上是把“基与基之间的关系”编码成一个矩阵然后用它去左乘旧坐标。以二维为例如果两组基分别是 e₁, e₂ 和 f₁, f₂并且 f₁ p₁₁e₁ p₂₁e₂f₂ p₁₂e₁ p₂₂e₂那么从 f 坐标到 e 坐标的过渡矩阵就是由这些系数构成的矩阵 P [[p₁₁, p₁₂], [p₂₁, p₂₂]]。旧坐标和新坐标之间的关系是旧坐标 P · 新坐标。这个变换听起来抽象但你在实际项目里天天在用。比如在图形引擎里一个点的世界坐标、相机坐标、裁剪坐标之间的转换本质上就是一连串坐标变换。换基就是换个观察角度去描述同一个对象。提示坐标变换里最容易错的是“矩阵乘的方向”。一定要先搞清楚 P 是从哪个基到哪个基的过渡矩阵再决定谁乘谁。实践中我总会在纸上把“旧基 → 新基”的箭头画出来再写矩阵出错率会大幅下降。4.4 从二维到 n 维向量的抽象之路一旦接受“向量是 n 个数组成的数组”这个观点向量就不仅限于空间里的箭头了。一个音频信号的 44100 个采样点、一张图片的像素灰度值、一条用户的购买记录都可以看成高维空间里的向量。每个“维度”对应一个属性每个样本就是空间中的一个点。这种抽象看起来只是换个说法但它带来一个巨大的好处你用向量的语言来分析数据。比如在机器学习中求两个样本之间的相似度就是计算两个高维向量之间的余弦距离做线性回归本质是在特征向量张成的空间里找一个最接近标签向量的线性组合。这一切都建立在向量运算之上。所以在学向量的运算时不要只盯着二维、三维的几何。等你以后接触 n 维空间坐标相加、数乘、点积、模长这些运算规则依然适用只是没有直观的几何图像了。数学的好处就在这儿规则一旦抽象化适用范围就成倍扩大。5. 向量运算的实用实操从手算到代码光看公式和概念掌握不了向量。我始终觉得动手算一算、写几行代码跑一跑才是真正理解向量的方式。这一节给出一些实际操作层面的内容包括手算步骤示例和 Python 代码实现。5.1 手算示例一道综合题拆开讲来一个完整的例子把前面讲的运算串起来。设 a (1, 2)b (3, 1)c (0, -1)。计算 a 2b - ca 2b - c (1, 2) 2(3, 1) - (0, -1) (1, 2) (6, 2) - (0, -1) (16-0, 221) (7, 5)。计算 a · ba · b 1×3 2×1 5。计算 a 的模长|a| √(1² 2²) √5。计算 a 与 b 的夹角 θcosθ (a · b) / (|a||b|) 5 / (√5 × √10) 5 / √50 1 / √2。于是 θ 45°。三维叉积示例设 a (1, 0, 0)b (0, 1, 0)a × b (0×0 - 0×1, 0×0 - 1×0, 1×1 - 0×0) (0, 0, 1)。这个结果正好是 z 轴方向的单位向量符合右手定则——x 轴弯向 y 轴大拇指指向 z 轴。一目了然。5.2 Python 手写向量运算不依赖库的底层实现学习阶段我建议你先用原生 Python 列表实现一遍向量运算不去调现成的 numpy这样能加深对规则的理解。下面这段代码就是向量运算的核心逻辑import math def add(a, b): return [a[i] b[i] for i in range(len(a))] def subtract(a, b): return [a[i] - b[i] for i in range(len(a))] def scalar_mul(k, v): return [k * x for x in v] def dot(a, b): return sum(a[i] * b[i] for i in range(len(a))) def norm(v): return math.sqrt(sum(x * x for x in v)) def cross_3d(a, b): return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ] a [1, 2] b [3, 1] print(a 2b - c , add(add(a, scalar_mul(2, b)), [0, 1])) print(a·b , dot(a, b)) print(|a| , norm(a))这段代码很短但涵盖了前面讲的所有基础运算。写一遍再跑一遍你就能直观地看到“对位相加”“对位相乘后求和”这些规则到底在做什么。写完原生实现再切到 numpy 去做数值计算你会对 numpy 为什么这么设计有更深的理解。5.3 用 numpy 进行向量运算工程中的标准姿势在实际的数据分析和机器学习项目里没人会手写向量的加减法大家都直接用 numpy。下面是对应的实现代码干净、性能也更好import numpy as np a np.array([1.0, 2.0]) b np.array([3.0, 1.0]) c np.array([0.0, -1.0]) # 加法、数乘、减法 result a 2 * b - c print(a 2b - c , result) # 点积 print(a·b , np.dot(a, b)) # 模长 print(|a| , np.linalg.norm(a)) # 夹角弧度转角度 cos_theta np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) theta_deg np.degrees(np.arccos(np.clip(cos_theta, -1.0, 1.0))) print(θ , theta_deg, degrees) # 三维叉积 a3 np.array([1.0, 0.0, 0.0]) b3 np.array([0.0, 1.0, 0.0]) print(a3 × b3 , np.cross(a3, b3))注意第 13 行的 np.clip。这是一个我踩过不少坑的点浮点数计算时cosθ 可能出现略大于 1 或略小于 -1 的值比如 1.0000000002直接传入 np.arccos 会得到 nan。用 np.clip 把输入限制在 [-1, 1] 区间内就不会出这种问题。工程上这种边界情况非常常见写代码时要特别留意。5.4 一个综合实战判断任意四边形的对角线是否垂直下面用一个实际问题把点积和坐标运算结合起来。给定平面上四个点 A、B、C、D判断四边形按顺序 A→B→C→D→A的两条对角线是否垂直。思路对角线 AC 的向量是 C - A。对角线 BD 的向量是 D - B。当且仅当 AC · BD 0 时两条对角线垂直。import numpy as np A np.array([0.0, 0.0]) B np.array([2.0, 1.0]) C np.array([3.0, 3.0]) D np.array([-1.0, 2.0]) vec_ac C - A vec_bd D - B dot_val np.dot(vec_ac, vec_bd) print(AC , vec_ac, , BD , vec_bd) print(AC·BD , dot_val) if abs(dot_val) 1e-9: print(两条对角线垂直) else: print(两条对角线不垂直)这里用 abs(dot_val) 1e-9 来判断“等于零”是有讲究的。浮点数有精度误差严格等于 0 的情况很少见所以工程上都是判断是否在某个极小阈值附近。这个套路在以后写几何算法时几乎天天用。6. 向量学习常见误区与实战经验排查学向量这门课我发现很多人并不是看不懂公式而是被几个反复出现的误区卡住了。把这些常见的坑提前指出来能帮你省下大量绕弯的时间。6.1 误区一点积结果到底是数还是向量这是最基础也最容易混淆的点。点积 a · b 的结果是一个标量不是向量。它的意义是投影长度的乘积是一个数。而叉积 a × b 的结果才是一个向量。我见过不少刚学线性代数的同学在一个需要求“两个向量是否垂直”的题目里用了叉积然后对着一个向量发呆——其实这里只要算点积然后看结果是否为 0。判断垂直只看点积判断平行和面积才用叉积。6.2 误区二向量乘法满足结合律吗普通数字乘法有结合律(ab)c a(bc)。但向量的运算没有这个“福利”。点积不满足结合律因为 (a · b) · c 这个式子本身就无意义——a · b 是标量标量不能再和 c 做点积。叉积不满足结合律实际上有 a × (b × c) ≠ (a × b) × c 的情况。这个称为“叉积的非结合性”在涉及多个叉积的公式推导时极易出错。正确处理姿势是遇到多个向量的乘积先想清楚各自的运算顺序再套用对应的公式。比如向量三重积 a × (b × c) 有专门的展开公式 a × (b × c) b(a · c) - c(a · b)不要自己去硬拆。6.3 误区三坐标变换时矩阵乘反了坐标变换里方向搞反会导致整个结果错误。我自己的判断技巧是把“过渡矩阵”看成新基在旧基下的坐标组成的矩阵。如果旧坐标 P · 新坐标那么矩阵 P 的每一列就是新基的一个基向量在旧基下的坐标。验证方法取新基的第一个向量 f₁算 P 乘上 (1, 0)看结果是不是 f₁ 在旧基下的坐标。如果吻合方向就对了。这种验证方法听起来笨但极其可靠。我每次写代码前都会先用 2 维手工验证一遍小例子再套到高维场景里。工程中 80% 的向量、矩阵错误都出在坐标系理解不一致上。6.4 学习路径建议从几何直观到代数抽象给零基础朋友一个少走弯路的学习路径。第一阶段建立几何直观。在纸上多画向量亲手验证三角形法则、平行四边形法则感受数乘对向量的拉长、压扁、反转。这个阶段不要急于算坐标先让“箭头在脑中能转起来”。第二阶段掌握代数运算。把几何直观翻译成坐标计算反复手算加、减、数乘、点积、叉积的题目直到不需要回忆公式也能写出结果。这个阶段的目标是让运算成为肌肉记忆。第三阶段接触抽象推广。引入线性组合、基、维数这些概念理解向量从“箭头”到“n 数组”的抽象过程。这个阶段开始你可以尝试用 numpy 编写向量运算代码在代码中加深对抽象概念的理解。第四阶段应用驱动巩固。找几个实际问题来练手比如判断空间几何关系、计算三角形面积、做一个简单的光照计算。把一个具体问题翻译成向量运算再编程解决这个过程会把前面所学串联起来。6.5 我的几点个人体会向量这些运算表面上是数学规则实际上是人类用来描述“方向与大小”最优雅的语言。在工作中很多看似和线性代数无关的问题最后的优化解法都落在向量运算上。第一点不要死记公式要想“这个公式在描述什么”。比如点积公式 a · b |a||b|cosθ它其实在说“两个向量的相似程度”。记住了这一点你自然知道什么时候该用它。第二点多画图多想几何意义。数学公式是抽象的但它的背后通常有一个直观的几何图像。叉积的方向为什么用右手定则就是因为我们生活在三维空间需要一种约定来区分“向上”和“向下”。第三点多用代码验证。向量运算是非常适合用代码验证的数学内容。随便造几个向量手算一遍再跑一遍代码两相对照基本不会有错。这种习惯能让你在更复杂的数学学习中保持踏实感。
返回列表