点积, 属于向量运算里极为基础、极为常用的运算当中的一个, 它将两个长度是一样的向量, 合成为一个标量, 能够表示一组数值的加权求和, 还能够反映两个向量之间的方向关系。
中, 点积, 既能借由列表以及循环予以实现, 又借助NumPy所提供的np.dot抑或@运算符达成。
一、什么是点积
1、点积的基本定义
在实数向量空间里, 点积, 其也被称作标量积, 它属于一种具体呈现形式的标准内积。
设两个 n 维向量为:
它们的点积定义为:
也可以写成求和形式:
可以这样概括点积的计算过程: 把两个向量对应位置那儿的元素相乘, 接着把所有乘得的积加起来, 最终得出一个标量。
因此, 点积要求两个向量包含相同数量的元素 。
2、点积与逐元素乘法
设:
逐元素乘法得到的是一个向量:
点积还需要将这些乘积相加:
因此,逐元素乘法的结果仍然是向量,而点积的结果是标量。
3、点积的手工计算示例
设两个三维向量为:
先计算对应位置元素的乘积:
再将三个乘积相加:
因此:
点积结果 −3 是一个标量,不再具有三个分量。
二、使用 基本语法计算点积
1、使用循环计算
先用 列表表示两个向量:
a = [2, -1, 3]b = [4, 5, -2]
点积的数学计算过程是:
对应的 实现为:
a = [2, -1, 3]b = [4, 5, -2]
# 点积要求两个向量的长度相同iflen(a) != len(b):raise ValueError("两个向量的长度必须相同")
dot_product = 0
# 将对应位置的元素相乘,再累加到 dot_productfor i inrange(len(a)): dot_product += a[i] * b[i]
print(dot_product)
输出结果:
-3
2、使用 zip 和 sum
zip 可以将两个序列中相同位置的元素组合起来:
a = [2, -1, 3]b = [4, 5, -2]
iflen(a) != len(b):raise ValueError("两个向量的长度必须相同")
dot_product = sum(x * y for x, y inzip(a, b))print(dot_product)
输出结果:
-3
其中,zip(a, b) 依次生成:
(2, 4)(-1, 5)(3, -2)
生成式:
x * y for x, y in zip(a, b)
依次得到:
8-5-6
最后由 sum 求和:
8 + (-5) + (-6) = -3
必须留意, zip会于较短的序列终结之际停下。所以, 在开展点积计算之前, 要核查两个向量的长度是不是一样。
三、使用 NumPy 计算点积
在常用数值计算库范围里, NumPy 占据一席之地。针对于向量以及矩阵运算, NumPy 往往展现出比手动循环更为简洁的特性, 并且它在处理大规模数据方面也具备更强的适配性。
1、使用 np.dot
仍然采用前面所提及的那两个向量, 它们的点积已然被计算得出结果是−3 , 运用 NumPy 能够将其写成:
import numpy as np
a = np.array([2, -1, 3])b = np.array([4, 5, -2])
result = np.dot(a, b)
print(result) # −3
对于两个, 属于一维数组的, np.dot(a, b), 它所表示的是, 标准的, 向量点积。
2、使用 @ 运算符
NumPy 也支持使用 @ 计算点积:
import numpy as np
a = np.array([2, -1, 3])b = np.array([4, 5, -2])
result = a @ b
print(result) # −3
当 a 和 b 都是一维数组时:
np.dot(a, b)
与:
a @ b
得到相同的结果。

