深度学习基础 - 向量投影
flyfish
给定两个向量 a \mathbf{a} a 和 b \mathbf{b} b,我们想要计算 a \mathbf{a} a 在 b \mathbf{b} b 上的投影。
- 点乘 (Dot Product)
点乘是一个标量,表示两个向量在相同方向上的程度。公式为:
a ⋅ b = ∥ a ∥ ∥ b ∥ cos θ \mathbf{a} \cdot \mathbf{b} = \| \mathbf{a} \| \| \mathbf{b} \| \cos \theta a⋅b=∥a∥∥b∥cosθ
其中:
∥ a ∥ \| \mathbf{a} \| ∥a∥ 是向量 a \mathbf{a} a 的模(长度)。
∥ b ∥ \| \mathbf{b} \| ∥b∥ 是向量 b \mathbf{b} b 的模(长度)。
θ \theta θ 是向量 a \mathbf{a} a 和 b \mathbf{b} b 之间的夹角。
cos θ \cos \theta cosθ 表示 a \mathbf{a} a 在 b \mathbf{b} b 方向上的分量。
- 模 (Magnitude or Length)
向量的模是向量长度的度量:
∥ a ∥ = a 1 2 + a 2 2 + ⋯ + a n 2 \| \mathbf{a} \| = \sqrt{a_1^2 + a_2^2 + \cdots + a_n^2} ∥a∥=a12+a22+⋯+an2
∥ b ∥ = b 1 2 + b 2 2 + ⋯ + b n 2 \| \mathbf{b} \| = \sqrt{b_1^2 + b_2^2 + \cdots + b_n^2} ∥b∥=b12+b22+⋯+bn2
- 向量投影 (Vector Projection) 向量 a \mathbf{a} a 在向量 b \mathbf{b} b 上的投影 proj b a \text{proj}{\mathbf{b}} \mathbf{a} projba 的公式为: proj b a = ( a ⋅ b b ⋅ b ) b \text{proj}{\mathbf{b}} \mathbf{a} = \left( \frac{\mathbf{a} \cdot \mathbf{b}}{\mathbf{b} \cdot \mathbf{b}} \right) \mathbf{b} projba=(b⋅ba⋅b)b
或者,使用单位向量 b ^ \hat{\mathbf{b}} b^: proj b a = ( a ⋅ b ^ ) b ^ \text{proj}_{\mathbf{b}} \mathbf{a} = (\mathbf{a} \cdot \hat{\mathbf{b}}) \hat{\mathbf{b}} projba=(a⋅b^)b^
其中 b ^ = b ∥ b ∥ \hat{\mathbf{b}} = \frac{\mathbf{b}}{\| \mathbf{b} \|} b^=∥b∥b 是 b \mathbf{b} b 的单位向量。
关系分析
点乘和夹角 :通过点乘,可以计算两个向量之间的夹角 θ \theta θ: cos θ = a ⋅ b ∥ a ∥ ∥ b ∥ \cos \theta = \frac{\mathbf{a} \cdot \mathbf{b}}{\| \mathbf{a} \| \| \mathbf{b} \|} cosθ=∥a∥∥b∥a⋅b
投影与点乘 :向量 a \mathbf{a} a 在 b \mathbf{b} b 上的投影直接由点乘计算,因为它衡量了 a \mathbf{a} a 在 b \mathbf{b} b 方向上的分量大小。
向量模 :向量的模提供了向量长度的信息。
示例
假设 a = [ a 1 , a 2 ] \mathbf{a} = [a_1, a_2] a=[a1,a2] 和 b = [ b 1 , b 2 ] \mathbf{b} = [b_1, b_2] b=[b1,b2],计算向量 a \mathbf{a} a 在 b \mathbf{b} b 上的投影:
-
点乘 : a ⋅ b = a 1 b 1 + a 2 b 2 \mathbf{a} \cdot \mathbf{b} = a_1 b_1 + a_2 b_2 a⋅b=a1b1+a2b2
-
b \mathbf{b} b 的模 : ∥ b ∥ = b 1 2 + b 2 2 \| \mathbf{b} \| = \sqrt{b_1^2 + b_2^2} ∥b∥=b12+b22
-
投影 : proj b a = ( a 1 b 1 + a 2 b 2 b 1 2 + b 2 2 ) [ b 1 b 2 ] \text{proj}_{\mathbf{b}} \mathbf{a} = \left( \frac{a_1 b_1 + a_2 b_2}{b_1^2 + b_2^2} \right) \begin{bmatrix} b_1 \\ b_2 \end{bmatrix} projba=(b12+b22a1b1+a2b2)[b1b2]
绘图代码
cpp
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
# 设置字体以支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 定义向量 a 和 b
a = np.array([3, 4])
b = np.array([5, 0])
# 计算向量 b 的单位向量
b_unit = b / np.linalg.norm(b)
# 计算向量 a 在 b 上的投影
a_proj_on_b = np.dot(a, b_unit) * b_unit
# 定义原点 O
O = np.array([0, 0])
# 计算点 A 和点 B 的坐标
A = a
B = b
# 计算投影点 P 的坐标
P = a_proj_on_b
# 绘制向量和点
plt.figure(figsize=(8, 6))
# 绘制向量 a
plt.quiver(O[0], O[1], a[0], a[1], angles='xy', scale_units='xy', scale=1, color='r', label=r'$\mathbf{a}$')
# 绘制向量 b
plt.quiver(O[0], O[1], b[0], b[1], angles='xy', scale_units='xy', scale=1, color='b', label=r'$\mathbf{b}$')
# 绘制向量 a 在 b 上的投影
plt.quiver(O[0], O[1], a_proj_on_b[0], a_proj_on_b[1], angles='xy', scale_units='xy', scale=1, color='g', linestyle='--', label=r'$\text{Projection of }\mathbf{a}\text{ on }\mathbf{b}$')
# 标注关键点和向量
plt.scatter(*A, color='r')
plt.text(A[0], A[1], 'A', fontsize=12, color='r', ha='right')
plt.scatter(*B, color='b')
plt.text(B[0], B[1], 'B', fontsize=12, color='b', ha='right')
plt.scatter(*P, color='g')
plt.text(P[0], P[1], 'P', fontsize=12, color='g', ha='right')
plt.text(O[0], O[1], 'O', fontsize=12, ha='right')
# 计算和标注夹角 θ
cos_theta = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
theta = np.arccos(cos_theta)
# 添加 θ 的弧线
arc = np.linspace(0, theta, 100)
r = 0.5
x_arc = r * np.cos(arc)
y_arc = r * np.sin(arc)
plt.plot(x_arc, y_arc, color='purple')
plt.text(r * np.cos(theta / 2), r * np.sin(theta / 2), r'$\theta$', fontsize=12, color='purple')
# 使用 Line2D 来绘制虚线,从 A 到 P
line = Line2D([A[0], P[0]], [A[1], P[1]], linestyle='--', dashes=(5, 5), linewidth=2, color='k')
ax = plt.gca()
ax.add_line(line)
# 设置图形参数
plt.xlim(-1, 6)
plt.ylim(-1, 5)
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.grid(True, linestyle='--', alpha=0.5)
plt.gca().set_aspect('equal', adjustable='box')
plt.xlabel('x')
plt.ylabel('y')
plt.title('向量 $\mathbf{a}$ 在向量 $\mathbf{b}$ 上的投影')
plt.legend()
# 显示图形
plt.show()
plt.scatter 例子
cpp
import matplotlib.pyplot as plt
# 数据
x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]
sizes = [20, 50, 80, 200, 500]
colors = ['red', 'green', 'blue', 'orange', 'purple']
# 绘制散点图
plt.scatter(x, y, s=sizes, c=colors, alpha=0.6, edgecolors='w', linewidths=2, marker='o')
# 添加标题和标签
plt.title('Example Scatter Plot')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
# 显示图形
plt.show()
参数说明
基本参数
x: 数组或列表,指定 x 坐标。
y: 数组或列表,指定 y 坐标。
可选参数
s: 标量或数组,指定点的大小(默认 20)。
c: 颜色或颜色序列,指定点的颜色。
marker: 字符串,指定标记样式(如 'o'、's')。
cmap: 字符串或 Colormap,用于数值颜色映射。
linewidths: 标量或数组,指定标记边缘宽度。
edgecolors: 颜色或颜色序列,指定边缘颜色(如 'face'、'none')。
alpha: 标量,指定透明度(0 到 1)。
label: 字符串,指定图例标签。