一、线性代数是什么?
线性代数是研究向量 、向量空间 (线性空间)、线性变换 和线性方程组的数学分支。它是机器学习、数据科学、计算机图形学、量子力学等领域的数学基础。
核心思想:用"线性"的方式描述和变换数据。
二、标量、向量、矩阵、张量
1. 标量(Scalar)
单独的数值,0维张量。
python
# Python表示
scalar = 3.14
print(type(scalar)) # <class 'float'>
2. 向量(Vector)
一维数组,有方向的量。
python
import numpy as np
# 行向量(1×n)
row_vector = np.array([1, 2, 3, 4])
print(row_vector.shape) # (4,)
# 列向量(n×1)
col_vector = np.array([[1], [2], [3]])
print(col_vector.shape) # (3, 1)
3. 矩阵(Matrix)
二维数组,由行和列组成。
python
# 2×3 矩阵
matrix = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(matrix.shape) # (2, 3)
4. 张量(Tensor)
多维数组,是向量和矩阵的推广。
python
# 3D张量(2×3×4)
tensor = np.random.rand(2, 3, 4)
print(tensor.shape) # (2, 3, 4)
三、向量运算
1. 向量加减法(对应元素相加减)
python
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b) # [5 7 9]
print(a - b) # [-3 -3 -3]
2. 数乘(标量×向量)
python
k = 3
a = np.array([1, 2, 3])
print(k * a) # [3 6 9]
3. 点积(内积)
几何意义:a⋅b=∣a∣∣b∣cosθa⋅b=∣a∣∣b∣cosθ
用于计算相似度、投影等。
python
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 方法1:np.dot
dot1 = np.dot(a, b)
print(dot1) # 32 = 1*4 + 2*5 + 3*6
# 方法2:a @ b
dot2 = a @ b
print(dot2) # 32
# 手动计算
dot_manual = sum(a[i] * b[i] for i in range(len(a)))
print(dot_manual) # 32
4. 向量长度(模、范数)
python
v = np.array([3, 4])
# L2范数(欧几里得距离)
l2_norm = np.linalg.norm(v)
print(l2_norm) # 5.0 (勾股定理:3²+4²=5²)
# L1范数(曼哈顿距离)
l1_norm = np.linalg.norm(v, ord=1)
print(l1_norm) # 7 (|3|+|4|)
# 手动计算
manual_norm = (3**2 + 4**2) ** 0.5
print(manual_norm) # 5.0
5. 向量夹角(余弦相似度)
python
def cosine_similarity(a, b):
"""计算两个向量的余弦相似度(范围[-1, 1])"""
dot = np.dot(a, b)
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
return dot / (norm_a * norm_b)
a = np.array([1, 0])
b = np.array([0, 1])
print(cosine_similarity(a, b)) # 0.0 (垂直,不相关)
a = np.array([1, 2, 3])
b = np.array([2, 4, 6]) # b = 2a,方向相同
print(cosine_similarity(a, b)) # 1.0 (完全相似)
a = np.array([1, 2, 3])
b = np.array([-1, -2, -3]) # 反向
print(cosine_similarity(a, b)) # -1.0 (完全相反)
6. 叉积(向量积)
仅适用于三维向量,结果是与两个向量都垂直的向量。
python
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
cross = np.cross(a, b)
print(cross) # [-3 6 -3]
# 验证:a·(a×b) = 0, b·(a×b) = 0
print(np.dot(a, cross)) # 0
print(np.dot(b, cross)) # 0
# 叉积的模 = |a||b|sinθ,等于平行四边形面积
四、矩阵运算
1. 矩阵加减法(对应元素相加减)
python
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A + B) # [[ 6 8]
# [10 12]]
print(A - B) # [[-4 -4]
# [-4 -4]]
2. 数乘矩阵
python
A = np.array([[1, 2], [3, 4]])
k = 2
print(k * A) # [[2 4]
# [6 8]]
3. 矩阵乘法
规则:A(m×n) × B(n×p) = C(m×p)
python
A = np.array([[1, 2, 3],
[4, 5, 6]]) # 2×3
B = np.array([[7, 8],
[9, 10],
[11, 12]]) # 3×2
C = np.matmul(A, B) # 或 A @ B
print(C) # [[ 58 64]
# [139 154]]
# C[0,0] = 1*7 + 2*9 + 3*11 = 58
# C[0,1] = 1*8 + 2*10 + 3*12 = 64
4. 矩阵转置
行变列,列变行。
python
A = np.array([[1, 2, 3],
[4, 5, 6]])
print(A.T) # [[1 4]
# [2 5]
# [3 6]]
# 性质:(Aᵀ)ᵀ = A
print((A.T).T == A) # True
5. 矩阵的迹(对角线之和)
python
A = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
trace = np.trace(A)
print(trace) # 15 = 1+5+9
6. 矩阵的秩
几何意义:矩阵列向量张成空间的维数。
python
A = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
rank = np.linalg.matrix_rank(A)
print(rank) # 2 (第三行 = 2×第二行 - 第一行)
# 满秩矩阵
B = np.array([[1, 2],
[3, 4]])
print(np.linalg.matrix_rank(B)) # 2
五、特殊矩阵
1. 单位矩阵(Identity Matrix)
对角线为1,其余为0。
python
I = np.eye(3)
print(I)
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
# 性质:A·I = I·A = A
A = np.array([[1, 2], [3, 4]])
I2 = np.eye(2)
print(A @ I2) # [[1. 2.]
# [3. 4.]]
2. 对角矩阵
非对角线元素为0。
python
D = np.diag([1, 2, 3])
print(D)
# [[1 0 0]
# [0 2 0]
# [0 0 3]]
# 提取对角线
A = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
diag = np.diag(A)
print(diag) # [1 5 9]
3. 对称矩阵
A = Aᵀ
python
A = np.array([[1, 2, 3],
[2, 4, 5],
[3, 5, 6]])
print(np.allclose(A, A.T)) # True
# 协方差矩阵就是对称矩阵
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
cov = np.cov(data)
print(np.allclose(cov, cov.T)) # True
六、行列式
几何意义:矩阵变换对面积/体积的缩放倍数。
python
A = np.array([[2, 0],
[0, 3]])
det = np.linalg.det(A)
print(det) # 6.0 (面积缩放6倍)
# 奇异性:行列式为0,矩阵不可逆
B = np.array([[1, 2],
[2, 4]]) # 第二行 = 2×第一行
print(np.linalg.det(B)) # 0.0
七、逆矩阵
只有方阵且满秩(行列式≠0)才有逆矩阵。
性质:A·A⁻¹ = A⁻¹·A = I
python
A = np.array([[4, 7],
[2, 6]])
det = np.linalg.det(A)
print(det) # 10.0
A_inv = np.linalg.inv(A)
print(A_inv)
# [[ 0.6 -0.7]
# [-0.2 0.4]]
# 验证:A × A⁻¹ = I
print(A @ A_inv) # [[1. 0.]
# [0. 1.]]
# 解线性方程组:Ax = b
b = np.array([1, 2])
x = A_inv @ b
print(x) # [-0.8 0.6]
八、线性方程组
1. 增广矩阵与高斯消元法
python
# 解方程组:
# x + 2y = 5
# 3x + 4y = 6
A = np.array([[1, 2],
[3, 4]])
b = np.array([5, 6])
# 方法1:逆矩阵法
x = np.linalg.inv(A) @ b
print(x) # [-4. 4.5]
# 方法2:solve函数
x = np.linalg.solve(A, b)
print(x) # [-4. 4.5]
# 验证:A·x = b
print(A @ x) # [5. 6.]
2. 最小二乘法(超定方程组)
当方程个数多于未知数时,求近似解。
python
# 数据点:(1, 2), (2, 3), (3, 5)
# 拟合直线 y = ax + b
X = np.array([[1, 1],
[2, 1],
[3, 1]]) # 特征矩阵(添加截距项)
y = np.array([2, 3, 5])
# 最小二乘解:a = (XᵀX)⁻¹Xᵀy
a = np.linalg.inv(X.T @ X) @ X.T @ y
print(a) # [1.5 0.333] 即 y = 1.5x + 0.333
# 使用numpy内置函数
a = np.linalg.lstsq(X, y, rcond=None)[0]
print(a) # [1.5 0.333]
九、特征值与特征向量
核心概念:A·v = λ·v
-
λ:特征值(标量)
-
v:特征向量(方向不变,只被缩放)
python
A = np.array([[4, 2],
[1, 3]])
# 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues) # [5. 2.]
print("特征向量:", eigenvectors) # 列向量
# [[ 0.894 -0.707]
# [ 0.447 0.707]]
# 验证:A·v = λ·v
for i in range(len(eigenvalues)):
v = eigenvectors[:, i]
lambda_ = eigenvalues[i]
print(np.allclose(A @ v, lambda_ * v)) # True
特征分解(对角化)
如果矩阵可对角化:A = Q·Λ·Q⁻¹
python
# 使用上面的矩阵
Q = eigenvectors
Lambda = np.diag(eigenvalues)
Q_inv = np.linalg.inv(Q)
# 重构原矩阵
A_reconstructed = Q @ Lambda @ Q_inv
print(np.allclose(A, A_reconstructed)) # True
十、奇异值分解(SVD)
核心思想 :任意矩阵都可以分解为三个矩阵的乘积。
A = U·Σ·Vᵀ
-
U:左奇异向量(正交矩阵)
-
Σ:对角矩阵(奇异值)
-
V:右奇异向量(正交矩阵)
python
A = np.array([[1, 2, 3],
[4, 5, 6]])
U, S, Vt = np.linalg.svd(A, full_matrices=False)
print("U shape:", U.shape) # (2, 2)
print("S:", S) # [9.51 0.51] (奇异值)
print("Vt shape:", Vt.shape) # (2, 3)
# 重构原矩阵
Sigma = np.diag(S)
A_reconstructed = U @ Sigma @ Vt
print(np.allclose(A, A_reconstructed)) # True
# 应用:降维(PCA的核心)
# 取前k个最大的奇异值,实现数据压缩
k = 1
A_compressed = U[:, :k] @ np.diag(S[:k]) @ Vt[:k, :]
print(A_compressed)
十一、向量空间与基
1. 线性组合与张成
python
# 向量组
v1 = np.array([1, 0])
v2 = np.array([0, 1])
# 线性组合:c1*v1 + c2*v2
c1, c2 = 2, 3
result = c1 * v1 + c2 * v2
print(result) # [2 3]
2. 线性相关与线性无关
python
# 线性相关:存在不全为0的系数使组合为0
v1 = np.array([1, 2])
v2 = np.array([2, 4]) # v2 = 2*v1
# 组成矩阵,看秩
A = np.column_stack([v1, v2])
print(np.linalg.matrix_rank(A)) # 1 (< 2,线性相关)
# 线性无关
v3 = np.array([1, 2])
v4 = np.array([3, 4]) # 不成比例
B = np.column_stack([v3, v4])
print(np.linalg.matrix_rank(B)) # 2 (= 2,线性无关)
3. 标准基
python
# R²的标准基
e1 = np.array([1, 0])
e2 = np.array([0, 1])
# R³的标准基
e1_3d = np.array([1, 0, 0])
e2_3d = np.array([0, 1, 0])
e3_3d = np.array([0, 0, 1])
十二、线性变换
几何意义:保持直线和平行线的变换。
常见变换的矩阵表示
python
import matplotlib.pyplot as plt
# 定义变换矩阵
def apply_transform(v, matrix):
return matrix @ v
# 1. 旋转(逆时针旋转θ角)
theta = np.pi / 4 # 45度
R = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
v = np.array([1, 0])
v_rotated = apply_transform(v, R)
print("旋转后的向量:", v_rotated) # [0.707 0.707]
# 2. 缩放
S = np.array([[2, 0],
[0, 3]])
v_scaled = apply_transform(v, S)
print("缩放后的向量:", v_scaled) # [2 0]
# 3. 投影(投影到x轴)
P = np.array([[1, 0],
[0, 0]])
v = np.array([1, 2])
v_projected = apply_transform(v, P)
print("投影后的向量:", v_projected) # [1 0]
# 4. 剪切
H = np.array([[1, 0.5],
[0, 1]])
v = np.array([1, 1])
v_sheared = apply_transform(v, H)
print("剪切后的向量:", v_sheared) # [1.5 1. ]
十三、实战场合应用
1. PCA降维
python
# 生成三维数据
np.random.seed(42)
data = np.random.randn(100, 3)
data[:, 1] = data[:, 0] * 0.8 + np.random.randn(100) * 0.1
data[:, 2] = data[:, 0] * 0.5 + np.random.randn(100) * 0.2
# 中心化
mean = np.mean(data, axis=0)
centered = data - mean
# 协方差矩阵
cov = centered.T @ centered / (len(data) - 1)
# 特征分解
eigenvalues, eigenvectors = np.linalg.eig(cov)
# 按特征值排序
idx = np.argsort(eigenvalues)[::-1]
eigenvectors = eigenvectors[:, idx]
# 降维到2维
k = 2
proj_matrix = eigenvectors[:, :k]
data_pca = centered @ proj_matrix
print("原始数据形状:", data.shape) # (100, 3)
print("PCA后形状:", data_pca.shape) # (100, 2)
print("保留方差比例:", np.sum(eigenvalues[:k]) / np.sum(eigenvalues))
2. 图像压缩
python
# 模拟图像压缩(使用SVD)
import numpy as np
# 创建简单灰度图(8×8矩阵)
image = np.array([
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 0],
[0, 0, 0, 0, 1, 1, 1, 0],
[0, 0, 0, 0, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0]
])
# SVD分解
U, S, Vt = np.linalg.svd(image)
# 保留前k个奇异值进行压缩
def compress_image(img, k):
U, S, Vt = np.linalg.svd(img)
return U[:, :k] @ np.diag(S[:k]) @ Vt[:k, :]
k_values = [1, 2, 4, 8]
for k in k_values:
compressed = compress_image(image, k)
print(f"k={k}, 压缩率={k*8*2/(8*8):.1%}")
3. 推荐系统(协同过滤)
python
# 用户-物品评分矩阵
ratings = np.array([
[5, 3, 0, 1],
[4, 0, 0, 1],
[1, 1, 0, 5],
[1, 0, 0, 4],
[0, 1, 5, 4],
])
# SVD分解
U, S, Vt = np.linalg.svd(ratings, full_matrices=False)
# 降维到2维
k = 2
U_k = U[:, :k]
S_k = np.diag(S[:k])
Vt_k = Vt[:k, :]
# 重构评分(填充缺失值)
ratings_pred = U_k @ S_k @ Vt_k
print(ratings_pred)
十四、知识点速查表
| 知识点 | 公式/定义 | 计算代码 |
|---|---|---|
| 向量点积 | a·b = Σaᵢbᵢ | np.dot(a, b) |
| 向量叉积 | a×b = 垂直向量 | np.cross(a, b) |
| L2范数 | |v|₂ = √(Σvᵢ²) | np.linalg.norm(v) |
| 矩阵乘法 | (AB)ᵢⱼ = ΣAᵢₖBₖⱼ | A @ B |
| 转置 | (Aᵀ)ᵢⱼ = Aⱼᵢ | A.T |
| 逆矩阵 | A·A⁻¹ = I | np.linalg.inv(A) |
| 行列式 | det(A) | np.linalg.det(A) |
| 秩 | rank(A) | np.linalg.matrix_rank(A) |
| 特征值 | A·v = λ·v | np.linalg.eig(A) |
| SVD | A = U·Σ·Vᵀ | np.linalg.svd(A) |
| 解方程组 | Ax = b | np.linalg.solve(A, b) |