# 的处理意思愈发趋向于线性代数里的乘法标记, 所以于关联向量以及矩阵的程序代码当中常常被运用。
3、查看结果的形状
import numpy as np
a = np.array([2, -1, 3])b = np.array([4, 5, -2])
result = a @ b
print(a.shape)print(b.shape)
print(result)print(np.shape(result))
输出结果:
(3,)(3,)-3
其中, a的形状是(3,), 这意味着a是一个含有3个元素的一维数组, 而b的形状同样是(3,), 点积的结是标量, 所以其形状为。
四、点积的几何意义
1、点积与向量夹角
点积, 它所表示的并非仅仅是对应元素乘积之和, 它还能够反映出两个向量之间的方向关系。
对于两个非零向量 a 和 b,设它们之间的夹角为 θ,则:
其中:
‖a‖ 表示向量 a 的长度;
‖b‖ 表示向量 b 的长度;
θ 表示两个向量之间的夹角。
n 维向量 a 的长度为:
由点积公式可以得到夹角余弦:
这个公式将点积的代数计算与向量的几何方向联系起来。
2、点积的符号与方向关系
对于两个并非是零向量的向量来说, 其模长‖a‖以及模长‖b‖都是大于0的情况, 所以点积的符号是由cos θ来决定的:
a与b的数量积大于0, 意味着两向量夹角小于90°, 表明这两个向量的方向从整体上来说相对比较一致。
a·b = 0:夹角等于 90°,两个向量相互正交;
a·b < 0:夹角大于 90°,两个向量的方向总体相反。
例如:
计算点积:
因此,a 和 b 相互正交。
对应的 代码为:
import numpy as np
a = np.array([1, 0])b = np.array([0, 1])
result = a @ bprint(result)
输出结果:
0
3、使用点积计算夹角
设:
先计算点积:
再计算两个向量的长度:
代入夹角公式:
因此:
使用 计算:
import numpy as np
a = np.array([1.0, 2.0])b = np.array([3.0, 1.0])
# 计算点积dot_product = a @ b
# 计算两个向量的长度norm_a = np.linalg.norm(a)norm_b = np.linalg.norm(b)
# 根据点积公式计算夹角的余弦值cos_theta = dot_product / (norm_a * norm_b)
# 避免浮点误差使数值略微超出 [-1, 1]cos_theta = np.clip(cos_theta, -1.0, 1.0)
# arccos 返回弧度,再转换成角度theta_radians = np.arccos(cos_theta)theta_degrees = np.degrees(theta_radians)
print("点积:", dot_product)print("夹角余弦:", cos_theta)print("夹角:", theta_degrees)
输出结果:
点积: 5.0夹角余弦: 0.7071067811865475夹角: 45.0
零向量, 其长度是为0的, 它没办法确定方向。所以, 当存在任意其中的一个向量刚好是零向量的时候, 是不能够运用上述公式去计算夹角的。
五、扩展:复数向量的内积
真要细究起实数向量这般情况, 点积它其实就是相应元素乘积逐一相加的结果。然而, 一旦涉及到复数向量这边, 其内积除了常规的那些之外, 还得要对其中一个向量进行取复共轭这样的操作。不同门类的教材, 在记号设定约定这块很可能采用不一样的方式, 而这里参照的是 NumPy np.vdot 的规则, 也就是专门针对第一个向量去取复共轭。
因此,复数向量 a 和 b 的内积写为:
其中,āᵢ 表示 aᵢ 的复共轭。
例如:
对第一个向量取复共轭:
计算内积:
NumPy 可以使用 np. vdot 完成这种运算:
import numpy as np
a = np.array([1 + 1j, 2])b = np.array([3, 1 – 1j])
result = np.vdot(a, b)print(result)
输出结果:
(5-5j)
np.vdot(a, b), 它会先把输入置为展平状态, 之后再针对第一个输入去取复共轭。
对于普通的, 属于实数范畴的, 且为一维的向量而言, np.vdot、np.dot以及@通常会得出相同的结果, 对于属于复数范畴的向量来讲, 它们所具有的含义有可能是不一样的。
六、点积运算在 AI 编程中的应用
1、使用余弦相似度比较向量
以两个向量夹角的余弦值当作相似程度, 余弦相似度()是这样的, 依据前面的点积公式, 它能够被写成:
对点积进行归一化时, 余弦相似度会先用向量长度, 所以主要比较的是向量的方向, 并且不会直接受到向量整体大小的影响。
例如,向量:
与其倍数:

