数学是机器学习的第一语言。掌握数学基础,才能真正理解算法背后的原理。
环境声明
在开始本章学习之前,请确保你的环境满足以下要求:
- Python版本:Python 3.12+(建议使用3.10以上版本)
- 核心库:NumPy 1.24+、SciPy 1.10+、Matplotlib 3.7+
- 开发工具:PyCharm 或 VS Code
- 操作系统:Windows / macOS / Linux(通用)
bash
# 安装依赖
pip install numpy scipy matplotlib
学习目标
完成本章学习后,你将能够:
- 理解向量、矩阵的基本运算及其几何意义
- 掌握特征分解与SVD的数学原理
- 理解概率分布、期望、方差等核心概念
- 掌握假设检验的基本方法
- 理解PCA降维的数学推导过程
- 使用NumPy实现PCA算法
1. 线性代数核心概念
线性代数是机器学习的基石。从数据表示到算法实现,线性代数无处不在。
1.1 向量与矩阵基础
向量的定义
向量是既有大小又有方向的量。在机器学习中,一个样本的特征通常表示为一个向量。
列向量表示:
x=[x1x2⋮xn]∈Rn \mathbf{x} = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} \in \mathbb{R}^n x= x1x2⋮xn ∈Rn
向量的基本运算:
| 运算 | 公式 | 几何意义 |
|---|---|---|
| 加法 | a+b\mathbf{a} + \mathbf{b}a+b | 平行四边形法则 |
| 数乘 | c⋅ac \cdot \mathbf{a}c⋅a | 向量缩放 |
| 点积 | a⋅b=∑i=1naibi\mathbf{a} \cdot \mathbf{b} = \sum_{i=1}^{n} a_i b_ia⋅b=∑i=1naibi | 投影长度 |
| 模长 | ∣a∣=∑i=1nai2|\mathbf{a}| = \sqrt{\sum_{i=1}^{n} a_i^2}∣a∣=∑i=1nai2 | 向量长度 |
矩阵的定义
矩阵是按矩形排列的数表,是向量的推广。
A=[a11a12⋯a1na21a22⋯a2n⋮⋮⋱⋮am1am2⋯amn]∈Rm×n \mathbf{A} = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{bmatrix} \in \mathbb{R}^{m \times n} A= a11a21⋮am1a12a22⋮am2⋯⋯⋱⋯a1na2n⋮amn ∈Rm×n
矩阵的基本运算:
python
import numpy as np
# 向量定义
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 向量点积
dot_product = np.dot(a, b) # 1*4 + 2*5 + 3*6 = 32
print(f"点积: {dot_product}")
# 向量模长
norm_a = np.linalg.norm(a) # sqrt(1 + 4 + 9) = sqrt(14)
print(f"模长: {norm_a:.4f}")
# 矩阵定义
A = np.array([[1, 2], [3, 4], [5, 6]]) # 3x2矩阵
B = np.array([[7, 8], [9, 10]]) # 2x2矩阵
# 矩阵乘法
C = np.dot(A, B) # 结果维度: 3x2
print(f"矩阵乘法结果:\n{C}")
1.2 特殊矩阵
在机器学习中,以下几类特殊矩阵尤为重要:
| 矩阵类型 | 定义 | 性质 |
|---|---|---|
| 单位矩阵 I\mathbf{I}I | 对角线为1,其余为0 | AI=A\mathbf{A}\mathbf{I} = \mathbf{A}AI=A |
| 对角矩阵 D\mathbf{D}D | 非对角线元素为0 | 特征值存储于对角线 |
| 对称矩阵 A\mathbf{A}A | AT=A\mathbf{A}^T = \mathbf{A}AT=A | 特征值为实数 |
| 正交矩阵 Q\mathbf{Q}Q | QTQ=I\mathbf{Q}^T\mathbf{Q} = \mathbf{I}QTQ=I | 保持向量长度不变 |
| 正定矩阵 | xTAx>0\mathbf{x}^T\mathbf{A}\mathbf{x} > 0xTAx>0 | 所有特征值大于0 |
1.3 特征分解
特征分解是理解矩阵本质的重要工具。
特征值与特征向量
对于方阵 A\mathbf{A}A,如果存在非零向量 v\mathbf{v}v 和标量 λ\lambdaλ 满足:
Av=λv \mathbf{A}\mathbf{v} = \lambda\mathbf{v} Av=λv
则称 λ\lambdaλ 为特征值,v\mathbf{v}v 为对应的特征向量。
特征分解公式
A=VΛV−1 \mathbf{A} = \mathbf{V}\mathbf{\Lambda}\mathbf{V}^{-1} A=VΛV−1
其中:
- Λ\mathbf{\Lambda}Λ 是由特征值构成的对角矩阵
- V\mathbf{V}V 是由特征向量构成的矩阵
特征分解的几何意义:
矩阵乘法 Ax\mathbf{A}\mathbf{x}Ax 可以理解为:先将向量 x\mathbf{x}x 变换到特征向量构成的坐标系(V−1x\mathbf{V}^{-1}\mathbf{x}V−1x),然后沿各坐标轴缩放(Λ\mathbf{\Lambda}Λ),最后变换回原坐标系(V\mathbf{V}V)。
python
import numpy as np
# 定义对称矩阵
A = np.array([[4, 2], [2, 3]])
# 特征分解
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues)
print("特征向量:\n", eigenvectors)
# 验证: A = V * Lambda * V^(-1)
Lambda = np.diag(eigenvalues)
V = eigenvectors
A_reconstructed = V @ Lambda @ np.linalg.inv(V)
print("重构矩阵:\n", A_reconstructed)
1.4 奇异值分解(SVD)
SVD是特征分解的广义形式,适用于任意矩阵(不限于方阵)。
SVD公式
对于矩阵 A∈Rm×n\mathbf{A} \in \mathbb{R}^{m \times n}A∈Rm×n,其SVD分解为:
A=UΣVT \mathbf{A} = \mathbf{U}\mathbf{\Sigma}\mathbf{V}^T A=UΣVT
其中:
- U∈Rm×m\mathbf{U} \in \mathbb{R}^{m \times m}U∈Rm×m:左奇异向量矩阵(正交矩阵)
- Σ∈Rm×n\mathbf{\Sigma} \in \mathbb{R}^{m \times n}Σ∈Rm×n:奇异值对角矩阵
- V∈Rn×n\mathbf{V} \in \mathbb{R}^{n \times n}V∈Rn×n:右奇异向量矩阵(正交矩阵)
SVD与特征分解的关系:
- ATA\mathbf{A}^T\mathbf{A}ATA 的特征向量构成 V\mathbf{V}V
- AAT\mathbf{A}\mathbf{A}^TAAT 的特征向量构成 U\mathbf{U}U
- 奇异值是 ATA\mathbf{A}^T\mathbf{A}ATA 特征值的平方根
python
import numpy as np
# 定义矩阵
A = np.array([[1, 2, 3], [4, 5, 6]]) # 2x3矩阵
# SVD分解
U, S, Vt = np.linalg.svd(A, full_matrices=False)
print("U矩阵:\n", U)
print("奇异值:", S)
print("V^T矩阵:\n", Vt)
# 重构矩阵
Sigma = np.diag(S)
A_reconstructed = U @ Sigma @ Vt
print("重构矩阵:\n", A_reconstructed)
2. 概率论基础
概率论为机器学习提供了处理不确定性的数学框架。
2.1 概率的基本概念
概率的定义
概率是描述随机事件发生可能性的数值,满足:
- 非负性:P(A)≥0P(A) \geq 0P(A)≥0
- 规范性:P(Ω)=1P(\Omega) = 1P(Ω)=1
- 可加性:互斥事件的概率可相加
条件概率与贝叶斯定理
条件概率:
P(A∣B)=P(A∩B)P(B),P(B)>0 P(A|B) = \frac{P(A \cap B)}{P(B)}, \quad P(B) > 0 P(A∣B)=P(B)P(A∩B),P(B)>0
贝叶斯定理:
P(A∣B)=P(B∣A)⋅P(A)P(B) P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)} P(A∣B)=P(B)P(B∣A)⋅P(A)
贝叶斯定理在机器学习中应用广泛,如朴素贝叶斯分类器、贝叶斯优化等。
2.2 常见概率分布
离散型分布
| 分布 | 概率质量函数 | 期望 | 方差 | 应用场景 |
|---|---|---|---|---|
| 伯努利分布 | P(X=k)=pk(1−p)1−kP(X=k) = p^k(1-p)^{1-k}P(X=k)=pk(1−p)1−k | ppp | p(1−p)p(1-p)p(1−p) | 二分类问题 |
| 二项分布 | P(X=k)=Cnkpk(1−p)n−kP(X=k) = C_n^k p^k(1-p)^{n-k}P(X=k)=Cnkpk(1−p)n−k | npnpnp | np(1−p)np(1-p)np(1−p) | n次独立试验 |
| 泊松分布 | P(X=k)=λke−λk!P(X=k) = \frac{\lambda^k e^{-\lambda}}{k!}P(X=k)=k!λke−λ | λ\lambdaλ | λ\lambdaλ | 计数数据 |
连续型分布
| 分布 | 概率密度函数 | 期望 | 方差 | 应用场景 |
|---|---|---|---|---|
| 均匀分布 | f(x)=1b−af(x) = \frac{1}{b-a}f(x)=b−a1 | a+b2\frac{a+b}{2}2a+b | (b−a)212\frac{(b-a)^2}{12}12(b−a)2 | 随机初始化 |
| 正态分布 | f(x)=12πσe−(x−μ)22σ2f(x) = \frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}}f(x)=2π σ1e−2σ2(x−μ)2 | μ\muμ | σ2\sigma^2σ2 | 误差建模、先验分布 |
| 指数分布 | f(x)=λe−λxf(x) = \lambda e^{-\lambda x}f(x)=λe−λx | 1λ\frac{1}{\lambda}λ1 | 1λ2\frac{1}{\lambda^2}λ21 | 等待时间 |
python
import numpy as np
from scipy import stats
# 正态分布
mu, sigma = 0, 1
normal_dist = stats.norm(mu, sigma)
# 概率密度函数
pdf_value = normal_dist.pdf(0) # x=0处的密度
print(f"PDF at x=0: {pdf_value:.4f}")
# 累积分布函数
cdf_value = normal_dist.cdf(1.96) # P(X <= 1.96)
print(f"CDF at x=1.96: {cdf_value:.4f}")
# 采样
samples = normal_dist.rvs(size=1000)
print(f"样本均值: {np.mean(samples):.4f}, 标准差: {np.std(samples):.4f}")
# 二项分布
n, p = 10, 0.5
binomial_dist = stats.binom(n, p)
prob = binomial_dist.pmf(5) # P(X=5)
print(f"二项分布P(X=5): {prob:.4f}")
2.3 期望与方差
期望(Expectation)
期望是随机变量的加权平均值,代表长期实验的平均结果。
离散型:
E[X]=∑ixi⋅P(X=xi) E[X] = \sum_{i} x_i \cdot P(X=x_i) E[X]=i∑xi⋅P(X=xi)
连续型:
E[X]=∫−∞∞x⋅f(x)dx E[X] = \int_{-\infty}^{\infty} x \cdot f(x) dx E[X]=∫−∞∞x⋅f(x)dx
方差(Variance)
方差度量随机变量偏离期望的程度。
Var(X)=E[(X−E[X])2]=E[X2]−(E[X])2 Var(X) = E[(X - E[X])^2] = E[X^2] - (E[X])^2 Var(X)=E[(X−E[X])2]=E[X2]−(E[X])2
协方差与相关系数
协方差:
Cov(X,Y)=E[(X−E[X])(Y−E[Y])] Cov(X, Y) = E[(X - E[X])(Y - E[Y])] Cov(X,Y)=E[(X−E[X])(Y−E[Y])]
相关系数:
ρXY=Cov(X,Y)σXσY \rho_{XY} = \frac{Cov(X, Y)}{\sigma_X \sigma_Y} ρXY=σXσYCov(X,Y)
python
import numpy as np
# 生成数据
np.random.seed(42)
X = np.random.randn(100)
Y = 2 * X + np.random.randn(100) * 0.5
# 期望
mean_X = np.mean(X)
mean_Y = np.mean(Y)
# 方差
var_X = np.var(X, ddof=1) # 样本方差
var_Y = np.var(Y, ddof=1)
# 协方差矩阵
cov_matrix = np.cov(X, Y)
print("协方差矩阵:\n", cov_matrix)
# 相关系数矩阵
corr_matrix = np.corrcoef(X, Y)
print("相关系数矩阵:\n", corr_matrix)
2.4 最大似然估计
最大似然估计(MLE)是机器学习中参数估计的核心方法。
似然函数
给定样本 x=(x1,x2,...,xn)\mathbf{x} = (x_1, x_2, ..., x_n)x=(x1,x2,...,xn),似然函数定义为:
L(θ∣x)=∏i=1nf(xi;θ) L(\theta | \mathbf{x}) = \prod_{i=1}^{n} f(x_i; \theta) L(θ∣x)=i=1∏nf(xi;θ)
对数似然
为了方便计算,通常使用对数似然:
ℓ(θ)=logL(θ∣x)=∑i=1nlogf(xi;θ) \ell(\theta) = \log L(\theta | \mathbf{x}) = \sum_{i=1}^{n} \log f(x_i; \theta) ℓ(θ)=logL(θ∣x)=i=1∑nlogf(xi;θ)
正态分布的MLE示例
对于正态分布 N(μ,σ2)N(\mu, \sigma^2)N(μ,σ2),MLE估计为:
μ^=1n∑i=1nxi \hat{\mu} = \frac{1}{n}\sum_{i=1}^{n} x_i μ^=n1i=1∑nxi
σ^2=1n∑i=1n(xi−μ^)2 \hat{\sigma}^2 = \frac{1}{n}\sum_{i=1}^{n} (x_i - \hat{\mu})^2 σ^2=n1i=1∑n(xi−μ^)2
python
import numpy as np
from scipy.optimize import minimize
# 生成正态分布样本
true_mu, true_sigma = 5, 2
np.random.seed(42)
samples = np.random.normal(true_mu, true_sigma, 1000)
# 定义负对数似然函数
def negative_log_likelihood(params, data):
mu, sigma = params
if sigma <= 0:
return np.inf
n = len(data)
log_likelihood = -0.5 * n * np.log(2 * np.pi) - n * np.log(sigma) - \
np.sum((data - mu)**2) / (2 * sigma**2)
return -log_likelihood
# 最大似然估计
result = minimize(negative_log_likelihood, [0, 1], args=(samples,))
mle_mu, mle_sigma = result.x
print(f"真实参数: mu={true_mu}, sigma={true_sigma}")
print(f"MLE估计: mu={mle_mu:.4f}, sigma={mle_sigma:.4f}")
3. 统计学基础
统计学提供了从数据中提取信息和做出推断的方法。
3.1 描述性统计
描述性统计用于总结和描述数据的基本特征。
| 统计量 | 定义 | 公式 |
|---|---|---|
| 均值 | 数据的平均值 | xˉ=1n∑i=1nxi\bar{x} = \frac{1}{n}\sum_{i=1}^{n} x_ixˉ=n1∑i=1nxi |
| 中位数 | 排序后中间位置的值 | - |
| 众数 | 出现频率最高的值 | - |
| 标准差 | 数据离散程度 | s=1n−1∑i=1n(xi−xˉ)2s = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2}s=n−11∑i=1n(xi−xˉ)2 |
| 四分位数 | 将数据分为四等份 | Q1, Q2, Q3 |
3.2 假设检验
假设检验用于判断样本数据是否支持某个统计假设。
基本步骤
-
建立假设
- 原假设 H0H_0H0:待检验的假设
- 备择假设 H1H_1H1:与原假设对立的假设
-
选择检验统计量
-
确定显著性水平 α\alphaα(通常取0.05)
-
计算p值并做出决策
常见检验方法
| 检验类型 | 适用场景 | 检验统计量 |
|---|---|---|
| Z检验 | 大样本均值检验 | Z=Xˉ−μ0σ/nZ = \frac{\bar{X} - \mu_0}{\sigma/\sqrt{n}}Z=σ/n Xˉ−μ0 |
| T检验 | 小样本均值检验 | t=Xˉ−μ0s/nt = \frac{\bar{X} - \mu_0}{s/\sqrt{n}}t=s/n Xˉ−μ0 |
| 卡方检验 | 分类变量独立性 | χ2=∑(O−E)2E\chi^2 = \sum \frac{(O-E)^2}{E}χ2=∑E(O−E)2 |
| F检验 | 方差比较 | F=s12s22F = \frac{s_1^2}{s_2^2}F=s22s12 |
3.3 置信区间
置信区间给出了估计值的不确定性范围。
均值的置信区间
对于正态分布样本,95%置信区间为:
xˉ±t0.025,n−1⋅sn \bar{x} \pm t_{0.025, n-1} \cdot \frac{s}{\sqrt{n}} xˉ±t0.025,n−1⋅n s
python
import numpy as np
from scipy import stats
# 生成样本数据
np.random.seed(42)
sample = np.random.normal(100, 15, 50)
# 计算95%置信区间
confidence_level = 0.95
alpha = 1 - confidence_level
mean = np.mean(sample)
std_err = stats.sem(sample) # 标准误
# 使用t分布
df = len(sample) - 1
t_critical = stats.t.ppf(1 - alpha/2, df)
margin_error = t_critical * std_err
ci_lower = mean - margin_error
ci_upper = mean + margin_error
print(f"样本均值: {mean:.2f}")
print(f"95%置信区间: [{ci_lower:.2f}, {ci_upper:.2f}]")
# 使用scipy直接计算
confidence_interval = stats.t.interval(
confidence_level, df, loc=mean, scale=std_err
)
print(f"置信区间(函数计算): {confidence_interval}")
3.4 p值的解释
p值是在原假设为真的前提下,观察到当前样本或更极端样本的概率。
p值的解读:
| p值范围 | 结论 |
|---|---|
| p < 0.01 | 极强证据拒绝原假设 |
| 0.01 <= p < 0.05 | 较强证据拒绝原假设 |
| 0.05 <= p < 0.1 | 弱证据 |
| p >= 0.1 | 无充分证据拒绝原假设 |
注意:p值不是原假设为真的概率,也不是备择假设为真的概率。
4. 机器学习中的数学应用
4.1 PCA的数学原理
主成分分析(PCA)是一种经典的无监督降维算法,其核心思想是找到数据方差最大的方向。
PCA的数学推导
目标:将数据投影到低维空间,同时最大化保留方差。
设数据矩阵 X∈Rn×d\mathbf{X} \in \mathbb{R}^{n \times d}X∈Rn×d(n个样本,d个特征),已中心化(均值为0)。
第一步:计算协方差矩阵
C=1n−1XTX \mathbf{C} = \frac{1}{n-1}\mathbf{X}^T\mathbf{X} C=n−11XTX
第二步:特征分解
Cvi=λivi \mathbf{C}\mathbf{v}_i = \lambda_i\mathbf{v}_i Cvi=λivi
其中 λ1≥λ2≥...≥λd\lambda_1 \geq \lambda_2 \geq ... \geq \lambda_dλ1≥λ2≥...≥λd 是特征值,vi\mathbf{v}_ivi 是对应的特征向量。
第三步:选择主成分
选择前k个最大特征值对应的特征向量,构成投影矩阵 W=[v1,v2,...,vk]\mathbf{W} = [\mathbf{v}_1, \mathbf{v}_2, ..., \mathbf{v}_k]W=[v1,v2,...,vk]。
第四步:数据投影
Z=XW \mathbf{Z} = \mathbf{X}\mathbf{W} Z=XW
PCA与SVD的关系
PCA可以通过SVD高效计算:
X=UΣVT \mathbf{X} = \mathbf{U}\mathbf{\Sigma}\mathbf{V}^T X=UΣVT
其中 V\mathbf{V}V 的列向量就是PCA的主成分方向。
方差保留率
第i个主成分保留的方差比例为:
方差保留率i=λi∑j=1dλj \text{方差保留率}i = \frac{\lambda_i}{\sum{j=1}^{d}\lambda_j} 方差保留率i=∑j=1dλjλi
前k个主成分的累计方差保留率:
累计保留率=∑i=1kλi∑j=1dλj \text{累计保留率} = \frac{\sum_{i=1}^{k}\lambda_i}{\sum_{j=1}^{d}\lambda_j} 累计保留率=∑j=1dλj∑i=1kλi
4.2 梯度下降的数学推导
梯度下降是优化机器学习模型参数的核心算法。
梯度下降的原理
目标 :最小化损失函数 J(θ)J(\theta)J(θ)
更新规则:
θt+1=θt−α∇J(θt) \theta_{t+1} = \theta_t - \alpha \nabla J(\theta_t) θt+1=θt−α∇J(θt)
其中:
- α\alphaα 是学习率
- ∇J(θ)\nabla J(\theta)∇J(θ) 是损失函数的梯度
线性回归的梯度下降
对于线性回归,损失函数为均方误差(MSE):
J(θ)=12m∑i=1m(hθ(x(i))−y(i))2 J(\theta) = \frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)}) - y^{(i)})^2 J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
其中 hθ(x)=θTxh_\theta(x) = \theta^T xhθ(x)=θTx。
梯度计算:
∂J∂θj=1m∑i=1m(hθ(x(i))−y(i))xj(i) \frac{\partial J}{\partial \theta_j} = \frac{1}{m}\sum_{i=1}^{m}(h_\theta(x^{(i)}) - y^{(i)})x_j^{(i)} ∂θj∂J=m1i=1∑m(hθ(x(i))−y(i))xj(i)
向量化形式:
∇J(θ)=1mXT(Xθ−y) \nabla J(\theta) = \frac{1}{m}\mathbf{X}^T(\mathbf{X}\theta - \mathbf{y}) ∇J(θ)=m1XT(Xθ−y)
python
import numpy as np
def gradient_descent(X, y, theta, alpha, num_iters):
"""
梯度下降算法实现
参数:
X: 特征矩阵 (m, n)
y: 目标向量 (m,)
theta: 参数向量 (n,)
alpha: 学习率
num_iters: 迭代次数
"""
m = len(y)
cost_history = []
for i in range(num_iters):
# 计算预测值
predictions = X @ theta
# 计算误差
errors = predictions - y
# 计算梯度
gradient = (1/m) * (X.T @ errors)
# 更新参数
theta = theta - alpha * gradient
# 计算损失(用于监控)
cost = (1/(2*m)) * np.sum(errors**2)
cost_history.append(cost)
return theta, cost_history
5. 实战案例:使用NumPy实现PCA
本节将完整实现PCA算法,并将其应用于数据降维任务。
5.1 完整PCA实现
python
import numpy as np
import matplotlib.pyplot as plt
class PCA:
"""
主成分分析(PCA)的NumPy实现
参数:
n_components: 保留的主成分数量
"""
def __init__(self, n_components=None):
self.n_components = n_components
self.components_ = None # 主成分(特征向量)
self.explained_variance_ = None # 各主成分的方差
self.explained_variance_ratio_ = None # 方差贡献率
self.mean_ = None # 特征均值
def fit(self, X):
"""
拟合PCA模型
参数:
X: 输入数据,形状为 (n_samples, n_features)
"""
# 保存特征均值
self.mean_ = np.mean(X, axis=0)
# 数据中心化
X_centered = X - self.mean_
# 计算协方差矩阵
n_samples = X.shape[0]
cov_matrix = (X_centered.T @ X_centered) / (n_samples - 1)
# 特征分解
eigenvalues, eigenvectors = np.linalg.eigh(cov_matrix)
# 按特征值从大到小排序
idx = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[idx]
eigenvectors = eigenvectors[:, idx]
# 保存结果
self.explained_variance_ = eigenvalues
self.explained_variance_ratio_ = eigenvalues / np.sum(eigenvalues)
# 确定保留的主成分数量
if self.n_components is None:
self.n_components = X.shape[1]
self.components_ = eigenvectors[:, :self.n_components]
return self
def transform(self, X):
"""
将数据投影到主成分空间
参数:
X: 输入数据
返回:
降维后的数据
"""
X_centered = X - self.mean_
return X_centered @ self.components_
def fit_transform(self, X):
"""拟合模型并转换数据"""
self.fit(X)
return self.transform(X)
def inverse_transform(self, X_reduced):
"""
将降维后的数据还原到原始空间
参数:
X_reduced: 降维后的数据
返回:
还原后的数据
"""
return X_reduced @ self.components_.T + self.mean_
# 使用示例
if __name__ == "__main__":
# 生成示例数据
np.random.seed(42)
# 创建二维高斯数据,具有一定的相关性
mean = [0, 0]
cov = [[3, 2], [2, 2]] # 协方差矩阵
X = np.random.multivariate_normal(mean, cov, 300)
# 应用PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
# 输出结果
print("=" * 50)
print("PCA结果分析")
print("=" * 50)
print(f"原始数据维度: {X.shape}")
print(f"降维后数据维度: {X_pca.shape}")
print(f"\n特征值(方差): {pca.explained_variance_}")
print(f"方差贡献率: {pca.explained_variance_ratio_}")
print(f"累计方差贡献率: {np.cumsum(pca.explained_variance_ratio_)}")
print(f"\n主成分方向:\n{pca.components_}")
# 数据还原
X_reconstructed = pca.inverse_transform(X_pca)
reconstruction_error = np.mean((X - X_reconstructed)**2)
print(f"\n重构误差: {reconstruction_error:.6f}")
5.2 降维效果可视化
python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
# 加载鸢尾花数据集
iris = load_iris()
X = iris.data
y = iris.target
target_names = iris.target_names
# 应用PCA降至2维
pca = PCA(n_components=2)
X_r = pca.fit_transform(X)
# 可视化
plt.figure(figsize=(10, 8))
colors = ['navy', 'turquoise', 'darkorange']
for color, i, target_name in zip(colors, [0, 1, 2], target_names):
plt.scatter(X_r[y == i, 0], X_r[y == i, 1],
color=color, alpha=0.8, lw=2, label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('PCA of IRIS Dataset')
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.1%} variance)')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.1%} variance)')
plt.grid(True, alpha=0.3)
plt.savefig('pca_iris_visualization.png', dpi=150, bbox_inches='tight')
plt.show()
# 方差贡献率分析
print("\n各主成分方差贡献率:")
for i, ratio in enumerate(pca.explained_variance_ratio_):
print(f" PC{i+1}: {ratio:.4f} ({ratio:.2%})")
print(f"累计贡献率: {np.sum(pca.explained_variance_ratio_):.2%}")
5.3 选择合适的主成分数量
python
import numpy as np
import matplotlib.pyplot as plt
def plot_variance_explained(pca, threshold=0.95):
"""
绘制方差贡献率图,帮助选择主成分数量
参数:
pca: 拟合好的PCA对象
threshold: 方差保留阈值
"""
n_components = len(pca.explained_variance_ratio_)
# 计算累计方差贡献率
cumsum_ratio = np.cumsum(pca.explained_variance_ratio_)
# 找到满足阈值的最小主成分数
n_components_needed = np.argmax(cumsum_ratio >= threshold) + 1
# 绘图
plt.figure(figsize=(10, 6))
# 单个方差贡献率
plt.bar(range(1, n_components + 1),
pca.explained_variance_ratio_,
alpha=0.7, label='Individual')
# 累计方差贡献率
plt.plot(range(1, n_components + 1),
cumsum_ratio,
'ro-', label='Cumulative')
# 阈值线
plt.axhline(y=threshold, color='g', linestyle='--',
label=f'{threshold:.0%} threshold')
plt.axvline(x=n_components_needed, color='g', linestyle='--')
plt.xlabel('Number of Components')
plt.ylabel('Explained Variance Ratio')
plt.title('PCA Variance Explained')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('pca_variance_explained.png', dpi=150, bbox_inches='tight')
plt.show()
print(f"保留{threshold:.0%}方差需要的主成分数: {n_components_needed}")
return n_components_needed
# 示例使用
# n_needed = plot_variance_explained(pca, threshold=0.95)
6. 避坑小贴士
6.1 线性代数常见错误
-
矩阵维度不匹配
- 在进行矩阵乘法前,务必检查维度
- A(m,n) @ B(n,p) = C(m,p)
-
混淆矩阵乘法和逐元素乘法
np.dot(A, B)或A @ B:矩阵乘法A * B:逐元素乘法(Hadamard积)
-
忽视数值稳定性
- 求逆矩阵时,条件数过大的矩阵会导致数值不稳定
- 优先使用
np.linalg.solve而非直接求逆
6.2 概率统计常见错误
-
混淆样本方差和总体方差
- 样本方差分母为 n-1(无偏估计)
- NumPy中
np.var(x, ddof=1)计算样本方差
-
误解p值的含义
- p值不是原假设为真的概率
- p值小只说明数据与原假设不一致,不代表效应大小
-
忽视数据分布假设
- t检验假设数据近似正态分布
- 样本量小时,先检验正态性
6.3 PCA使用注意事项
-
数据必须中心化
- PCA对数据的平移敏感
- 实现时务必减去均值
-
特征缩放
- 当特征量纲不同时,先进行标准化
- 否则量纲大的特征会主导主成分
-
处理缺失值
- PCA不能处理含缺失值的数据
- 需先进行缺失值填充
7. 本章小结
本章系统介绍了机器学习所需的数学基础,核心要点如下:
线性代数:
- 向量与矩阵是数据的数学表示
- 特征分解揭示矩阵的本质结构
- SVD是更通用的矩阵分解方法
概率论:
- 概率分布建模随机现象
- 期望和方差描述分布特征
- 最大似然估计是参数估计的核心方法
统计学:
- 假设检验用于判断统计显著性
- 置信区间量化估计的不确定性
- p值是证据强度的度量
机器学习应用:
- PCA通过特征分解实现数据降维
- 梯度下降利用导数信息优化参数
- 数学原理是理解算法的关键
8. 思考与练习
基础练习
-
向量运算 :给定向量 a=[1,2,3]T\mathbf{a} = [1, 2, 3]^Ta=[1,2,3]T 和 b=[4,5,6]T\mathbf{b} = [4, 5, 6]^Tb=[4,5,6]T,计算:
- 点积 a⋅b\mathbf{a} \cdot \mathbf{b}a⋅b
- 叉积(如果是在3D空间)
- 向量夹角的余弦值
-
矩阵分解 :对矩阵 A=[4223]\mathbf{A} = \begin{bmatrix} 4 & 2 \\ 2 & 3 \end{bmatrix}A=[4223] 进行特征分解,并验证 A=VΛV−1\mathbf{A} = \mathbf{V}\mathbf{\Lambda}\mathbf{V}^{-1}A=VΛV−1。
-
概率计算 :假设某班级学生身高服从正态分布 N(170,25)N(170, 25)N(170,25),计算:
- 随机抽取一名学生身高超过180cm的概率
- 身高在165cm到175cm之间的概率
进阶练习
-
PCA实现:使用NumPy实现PCA算法,并在MNIST数据集上进行降维可视化(降至2维)。
-
梯度下降优化:实现带动量的梯度下降算法,比较其与标准梯度下降在收敛速度上的差异。
-
假设检验:收集一组样本数据,进行单样本t检验,判断样本均值是否显著不同于某个假设值。
挑战练习
-
SVD应用:使用SVD进行图像压缩,比较不同保留奇异值数量对图像质量和压缩比的影响。
-
MLE推导:推导泊松分布和指数分布的最大似然估计公式,并用Python实现。
-
协方差分析:分析多变量数据集的协方差矩阵,解释变量间的相关性结构。
学习建议:数学基础需要反复练习才能掌握。建议读者动手推导本章的公式,并运行所有代码示例。
本系列教程持续更新中,欢迎关注专栏获取更多机器学习深度内容。