点积、叉积、外积、张量积:四个易混概念的彻底辨析 📅 发布时间:2026/9/7 18:54:20 👁 浏览次数: 这几个概念我估计每个学线性代数、搞机器学习、做图形学的人都经历过一段混乱期。点积、内积、外积、叉积、张量积名字长得像亲兄弟内涵却差出十万八千里。更坑的是不同教材对“外积”的定义还互相打架有的说外积是叉积有的说外积是向量变矩阵直接把初学者绕晕在概念迷宫里。这篇文章我把这五个概念从头到尾捋一遍不只讲定义还会解释它们各自到底为了解决什么问题、为什么维度会变、在机器学习和图形学里各自长什么样。适合刚学线代的大学生、转行做算法的朋友以及写代码时被numpy里的dot、outer、cross搞到怀疑人生的工程师。照着我这篇文章过一遍这几个概念大概率能彻底分清。1. 概念混乱的根源两个“外积”在打架1.1 教材口径不统一是最大元凶先说一个残酷的现实你搞不清这些概念不全是你的问题教材本身就非常不统一。中文理工科教材里《高等数学》把a×b叫做“向量积”或者“叉积”部分地方也写成“外积”。但在《线性代数》和矩阵论里“外积”指的是两个向量做张量积得到矩阵的运算英文叫outer product。同一本书里“外积”可能同时出现在不同章节指的还是两种完全不同的东西谁学谁不迷糊。内积和点积相对好一点。在实向量空间里内积就是点积点积就是内积两者在有限维欧氏空间里可以画等号。但严格来说内积是更抽象的概念它还包含函数空间里的积分内积比如f, g ∫f(x)g(x)dx这才是内积的完整含义。点积只是内积在坐标形式下的具体表现。至于张量积它其实站在更高的抽象层次上涵盖了外积。外积可以理解为张量积在“两个向量”这个特例下的具体结果。所以正确的关系脉络应该是张量包含外积外积包含矩阵形式点积是内积的坐标表示叉积是一个独立的三维特殊运算跟它们没有直接归属关系。1.2 最容易踩的三个认知坑第一个坑认为叉积就是外积。这是最普遍的误解。中文互联网上大量文章把cross product翻译成外积导致后面学outer product时直接崩溃“怎么来个向量变成一个矩阵了”我建议你直接把“叉积”和“外积”这两个词在脑海里分开。叉积(cross product)只用在三维空间输出还是向量外积(outer product)是一般张量运算输出是高阶结构。第二个坑认为张量积是把两个数字“乘起来”。初学者一听到张量积下意识觉得就是把两个张量逐元素乘一遍。实际上张量积的维度变化是相乘关系但排列方式完全不同。一维向量和二维矩阵做张量积结果会变成三维张量而不是简单逐元素相乘后的二维矩阵。第三个坑维度上想当然。点积要求两个向量维度相同结果是一个标量叉积只存在于三维结果是个向量外积没有维度限制m维向量乘以n维向量的转置结果是一个m×n矩阵张量积可对任意阶张量操作。很多人写代码时默认“两个向量的积就是逐元素相乘”结果用错了API程序跑出来形状完全不对。2. 内积与点积从投影到机器学习相似度计算2.1 几何视角点积就是“投影的长度”点积的几何定义是a·b |a||b|cosθ这个公式初中平面向量就学过。它真正表达的意思是把向量b投影到向量a的方向上投影长度乘以a的长度。你可以这样直观理解一个人拉着小车走一段路用的力是向量F走的位移是向量s那么做功W F·s。真正做功的只有力在位移方向上的分量也就是F·cosθ再乘以位移的大小s这就是点积。θ等于90度时力方向和位移方向垂直做的功为零这就是“正交”最直观的物理意义。这就能解释为什么零向量和任意向量的点积是零零向量长度为0投影结果自然是0。也就能解释为什么判断两个向量是否垂直可以简单看a·b是否为0。2.2 坐标视角分量相乘求和才是本质几何公式好看但无法计算。坐标定义为a (a1, a2, ..., an)b (b1, b2, ..., bn)则a·b a1b1 a2b2 ... anbn。这里有个关键认知当向量维度超过3维时“夹角”这个概念其实已经没有直观几何意义了但坐标公式依然成立。所以我们说坐标定义才是点积的本质几何公式只是三维空间里的直观解释。举个例子a (1, 2, 3)b (4, -5, 6)点积 1×4 2×(-5) 3×6 4 - 10 18 12。就这么简单。numpy里可以这么算import numpy as np a np.array([1, 2, 3]) b np.array([4, -5, 6]) print(np.dot(a, b)) # 12 print(a b) # 12Python 3.5 的约定写法 print(np.sum(a * b)) # 12逐元素相乘再求和注意第二种写法a b在Python 3.5以后被规定为矩阵乘法/点积的运算符写多了会非常顺手。第三种写法是“先逐元素相乘再求和”本质上也是点积很多初学者会在这三种写法之间犯迷糊其实结果完全一样。2.3 点积在机器学习里的实际出镜率点积在机器学习里可以说是最频繁出现的运算之一没有之一。比如余弦相似度公式cosθ a·b / (|a||b|)。两个向量的点积除以模长乘积就是它们夹角的余弦值。在推荐系统、NLP语义相似度计算中这个值用来度量两个向量在方向上是否一致值越接近1越相似。典型的例子是Word2Vec训练出的词向量对“猫”和“狗”两个词向量计算余弦相似度得分往往明显高于“猫”和“汽车”。再比如Transformer的注意力机制核心公式是Attention(Q, K, V) softmax(QK^T / √d_k)V。其中的QK^T本质就是对所有查询向量和键向量两两做点积得到一个相似度矩阵然后通过softmax归一化成权重。这个矩阵里每个值就是一对向量的点积数值越大代表这两个位置越相关。这个过程中点积之所以被选为相似度度量是因为它同时考虑了向量的大小和方向而且计算极度高效GPU对矩阵乘法的优化已经到了令人发指的程度点积公式正好转化为矩阵乘法一箭双雕。3. 叉积三维空间里“制造垂直向量”的专属工具3.1 几何意义输出向量的模等于平行四边形面积叉积的写法是c a×b结果c是一个向量。它满足三个条件c垂直于a和b所在平面c的方向由右手定则决定|c| |a||b|sinθ第三个条件很有意思两个向量张成的平行四边形面积正好等于|a||b|sinθ。所以在很多数学证明里叉积的模长直接用来计算三角形或者平行四边形的面积。两个共线向量叉积为零因为它们张不成任何面积。坐标计算方式如下a (a1, a2, a3)b (b1, b2, b3)c1 a2b3 - a3b2 c2 a3b1 - a1b3 c3 a1b2 - a2b1这个公式容易记错我自己常用行列式记忆法写一个3×3行列式第一行是单位向量i, j, k第二行是a的三个分量第三行是b的三个分量然后按第一行展开。展开的时候要注意符号i对应正号j对应负号k对应正号。numpy里一行代码搞定import numpy as np a np.array([1, 2, 3]) b np.array([4, 5, 6]) c np.cross(a, b) print(c) # [-3 6 -3]注意np.cross只对二维和三维数组有意义。二维时它返回一个标量代表两个向量围成的有向面积三维时返回三维向量。3.2 为什么叉积很难推广到高维空间这个问题很多惜字如金的教材根本不提导致学生默认“任何维度都能求叉积”。实际上不是这样。叉积的核心要求是给定n维空间里两个向量找到一个向量同时垂直于它们两个。三维空间里这个垂直方向是唯一的差一个正负号所以可以定义一个唯一的叉积结果。但四维空间里垂直于两个向量的方向有无穷多个形成一个二维平面你没法唯一确定“那个垂直向量”所以叉积无法自然推广到四维。高等数学里有一种推广叫外代数wedge product能处理任意维度的反对称乘积但它的结果不再是向量而是更高阶的东西比如两个向量的wedge product是一个2-向量本质上是一个有向平面元素。这和我们在三维空间里遇到的叉积不是一回事。很多人把外代数和张量积搞混是因为外代数也是张量积商掉对称部分得到的名字里都有“外”这个字但定位完全不同。3.3 图形学和物理里的高频使用场景叉积在三维图形学和物理里基本是天花板级别的存在我现在做3D渲染相关的项目几乎每天都会用到。第一个场景是求平面法向量。一个三角形有三个顶点求这三点的法向量方向时取两个边向量叉积一下除以模长得到单位法向量。法向量用于光照计算、遮挡剔除、碰撞检测到处都是。具体做法取顶点P0、P1、P2边向量u P1 - P0v P2 - P0法向量n u×v。如果三角形顶点顺序不一致法向量方向会翻转所以3D建模软件里统一规定逆时针方向为正面这是3D渲染里最经典的细节之一。第二个场景是物理中的力矩。力矩\tau r×Fr是力臂向量F是力向量力矩的方向就是转轴方向大小等于力在垂直于力臂方向上的分量乘以力臂长度。角动量L r×p位置向量与动量向量的叉积也是同一个套路。第三个场景是判断点在三角形内还是三角形外。这个方法叫“叉积符号法”对三角形的每条边计算边向量与边起点到测试点的向量的叉积z分量在二维平面里就是二维叉积如果三个符号相同点在三角形内部。这种方法在光栅化渲染器中非常常见判定逻辑简单且数值稳定。4. 外积把两个向量“张”成一个矩阵4.1 线性代数里的外积张量积的向量特例既然说完叉积现在正式说外积。在矩阵论和机器学习语境里外积(outer product)的定义是给定两个列向量u ∈ R^m和v ∈ R^n则u和v的外积是一个m×n的矩阵[u1v1, u1v2, ...; u2v1, u2v2, ...; ...]写成张量形式就是用\u ⊗ v。在Python里import numpy as np u np.array([1, 2, 3]) # 3维 v np.array([4, 5]) # 2维 M np.outer(u, v) print(M) # [[ 4 5] # [ 8 10] # [12 15]]这里得到的M是3×2矩阵。注意跟前面叉积完全不同叉积要求两个向量维度必须完全一致外积则没有任何维度限制这也是最容易踩坑的地方。从张量积的角度看向量是一阶张量两个一阶张量的张量积是二阶张量也就是矩阵。所以外积就是张量积在“两个向量”上的具体实现。这里“外”字的含义是从整个张量空间的视角来看——它生成了一个更高阶的结构而不是像内积那样折叠降维。内积和外积正好是对偶的操作一个把两个张量缩并成低阶一个把两个张量扩展成高阶。4.2 秩一矩阵与外积的关系如果一个矩阵是两个非零向量的外积uv^T这个矩阵有很重要的性质它的秩是1。因为每一行都是v^T的某个倍数所有行都线性相关所以矩阵的列空间只有一维。反过来秩为1的矩阵一定能写成两个向量的外积。这个性质在数据科学里的应用非常关键。奇异值分解(SVD)的每一项就相当于一个奇异值乘以两个向量的外积A Σ σ_i u_i v_i^T其中σ_i是奇异值u_i和v_i分别是左右奇异向量。通过保留最大若干奇异值对应的外积项就能实现矩阵的低秩近似。举一个我常给朋友讲的例子一张灰度图像本质是一个矩阵。如果对它做SVD保留前50个奇异值重建出来的图像依然能保持人眼可辨认的主体轮廓文件存储所需的数值量却从原来几万个像素值降成了100个奇异值加100个向量分量。这个过程的每个低秩项的本质就是外积。很多人以为低秩近似是高深的东西说穿了就是用多个“秩一外积矩阵”叠加逼近原矩阵。外积还有一个常见的工程应用是可分离卷积。二维卷积核如果恰好是u和v的外积那么原卷积操作可以拆成先沿行做一维卷积再沿列做一维卷积计算量从O(n²)降到O(2n)速度快一个数量级。Gaussian模糊里常用的二维高斯滤波器就是典型的可分离卷积核正好对应两个一维高斯向量的外积。4.3 外积与叉积在代码里的辨识要点写代码的时候辨识这两个操作非常简单np.cross 是叉积要求输入是二维或三维的向量输出维度与输入一致。np.outer 是外积不限制维度输出维度是两个输入维度的笛卡尔积。比如两个三维向量做np.outer输出是3×3矩阵做np.cross输出是三维向量。两个函数名长得像行为完全不同。5. 张量积所有乘积概念的“总老板”5.1 张量积的抽象定义与维度公式张量积是一个抽象操作。给定两个线性空间V和W张量积V⊗W是一个新的线性空间它的维度是dim(V) × dim(W)。V中的向量v和W中的向量w可以构造出v⊗w属于V⊗W。这个定义初看很抽象但核心就一句话张量积的运算方式是“叉乘式组合”所有基向量的两两组合都会成为新空间的一组基。如果V有基{e1, e2}W有基{f1, f2}那么V⊗W有基{e1⊗f1, e1⊗f2, e2⊗f1, e2⊗f2}共4个基向量也就是2×24维。这个维度乘积公式是辨识张量积的关键。从这个角度看两个向量的外积u⊗v就是把两个向量各自的分量两两配对组合成矩阵。所以外积是张量积的最简单实例。更高阶的张量积比如一个向量和一个矩阵做张量积结果是一个三阶张量。我经常用这个理解来避免写代码时的形状错误两个数组做张量积结果的形状就是把两个输入的形状拼接起来。5.2 Kronecker积矩阵的张量积实现在数值计算里两个矩阵的张量积就是Kronecker积记作A⊗B。假设A是m×n矩阵B是p×q矩阵那么A⊗B是mp×nq的块矩阵用块的形式写出来就是A的每个元素乘上整个B矩阵A⊗B [[a11B, a12B, ..., a1nB], [a21B, a22B, ..., a2nB], ..., [am1B, am2B, ..., amnB]]numpy里这样求import numpy as np A np.array([[1, 2], [3, 4]]) B np.array([[0, 1], [1, 0]]) C np.kron(A, B) print(C.shape) # (4, 4)Kronecker积有几个很重要的性质。第一(A⊗B)^T A^T⊗B^T第二如果A和B分别是可逆矩阵那么(A⊗B)^{-1} A^{-1}⊗B^{-1}第三特征值具有乘法结构如果λ是A的特征值μ是B的特征值那么λμ是A⊗B的特征值。这些性质在控制论、信号处理、量子计算中大量使用。在量子计算中多个量子比特的态空间就是单个量子比特态空间的张量积。一个量子比特的状态是二维复向量两个量子比特的态空间就是2×24维三个就是8维。这也是为什么量子计算模拟器内存消耗是指数级增长的原因——张量积的维度乘积公式决定了状态的维度随量子比特数指数爆炸。5.3 张量积与点积、外积的关系总览我一直给学生用一句话总结这几个概念的关系点积是张量积之后“缩并”外积是张量积本身叉积是三维空间里“张量积再反对称化”的结果。点积其实可以理解为先把两个一阶张量做张量积得到一个二阶张量矩阵再把指标两两配对求和也就是做缩并最后得到标量。这个过程在物理学里叫“指标收缩”。所以点积是张量运算的一个特例只是它同时包括了张量积和缩并两步。外积则是只做张量积、不做缩并所以维度升高。叉积在三维空间里是在张量积的基础上做了反对称投影抛掉对角部分和多余分量只保留与两向量垂直的对抗部分。这解释了为什么叉积输出维度跟输入一致因为反对称条件和垂直条件刚好把自由度压到了3。如果你做深度学习模型开发PyTorch和TensorFlow里的张量概念直接对应这里的张量积。两个不同形状的Tensor进行矩阵乘法、广播逐元素乘法本质上都是张量运算的一部分。而广播机制里两个向量的batch矩阵乘法经常就是手动实现的外积操作。6. 一张总表彻底分清四个概念6.1 多维度对比速查表用表格把这四个概念的关键差异整理清楚建议你存下来随时翻阅概念别名输入输出维度变化几何意义常见应用点积/内积dot product, inner product两个n维向量标量n维×n维 - 1维投影长度的乘积余弦相似度、注意力机制叉积vector product, cross product两个三维向量三维向量3维×3维 - 3维垂直于平面的向量模长为平行四边形面积法向量、力矩、光栅化判定外积outer productm维向量、n维向量m×n矩阵m维×n维 - m×n维矩阵生成秩一矩阵SVD低秩近似、可分离卷积张量积tensor product, Kronecker积任意阶张量高阶张量dim1×dim2组合所有基向量量子态组合、神经网络批量运算注意一个容易误导的地方这里的“内积”在实向量空间中等于点积但在泛函分析中还包括函数内积那个地方就没有“点积”的说法了需要额外学习。6.2 按你的领域选择合适的掌握深度不同方向的人这四个概念的优先级完全不同。做机器学习的同学必须熟练点积和张量积这两个是神经网络前向传播的最基础运算Transformer里的QK^T、多模态模型里的各种张量操作都离不开它们。外积在矩阵分解里常用SVD、PCA都有它推荐系统里面用户物品矩阵的低秩分解就是外积的叠加。叉积在你的日常工作中如果不用三维坐标基本碰不到知道存在就行。做图形学、游戏开发、机器人方向的同学叉积优先级最高法向量、旋转、物理碰撞每天都用外积用的场景少一些但掌握它才能理解渲染管线里的各种变换矩阵。张量积在图形学里偶尔会用在切线空间的构造上不深入接触也许用不到。做理论数学、物理、量子计算方向的同学张量积是主线必须从线性算子角度理解透外积只是张量积的一个简单例子内积是张量积加缩并叉积要么扔掉换成外代数要么当成三维特例反复用。6.3 我的建议先从几何直观切入再进入坐标计算最后统一到张量我的学习顺序建议是这样的先在二维和三维里把点积的投影含义和叉积的垂直含义吃透这两个几何直观能帮助你理解大部分问题。然后学坐标定义搞清楚怎么算。接着打开numpy用代码把每个概念演算一遍感受维度变化。最后再学张量积用它把点积、外积统一起来。很多人一上来就直接背张量积的抽象定义然后云里雾里。其实张量积最自然的理解路径就是“从外积到张量积”。你把两个向量做外积得到一个矩阵那一刻就已经在不知不觉中对张量积有了直观印象。只是那时候你不知道这个矩阵就是张量积在特定情况下的矩阵表表示。你现在把这个印象正式化概念就自动接上了。7. 实操中容易翻车的几个细节7.1 numpy里dot、matmul、outer、cross的选择方法写代码时最常遇到的困惑就是numpy里各种乘积函数怎么选。我平时判断的顺序是先看想要的结果维度。如果输入是两个一维数组想要输出标量用np.dot或者a b想要输出矩阵用np.outer想要输出一个与输入同维的向量且输入是二维或三维那大概率是np.cross。如果输入是二维及以上的矩阵情况比较复杂。np.dot在二维数组上是矩阵乘法但在一维数组上是内积。np.matmul和运算符则严格按照矩阵乘法规则来多维数组会做batch处理。PyTorch里的torch.matmul行为也更加规范推荐深度学习代码都用或者torch.matmul尽量避免在Tensor上用np.dot因为形状广播规则不完全一样很容易出现维度对不上的报错。我见过很多同事在numpy里想把两个向量做外积结果用了np.dot报错形状不对还有人在三维向量上想求法向量用了np.outer得到一个3×3矩阵。这些问题的共同根源是没有先想清楚想要的输出维度直接凭函数名猜功能。建议你写代码前先停顿两秒默念一遍输出的形状再选函数。7.2 越高阶越容易忽视的维度爆炸问题张量积一个非常实际的坑是维度爆炸。两个三维张量的张量积是六维张量如果三个高维向量做张量积结果维度是各维度乘积内存消耗以指数级增长。在做量子计算模拟时这个现象最明显。每增加一个量子比特态空间的维度翻倍。30个量子比特的态向量就需要2^30个复数存储大约8 GB内存直接打爆普通电脑。做深度学习大模型时也是一样不同特征张量如果直接做外积维度立刻爆炸所以现在模型里多用低秩分解、注意力降维等手段限制维度增长。这也是为什么很多结构复杂的计算图在写代码时要非常谨慎地设计张量形状一个多余的张量积操作可能就让显存翻倍。如果你遇到“内存不够”的报错检查一下代码里是不是无意中使用了np.outer或expand_dims后广播导致的张量积这些操作看起来很简单实际存储量巨大。合理的替代方案是先做降维再考虑是否真的需要张量积。7.3 符号命名的语言陷阱最后一个提醒不同编程语言和库的命名习惯差异很大很容易造成混淆。numpy的outer就是外积cross是叉积dot是内积kron是张量积。PyTorch里torch.outer是外积torch.cross是叉积torch.matmul是矩阵乘法/批量点积。TensorFlow里tf.tensordot可以做指定维度的收缩相当于更广义的点积tf.einsum用爱因斯坦求和约定统一描述所有乘积可以一句话同时实现点积、外积、矩阵乘法这也是我个人最推荐的表示方式。用einsum来写这些概念非常清晰点积是ij-所有元素求和外积是ij-...矩阵乘法是ij,jk-ik。如果你在某天需要同时处理多个张量的复杂缩并einsum可以帮你从维度地狱里解放出来。不过如果只是日常使用记住dot、outer、cross这三个就足够覆盖绝大多数场景了。我自己的习惯是在代码里用a b表示向量点积或矩阵乘法用np.outer表示外积用np.cross表示叉积用np.kron表示张量积的矩阵形式。保持命名和操作一一对应时间长了肌肉记忆自然会帮助你避开这些坑。