长度并不相同,但方向完全一致,因此余弦相似度为 1。
对于两个非零实数向量,余弦相似度的取值范围为:
其数值可以这样理解:
接近 1:两个向量方向高度一致;
接近 0:两个向量方向接近正交;
接近 −1:两个向量方向基本相反。
当存在两个并非零的向量, 其各个元素全都为并非负数的时候, 它们之间的点积不会比0小, 所以, 余弦相似度处于0到1这个范围之间。
使用 计算:
import numpy as np
a = np.array([1.0, 2.0])b = np.array([3.0, 6.0])
norm_a = np.linalg.norm(a)norm_b = np.linalg.norm(b)
if norm_a == 0 or norm_b == 0:raise ValueError("零向量不能用于计算余弦相似度")
cosine_similarity = (a @ b) / (norm_a * norm_b)cosine_similarity = np.clip(cosine_similarity, -1.0, 1.0)print(cosine_similarity)
输出结果:
1.0
于AI编程里, 余弦相似度常被用以比较文本向量, 以及图像特征, 还有嵌入向量。比如说, 两个文本的向量方向越是接近, 一般来讲就表明它们于模型表示空间当中的语义越是相似。
2、点积与加权求和
点积还可以表示一组数值的加权求和。
设输入向量为:
权重向量为:
加权求和为:
这正是两个向量的点积:
例如,设:
手工计算:
实现为:
import numpy as np
x = np.array([4.0, 2.0, 5.0])w = np.array([0.5, 1.5, -1.0])
weighted_sum = w @ x
print(weighted_sum)
输出结果:
0.0
在线性回归里头, 输出常常是由输入向量跟权重向量去做点积, 之后再加上偏置从而得到。人工神经元也是这样, 全连接层含有多个输出单元, 这里面每个输出单元均可视为一次做点积加上偏置;把这些计算合并起来后, 便形成了矩阵乘法。
七、常见问题
1、两个向量长度不同
设:
a = np.array([1, 2, 3])b = np.array([4, 5])
鉴于两个向量之中, 元素的数量是不一样的, 没办法进行逐项的配对, 所以不能够去计算标准的点积。
点积的形状条件是:
两个向量必须属于同一个 n 维空间。
2、混淆逐元素乘法与点积
在 NumPy 中:
a * b
其体现为逐元素乘法, 它针对对应位置的元素去分别进行相乘操作, 最终得出的结果依旧属于一个数组。
当 a 和 b 都是一维数组时:
a @ b
或:
np.dot(a, b)
表示点积。点积还会对逐元素乘积求和,因此结果是标量。
3、忽略零向量
零向量可以参与点积,并且它与任意向量的点积都等于 0:
但零向量, 其长度是为0, 同时也不存在确定的方向, 所以是不可以使用夹角公式的, 并且也不能使用余弦相似度公式。
需要留意, 尽管零向量跟任意向量进行点积的结果都为0, 然而却不能依据此就认定它们相互间的夹角是90°, 原因在于零向量和其他向量的夹角是没有被定义的。
4、浮点数结果可能存在微小误差
在进行夹角计算或者余弦相似度计算之际, 浮点误差存在着致使理论层面等于1的结果转变成为:
1.0000000000000002
在传入 np. 之前,可以使用:
cos_theta = np.clip(cos_theta, -1.0, 1.0)
将数值限制在合法范围内。
小结
将两个长度相等的向量, 其对应元素相乘之后进行求和, 所得到的结果是一个标量, 此为点积。它能够用来表示加权求和, 也能够反映出向量之间的方向关联。实现点积可以借助循环, 或者np.dot, 又或者@来达成;在进行夹角以及余弦相似度的计算时, 对于零向量以及浮点误差也需要加以留意。




