第三十一 向量(Vector)
向量(Vector)是线性代数的核心概念,也是物理学和工程学中描述方向和大小的基本工具。在计算机科学中,向量是机器学习、计算机图形学、物理模拟等领域的基础数据结构。
一、向量的定义
1.1 什么是向量
n 维向量:n 个有次序的数 $a_1, a_2, a_3, \ldots, a_n$ 所组成的数组称为 n 维向量。这 n 个数称为向量的 n 个分量,第 i 个分量 $a_i$ 为向量的第 i 个分量。
分量全为实数的向量称为实向量,分量中含有复数则称为复向量。
向量通常用粗体字母或带箭头的字母表示:
$$\vec{a} = (a_1, a_2, \ldots, a_n)$$
1.2 特殊向量
| 向量类型 | 定义 | 表示 |
|---|---|---|
| 零向量 | 所有元素都为零 | $\vec{0} = (0, 0, \ldots, 0)$ |
| 单位向量 | 长度为 1 的向量 | $|\vec{a}| = 1$ |
| 负向量 | 元素为对应元素取负数 | $-\vec{a} = (-a_1, -a_2, \ldots, -a_n)$ |
| 标准基向量 | 只有一个分量为 1,其余为 0 | $\vec{e}_i$ |
二、向量的基本运算
2.1 向量的加法
两个同维向量相加,对应分量相加:
$$\vec{a} + \vec{b} = (a_1 + b_1, a_2 + b_2, \ldots, a_n + b_n)$$
2.2 向量的数乘
向量与标量相乘,每个分量都乘以该标量:
$$k\vec{a} = (ka_1, ka_2, \ldots, ka_n)$$
2.3 运算律
| 运算律 | 公式 |
|---|---|
| 加法交换律 | $\vec{u} + \vec{v} = \vec{v} + \vec{u}$ |
| 加法结合律 | $(\vec{u} + \vec{v}) + \vec{w} = \vec{u} + (\vec{v} + \vec{w})$ |
| 数乘结合律 | $k(l\vec{u}) = (kl)\vec{u}$ |
| 数乘分配律(对向量) | $k(\vec{u} + \vec{v}) = k\vec{u} + k\vec{v}$ |
| 数乘分配律(对标量) | $(k + l)\vec{u} = k\vec{u} + l\vec{u}$ |
| 零向量性质 | $k\vec{u} = \vec{0} \Leftrightarrow k = 0 \text{ 或 } \vec{u} = \vec{0}$ |
fn vector_add(a: &[f64], b: &[f64]) -> Vec<f64> {
a.iter().zip(b.iter()).map(|(x, y)| x + y).collect()
}
fn vector_scale(a: &[f64], k: f64) -> Vec<f64> {
a.iter().map(|x| x * k).collect()
}
fn main() {
let a = vec![1.0, 2.0, 3.0];
let b = vec![4.0, 5.0, 6.0];
println!("a + b = {:?}", vector_add(&a, &b)); // [5, 7, 9]
println!("2a = {:?}", vector_scale(&a, 2.0)); // [2, 4, 6]
}
三、向量的内积(点积)
3.1 定义
两个 n 维向量的内积(点积)定义为:
$$\vec{a} \cdot \vec{b} = a_1b_1 + a_2b_2 + \cdots + a_nb_n = \sum_{i=1}^{n} a_ib_i$$
3.2 几何意义
$$\vec{a} \cdot \vec{b} = |\vec{a}| |\vec{b}| \cos\theta$$
其中 $\theta$ 是两个向量之间的夹角。
3.3 内积的性质
| 性质 | 公式 |
|---|---|
| 非负性 | $\vec{a} \cdot \vec{a} \ge 0$,且等于 0 当且仅当 $\vec{a} = \vec{0}$ |
| 对称性 | $\vec{a} \cdot \vec{b} = \vec{b} \cdot \vec{a}$ |
| 线性性 | $\vec{a} \cdot (\vec{b} + \vec{c}) = \vec{a} \cdot \vec{b} + \vec{a} \cdot \vec{c}$ |
| 数乘性 | $(k\vec{a}) \cdot \vec{b} = k(\vec{a} \cdot \vec{b})$ |
3.4 求向量夹角
$$\cos\theta = \frac{\vec{a} \cdot \vec{b}}{|\vec{a}| |\vec{b}|}$$
$$\theta = \arccos\left(\frac{\vec{a} \cdot \vec{b}}{|\vec{a}| |\vec{b}|}\right)$$
fn dot_product(a: &[f64], b: &[f64]) -> f64 {
a.iter().zip(b.iter()).map(|(x, y)| x * y).sum()
}
fn magnitude(a: &[f64]) -> f64 {
a.iter().map(|x| x * x).sum::<f64>().sqrt()
}
fn angle_between(a: &[f64], b: &[f64]) -> f64 {
let dot = dot_product(a, b);
let mag_a = magnitude(a);
let mag_b = magnitude(b);
(dot / (mag_a * mag_b)).acos()
}
fn main() {
let a = vec![1.0, 0.0];
let b = vec![0.0, 1.0];
println!("点积: {}", dot_product(&a, &b)); // 0
println!("夹角: {:.2} 弧度 = {:.2}°", angle_between(&a, &b), angle_between(&a, &b).to_degrees());
// 1.57 弧度 = 90°
}
四、向量的叉积
4.1 定义
两个三维向量的叉积定义为:
$$\vec{a} \times \vec{b} = \begin{vmatrix} \vec{i} & \vec{j} & \vec{k} \ a_1 & a_2 & a_3 \ b_1 & b_2 & b_3 \end{vmatrix}$$
$$= (a_2b_3 - a_3b_2, a_3b_1 - a_1b_3, a_1b_2 - a_2b_1)$$
4.2 几何意义
$$|\vec{a} \times \vec{b}| = |\vec{a}| |\vec{b}| \sin\theta$$
叉积的结果是一个向量,其方向垂直于 $\vec{a}$ 和 $\vec{b}$ 所在的平面(右手定则),大小等于以 $\vec{a}$ 和 $\vec{b}$ 为邻边的平行四边形的面积。
fn cross_product(a: &[f64; 3], b: &[f64; 3]) -> [f64; 3] {
[
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0],
]
}
fn main() {
let a = [1.0, 0.0, 0.0];
let b = [0.0, 1.0, 0.0];
let c = cross_product(&a, &b);
println!("a × b = {:?}", c); // [0, 0, 1]
}
五、向量的长度(模)
5.1 定义
向量 $\vec{a}$ 的长度(模或范数)定义为:
$$|\vec{a}| = \sqrt{\vec{a} \cdot \vec{a}} = \sqrt{a_1^2 + a_2^2 + \cdots + a_n^2}$$
5.2 范数的类型
| 范数类型 | 公式 | 说明 |
|---|---|---|
| L1 范数(曼哈顿范数) | $|\vec{a}|_1 = \sum | a_i |
| L2 范数(欧几里得范数) | $|\vec{a}|_2 = \sqrt{\sum a_i^2}$ | 最常用的范数 |
| L∞ 范数(无穷范数) | $|\vec{a}|_\infty = \max | a_i |
fn l1_norm(a: &[f64]) -> f64 {
a.iter().map(|x| x.abs()).sum()
}
fn l2_norm(a: &[f64]) -> f64 {
a.iter().map(|x| x * x).sum::<f64>().sqrt()
}
fn l_inf_norm(a: &[f64]) -> f64 {
a.iter().map(|x| x.abs()).fold(0.0, f64::max)
}
fn main() {
let a = vec![3.0, -4.0];
println!("L1 范数: {}", l1_norm(&a)); // 7
println!("L2 范数: {}", l2_norm(&a)); // 5
println!("L∞ 范数: {}", l_inf_norm(&a)); // 4
}
六、余弦相似度
余弦相似度(Cosine Similarity)衡量两个向量在方向上的相似程度,而不关心它们的大小(长度)。它的值只取决于向量之间的夹角。
$$\cos(\theta) = \frac{\vec{a} \cdot \vec{b}}{|\vec{a}| \cdot |\vec{b}|}$$
| 余弦相似度 | 含义 |
|---|---|
| 1 | 方向完全相同 |
| 0 | 正交(垂直) |
| -1 | 方向完全相反 |
fn cosine_similarity(a: &[f64], b: &[f64]) -> f64 {
let dot = dot_product(a, b);
let mag_a = magnitude(a);
let mag_b = magnitude(b);
dot / (mag_a * mag_b)
}
fn main() {
let doc1 = vec![1.0, 2.0, 1.0, 0.0]; // 文档1的词频向量
let doc2 = vec![1.0, 2.0, 1.0, 0.0]; // 文档2(与文档1相同)
let doc3 = vec![0.0, 0.0, 0.0, 1.0]; // 文档3(完全不同)
println!("doc1 与 doc2 相似度: {:.4}", cosine_similarity(&doc1, &doc2)); // 1.0000
println!("doc1 与 doc3 相似度: {:.4}", cosine_similarity(&doc1, &doc3)); // 0.0000
}
应用: 余弦相似度在文本检索、推荐系统、图像识别等领域广泛应用,用于衡量两个对象的相似程度。
七、线性组合与线性相关性
7.1 线性组合
给定向量组 $\vec{a}_1, \vec{a}_2, \ldots, \vec{a}_m$,对于任何一组实数 $k_1, k_2, \ldots, k_m$,表达式:
$$k_1\vec{a}_1 + k_2\vec{a}_2 + \cdots + k_m\vec{a}_m$$
称为向量组的线性组合。
- 零向量是任意向量的线性组合(取所有系数为 0)
- 向量组中的任一向量都可以表示为该向量组的线性组合
7.2 线性相关与线性无关
线性相关:如果存在不全为零的数 $k_1, k_2, \ldots, k_m$,使得:
$$k_1\vec{a}_1 + k_2\vec{a}_2 + \cdots + k_m\vec{a}_m = \vec{0}$$
则称向量组线性相关。
线性无关:只有当 $k_1 = k_2 = \cdots = k_m = 0$ 时上式才成立,则称向量组线性无关。
判定方法:
- 两个非零向量线性相关 $\Leftrightarrow$ 它们的分量对应成比例
- 向量组中含有零向量,则该向量组线性相关
- 向量组中有两个向量成比例,则该向量组线性相关
7.3 极大线性无关组
极大线性无关组是向量组中满足以下条件的子集:
- 该子集中的向量线性无关
- 向量组中任意其他向量都可以由该子集线性表示
- 添加任何其他向量都会使该子集变为线性相关
性质:
- 同一个向量组的不同极大线性无关组所含向量个数相同
- 这个个数称为向量组的秩
- 向量组与其极大线性无关组等价
八、正交与标准正交向量组
8.1 正交向量
若两个非零向量 $\vec{\alpha}$ 和 $\vec{\beta}$ 的内积为零,即 $(\vec{\alpha}, \vec{\beta}) = 0$,则称它们正交。
性质:
- 正交向量组是线性无关的
- 正交向量组中不含零向量
8.2 标准正交向量组
一组向量,其中每个向量都是单位向量(长度为 1),且两两正交(内积为 0),称为标准正交向量组(或单位正交向量组)。
8.3 施密特正交化
施密特正交化方法可以将一组线性无关的向量转化为一组正交向量:
$$\vec{\beta}_1 = \vec{\alpha}_1$$
$$\vec{\beta}_2 = \vec{\alpha}_2 - \frac{(\vec{\alpha}_2, \vec{\beta}_1)}{(\vec{\beta}_1, \vec{\beta}_1)}\vec{\beta}_1$$
$$\vec{\beta}_3 = \vec{\alpha}_3 - \frac{(\vec{\alpha}_3, \vec{\beta}_1)}{(\vec{\beta}_1, \vec{\beta}_1)}\vec{\beta}_1 - \frac{(\vec{\alpha}_3, \vec{\beta}_2)}{(\vec{\beta}_2, \vec{\beta}_2)}\vec{\beta}_2$$
一般地: $$ \vec{\beta}_k = \vec{\alpha}k - \sum{j=1}^{k-1} \frac{(\vec{\alpha}_k, \vec{\beta}_j)}{(\vec{\beta}_j, \vec{\beta}_j)}\vec{\beta}_j $$
fn gram_schmidt(vectors: &[Vec<f64>]) -> Vec<Vec<f64>> {
let mut result = Vec::new();
for v in vectors {
let mut u = v.clone();
for ortho in &result {
let proj = dot_product(v, ortho) / dot_product(ortho, ortho);
u = u.iter().zip(ortho.iter()).map(|(a, b)| a - proj * b).collect();
}
result.push(u);
}
result
}
fn main() {
let vectors = vec![
vec![1.0, 1.0, 0.0],
vec![1.0, 0.0, 1.0],
vec![0.0, 1.0, 1.0],
];
let orthogonal = gram_schmidt(&vectors);
println!("正交化结果:");
for v in &orthogonal {
println!(" {:?}", v);
}
}
九、向量与矩阵的关系
矩阵可以对向量进行线性变换,包括拉升、压缩、旋转、剪切、平移等操作。
9.1 旋转变换
use nalgebra::{Rotation2, Vector2};
fn main() {
let v = Vector2::new(1.0, 0.0);
let angle = std::f64::consts::FRAC_PI_4; // 45°
let rotation = Rotation2::new(angle);
let rotated = rotation * v;
println!("原向量: {:?}", v);
println!("旋转 45° 后: {:?}", rotated);
// (0.7071, 0.7071)
}
9.2 缩放变换
fn scale_vector(v: &[f64], sx: f64, sy: f64) -> Vec<f64> {
vec![v[0] * sx, v[1] * sy]
}
fn main() {
let v = vec![1.0, 1.0];
let scaled = scale_vector(&v, 2.0, 0.5);
println!("缩放后: {:?}", scaled); // [2.0, 0.5]
}
十、向量在 Rust 中的应用
10.1 使用 nalgebra
use nalgebra as na;
use na::{Vector3, Point3};
fn main() {
let a = Vector3::new(1.0, 2.0, 3.0);
let b = Vector3::new(4.0, 5.0, 6.0);
// 向量加法
let c = a + b;
println!("a + b = {:?}", c);
// 向量数乘
let d = a * 2.0;
println!("2a = {:?}", d);
// 点积
let dot = a.dot(&b);
println!("a · b = {}", dot); // 32.0
// 叉积
let cross = a.cross(&b);
println!("a × b = {:?}", cross); // (-3, 6, -3)
// 范数
let norm = a.norm();
println!("|a| = {}", norm); // 3.7417
// 归一化
let unit = a.normalize();
println!("单位向量 = {:?}", unit);
// 距离
let dist = a.metric_distance(&b);
println!("距离 = {}", dist);
// 点 (Point) 与向量 (Vector) 的区别
let p = Point3::new(1.0, 2.0, 3.0);
let q = Point3::new(4.0, 5.0, 6.0);
let vec = q - p; // 结果是 Vector3
println!("两点间的向量 = {:?}", vec);
}
十一、总结
| 概念 | 要点 |
|---|---|
| 向量定义 | n 个有次序的数组成的数组 |
| 向量加法 | 对应分量相加 |
| 向量数乘 | 每个分量乘以标量 |
| 点积 | $ \vec{a} \cdot \vec{b} = \sum a_ib_i = |\vec{a}| |\vec{b}| \cos\theta$ |
| 叉积 | 仅定义于三维,结果垂直于原向量所在平面 |
| 向量长度 | $|\vec{a}| = \sqrt{\sum a_i^2}$ |
| 余弦相似度 | $ \cos\theta = \frac{\vec{a} \cdot \vec{b}}{|\vec{a}||\vec{b}|}$ |
| 线性相关 | 存在不全为零的系数使线性组合为零向量 |
| 正交 | 内积为零,正交向量组线性无关 |
| 施密特正交化 | 将线性无关向量组转化为正交向量组 |
向量是连接代数与几何的桥梁,也是现代计算机科学的基石。从物理中的力和速度,到机器学习中的特征向量,向量的概念无处不在。
练习建议:
- 实现向量的各种运算(加法、数乘、点积、叉积)
- 用余弦相似度实现简单的文档相似度计算
- 实现施密特正交化算法