深入解析 PCA 与三元组损失:从理论推导到实践应用
- PCA (Principal Component Analysis) 主成分分析详解
- 1. 基本概念
- 1.1 什么是 PCA?
- 1.2 核心目标
- 1.3 应用场景
- 2. 数学原理详解
- 2.1 问题形式化
- 2.2 数据预处理
- 2.3 协方差矩阵的计算
- 2.4 特征值分解
- 2.5 最大方差推导
- 2.6 数据降维
- 3. 重要指标
- 3.1 方差贡献率
- 3.2 累积方差贡献率
- 总结
- PCA降维实战
- 代码
- 运行结果
- 三元组损失 (Triplet Loss) 的详解
- 1. 基本概念
- 2. 数学公式与推导
- 2.1 损失函数定义
- 2.2 损失函数分段表示
- 2.3 优化目标的几何解释
- 3. 公式推导过程
- 3.1 欧几里得距离的展开
- 3.2 损失函数表达式的代入
- 4. 模型训练与样本构造
- 4.1 三元组样本选择
- 4.2 训练过程
- 5. 重要性质与参数选择
- 5.1 边际值 \(\alpha\)
- 5.2 嵌入空间维度
- 总结
- 三元组损失函数实战
- 代码
- 结果分析
- 总结
PCA (Principal Component Analysis) 主成分分析详解
PCA 是一种强大的线性降维技术,广泛应用于机器学习和数据分析领域,其目标是通过线性变换将高维数据映射到低维空间,同时尽可能保留数据的主要信息。以下是 PCA 的理论基础与数学原理的详细解析。
1. 基本概念
1.1 什么是 PCA?
主成分分析 (PCA) 的核心思想是通过线性变换找到数据中“变化最大”的方向(即主成分),并将数据投影到这些方向上。这样可以实现数据降维,同时尽可能保留原始数据的信息。
其关键特性包括:
- 降维:将 (n) 维数据映射到 (k) 维 ((k < n)),减少数据维度。
- 保留方差:投影方向按数据方差大小排序,优先保留方差最大的方向。
- 正交性:主成分彼此正交,保证信息不冗余。
1.2 核心目标
PCA 的目标是找到一组新的坐标轴,使得:
- 数据在这些轴上的投影方差最大。
- 新坐标轴之间相互正交。
1.3 应用场景
PCA 常用于以下场景:
- 降维:减少数据维度,去掉冗余特征。
- 可视化:将高维数据映射到 2D 或 3D 空间,便于观察。
- 噪声过滤:通过忽略小方差的主成分来去除噪声。
- 特征提取:用少量无关的主成分代替原始特征。
2. 数学原理详解
2.1 问题形式化
假设我们有一个 (m \times n) 的数据矩阵 (X),其中 (m) 为样本数,(n) 为特征数:
X = [ x 11 x 12 ⋯ x 1 n x 21 x 22 ⋯ x 2 n ⋮ ⋮ ⋱ ⋮ x m 1 x m 2 ⋯ x m n ] . X = \begin{bmatrix} x_{11} & x_{12} & \cdots & x_{1n} \\ x_{21} & x_{22} & \cdots & x_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ x_{m1} & x_{m2} & \cdots & x_{mn} \end{bmatrix}. X= x11x21⋮xm1x12x22⋮xm2⋯⋯⋱⋯x1nx2n⋮xmn .
PCA 的目标是将数据从原始空间变换到一个新的低维空间 (Y),并且新空间中的每个维度都是原特征的线性组合。
2.2 数据预处理
- 中心化 (Mean Removal)
为确保结果不受原始特征取值范围的影响,需要对数据进行中心化操作,即将每个特征减去其均值:
μ = 1 m ∑ i = 1 m x i , X ′ = X − μ . \mu = \frac{1}{m} \sum_{i=1}^m x_i, \quad X' = X - \mu. μ=m1i=1∑mxi,X′=X−μ.
其中,(\mu) 是一个 (1 \times n) 的向量,表示每列的均值。中心化后的数据矩阵 (X’) 满足每列特征的均值为零。
- 标准化 (Optional)
如果不同特征的尺度差异较大(如身高以厘米为单位,体重以公斤为单位),还需要进行标准化处理:
x i j ′ = x i j − μ j σ j , σ j = 1 m ∑ i = 1 m ( x i j − μ j ) 2 . x'_{ij} = \frac{x_{ij} - \mu_j}{\sigma_j}, \quad \sigma_j = \sqrt{\frac{1}{m} \sum_{i=1}^m (x_{ij} - \mu_j)^2}. xij′=σjxij−μj,σj=m1i=1∑m(xij−μj)2.
标准化后的每列特征具有均值 0 和方差 1。
2.3 协方差矩阵的计算
中心化后的数据矩阵 (X’) 的协方差矩阵 (C) 用于表示不同特征之间的线性相关性:
C = 1 m − 1 X ′ T X ′ . C = \frac{1}{m-1} X'^T X'. C=m−11X′TX′.
协方差矩阵 (C) 是一个 (n \times n) 的对称矩阵,元素 (C_{ij}) 表示特征 (i) 和特征 (j) 的协方差:
C i j = 1 m − 1 ∑ k = 1 m ( x k i ′ ⋅ x k j ′ ) . C_{ij} = \frac{1}{m-1} \sum_{k=1}^m (x'_{ki} \cdot x'_{kj}). Cij=m−11k=1∑m(xki′⋅xkj′).
2.4 特征值分解
PCA 的核心在于对协方差矩阵进行特征值分解。
- 特征值和特征向量
解以下特征值问题:
C v = λ v , Cv = \lambda v, Cv=λv,
其中:
- (v \in \mathbb{R}^n) 为特征向量;
- (\lambda \in \mathbb{R}) 为特征值。
特征值表示在对应特征向量方向上的数据方差大小。所有特征值和特征向量构成一组正交基。
- 排序
将特征值按降序排列:
λ 1 ≥ λ 2 ≥ ⋯ ≥ λ n . \lambda_1 \geq \lambda_2 \geq \cdots \geq \lambda_n. λ1≥λ2≥⋯≥λn.
对应的特征向量为 (v_1, v_2, \dots, v_n)。
2.5 最大方差推导
投影方向 (w) 的方差可表示为:
Var ( X w ) = w T C w , \text{Var}(Xw) = w^T C w, Var(Xw)=wTCw,
约束条件为:
∥ w ∥ = 1. \|w\| = 1. ∥w∥=1.
通过拉格朗日乘子法求解最大方差问题:
L ( w , α ) = w T C w − α ( w T w − 1 ) , L(w, \alpha) = w^T C w - \alpha (w^T w - 1), L(w,α)=wTCw−α(wTw−1),
对 (w) 求导:
∂ L ∂ w = 2 C w − 2 α w = 0. \frac{\partial L}{\partial w} = 2Cw - 2\alpha w = 0. ∂w∂L=2Cw−2αw=0.
化简得:
C w = α w . Cw = \alpha w. Cw=αw.
由此可见,最优投影方向 (w) 即为协方差矩阵的特征向量。
2.6 数据降维
选择前 (k) 个最大的特征值对应的特征向量构成投影矩阵:
W = [ v 1 , v 2 , … , v k ] , W = [v_1, v_2, \dots, v_k], W=[v1,v2,…,vk],
其中 (W \in \mathbb{R}^{n \times k})。
降维后的数据为:
Y = X ′ W , Y = X' W, Y=X′W,
其中 (Y \in \mathbb{R}^{m \times k}) 为降维后的数据。
3. 重要指标
3.1 方差贡献率
方差贡献率用于衡量每个主成分在数据中所占的信息比例:
ρ i = λ i ∑ j = 1 n λ j . \rho_i = \frac{\lambda_i}{\sum_{j=1}^n \lambda_j}. ρi=∑j=1nλjλi.
3.2 累积方差贡献率
累积方差贡献率衡量前 (k) 个主成分所包含的信息比例:
R k = ∑ i = 1 k λ i ∑ j = 1 n λ j . R_k = \frac{\sum_{i=1}^k \lambda_i}{\sum_{j=1}^n \lambda_j}. Rk=∑j=1nλj∑i=1kλi.
当 (R_k) 接近 1 时,表示前 (k) 个主成分已包含绝大部分信息。
总结
PCA 是一个基于线性代数的优雅降维工具,它通过特征值分解或奇异值分解,将数据映射到低维空间,同时保留数据的主要信息。通过数学公式和描述性语言的结合,我们可以清晰地理解其原理及实际应用。
PCA降维实战
接下来演示使用PCA降维对MNIST数据集中的图片进行降维可视化展示
代码
import numpy as np
from sklearn.datasets import fetch_openml
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler, MinMaxScaler# 加载MNIST数据集
mnist = fetch_openml('mnist_784', version=1, as_frame=False)
X, y = mnist.data, mnist.target# 选择数字0的90张图片
digit_0_indices = np.where(y == '0')[0][:90]
X_0 = X[digit_0_indices]# 选择数字1-9各10张图片
X_others = []
y_others = []
for digit in range(1, 10):indices = np.where(y == str(digit))[0][:10]X_others.append(X[indices])y_others.extend([digit] * 10)# 合并所有数据
X_selected = np.vstack([X_0] + X_others)
y_selected = np.array(['0']*90 + y_others)# 更强的数据预处理
# 1. MinMax缩放到[0,1]
minmax_scaler = MinMaxScaler()
X_minmax = minmax_scaler.fit_transform(X_selected)
# 2. 标准化处理
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_minmax)# 应用PCA降维
pca = PCA(n_components=2, random_state=42)
X_pca = pca.fit_transform(X_scaled)# 计算类别中心点
centers = {}
for digit in range(10):mask = y_selected == str(digit)centers[digit] = np.mean(X_pca[mask], axis=0)# 可视化结果
plt.figure(figsize=(12, 8))
plt.style.use('default') # 使用默认样式# 修改颜色方案:红色表示0,蓝色表示其他所有数字
colors = ['#FF0000', '#1f77b4'] # 红色和蓝色# 绘制连接线(从每个点到类别中心)
# 先画其他数字(1-9)的连接线
for digit in range(1, 10):mask = y_selected == str(digit)points = X_pca[mask]center = centers[digit]for point in points:plt.plot([point[0], center[0]], [point[1], center[1]], color=colors[1], alpha=0.1)# 画数字0的连接线
mask = y_selected == '0'
points = X_pca[mask]
center = centers[0]
for point in points:plt.plot([point[0], center[0]], [point[1], center[1]], color=colors[0], alpha=0.1)# 先绘制其他数字(1-9)的散点
for digit in range(1, 10):mask = y_selected == str(digit)plt.scatter(X_pca[mask, 0], X_pca[mask, 1], c=[colors[1]], label='Other digits (1-9)' if digit == 1 else "",alpha=0.8,s=150,edgecolors='white',linewidth=1)# 绘制数字0的散点
mask = y_selected == '0'
plt.scatter(X_pca[mask, 0], X_pca[mask, 1], c=[colors[0]], label='Digit 0',alpha=0.8,s=150,edgecolors='white',linewidth=1)# 绘制类别中心点
for digit in range(10):plt.scatter(centers[digit][0], centers[digit][1], c=[colors[0] if digit == 0 else colors[1]], s=300,marker='*',edgecolors='black',linewidth=1.5)plt.title('MNIST Data PCA Visualization (2D)', fontsize=14, pad=20)
plt.xlabel(f'First Principal Component (Variance Ratio: {pca.explained_variance_ratio_[0]:.3f})', fontsize=12)
plt.ylabel(f'Second Principal Component (Variance Ratio: {pca.explained_variance_ratio_[1]:.3f})', fontsize=12)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=10)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('pca_visualization_enhanced.png', dpi=300, bbox_inches='tight')
plt.close()
# 打印解释方差信息
print(f"第一主成分解释的方差比例: {pca.explained_variance_ratio_[0]:.4f}")
print(f"第二主成分解释的方差比例: {pca.explained_variance_ratio_[1]:.4f}")
print(f"累计解释的方差比例: {sum(pca.explained_variance_ratio_):.4f}")
运行结果
通过图片可以出,是将数字0渲染为红色,其他数字均为蓝色,数字0一共有90张图片,其他数字每一个数字10张图片。
三元组损失 (Triplet Loss) 的详解
三元组损失(Triplet Loss)是一种广泛应用于深度学习中的度量学习方法,特别是在人脸识别、图像检索等任务中效果显著。它通过直接优化样本在嵌入空间中的几何关系,使得相似样本距离更近,不相似样本距离更远,从而学习到有判别力的特征表示。
1. 基本概念
三元组损失的核心思想是基于样本的三元组构造:
- Anchor (A):目标样本。
- Positive §:与 Anchor 属于同一类的样本。
- Negative (N):与 Anchor 属于不同类的样本。
目标是:
- 使 Anchor 和 Positive 之间的距离尽可能接近。
- 使 Anchor 和 Negative 之间的距离尽可能远。
数学上,三元组损失的优化目标可以用如下方式描述:
∥ f ( A ) − f ( P ) ∥ 2 2 + α < ∥ f ( A ) − f ( N ) ∥ 2 2 , \|f(A) - f(P)\|_2^2 + \alpha < \|f(A) - f(N)\|_2^2, ∥f(A)−f(P)∥22+α<∥f(A)−f(N)∥22,
其中:
- (f(x)) 是样本 (x) 的特征嵌入向量;
- (|\cdot|_2^2) 表示欧几里得距离的平方;
- (\alpha) 是一个正的边际值(margin),用来确保不同类别之间的样本距离有一定的间隔。
2. 数学公式与推导
2.1 损失函数定义
三元组损失的形式化定义为:
L ( A , P , N ) = max { 0 , ∥ f ( A ) − f ( P ) ∥ 2 2 − ∥ f ( A ) − f ( N ) ∥ 2 2 + α } . L(A, P, N) = \max\{0, \|f(A) - f(P)\|_2^2 - \|f(A) - f(N)\|_2^2 + \alpha\}. L(A,P,N)=max{0,∥f(A)−f(P)∥22−∥f(A)−f(N)∥22+α}.
其中:
- (|f(A) - f§|_2^2):Anchor 和 Positive 的欧几里得距离平方;
- (|f(A) - f(N)|_2^2):Anchor 和 Negative 的欧几里得距离平方;
- (\max{0, \cdot}):表示当距离关系符合约束时(即损失值为负时),损失记为 0;
- (\alpha):超参数,用来控制正负样本之间的最小距离差。
2.2 损失函数分段表示
三元组损失可以理解为一种分段函数:
L ( A , P , N ) = { 0 , if ∥ f ( A ) − f ( P ) ∥ 2 2 + α < ∥ f ( A ) − f ( N ) ∥ 2 2 , ∥ f ( A ) − f ( P ) ∥ 2 2 − ∥ f ( A ) − f ( N ) ∥ 2 2 + α , otherwise . L(A, P, N) = \begin{cases} 0, & \text{if } \|f(A) - f(P)\|_2^2 + \alpha < \|f(A) - f(N)\|_2^2, \\ \|f(A) - f(P)\|_2^2 - \|f(A) - f(N)\|_2^2 + \alpha, & \text{otherwise}. \end{cases} L(A,P,N)={0,∥f(A)−f(P)∥22−∥f(A)−f(N)∥22+α,if ∥f(A)−f(P)∥22+α<∥f(A)−f(N)∥22,otherwise.
这表明,当样本嵌入满足约束条件时,损失值为 0;当约束条件被违反时,损失函数的值取决于当前样本距离与边际值的差异。
2.3 优化目标的几何解释
三元组损失的优化目标是最小化:
- Anchor 和 Positive 的距离:使得相似样本被拉近。
- Anchor 和 Negative 的距离加上边际值 (\alpha):使得非相似样本被推远。
其几何含义如下:
- 优化前:
- 相似样本和非相似样本的距离可能存在交叠,无法区分类别。
- 优化后:
- 相似样本的嵌入点在高维空间中聚集,非相似样本的嵌入点彼此分离。
3. 公式推导过程
3.1 欧几里得距离的展开
首先定义任意两个嵌入向量之间的欧几里得距离平方为:
∥ f ( x 1 ) − f ( x 2 ) ∥ 2 2 = ∑ i = 1 d ( f ( x 1 ) i − f ( x 2 ) i ) 2 , \|f(x_1) - f(x_2)\|_2^2 = \sum_{i=1}^d (f(x_1)_i - f(x_2)_i)^2, ∥f(x1)−f(x2)∥22=i=1∑d(f(x1)i−f(x2)i)2,
其中 (f(x_1)_i) 表示 (x_1) 在第 (i) 个维度的嵌入值。
对于三元组损失中的两个距离:
- (d_{AP} = |f(A) - f§|_2^2);
- (d_{AN} = |f(A) - f(N)|_2^2)。
展开形式为:
d A P = ∥ f ( A ) − f ( P ) ∥ 2 2 = ∑ i = 1 d ( f ( A ) i − f ( P ) i ) 2 , d_{AP} = \|f(A) - f(P)\|_2^2 = \sum_{i=1}^d (f(A)_i - f(P)_i)^2, dAP=∥f(A)−f(P)∥22=i=1∑d(f(A)i−f(P)i)2,
d A N = ∥ f ( A ) − f ( N ) ∥ 2 2 = ∑ i = 1 d ( f ( A ) i − f ( N ) i ) 2 . d_{AN} = \|f(A) - f(N)\|_2^2 = \sum_{i=1}^d (f(A)_i - f(N)_i)^2. dAN=∥f(A)−f(N)∥22=i=1∑d(f(A)i−f(N)i)2.
3.2 损失函数表达式的代入
将上述距离代入三元组损失的定义:
L ( A , P , N ) = max { 0 , d A P − d A N + α } . L(A, P, N) = \max\{0, d_{AP} - d_{AN} + \alpha\}. L(A,P,N)=max{0,dAP−dAN+α}.
其中:
- (d_{AP} = |f(A) - f§|_2^2);
- (d_{AN} = |f(A) - f(N)|_2^2);
对于违反约束的情况 ((d_{AP} + \alpha \geq d_{AN})),展开得:
L ( A , P , N ) = ∥ f ( A ) − f ( P ) ∥ 2 2 − ∥ f ( A ) − f ( N ) ∥ 2 2 + α . L(A, P, N) = \|f(A) - f(P)\|_2^2 - \|f(A) - f(N)\|_2^2 + \alpha. L(A,P,N)=∥f(A)−f(P)∥22−∥f(A)−f(N)∥22+α.
4. 模型训练与样本构造
4.1 三元组样本选择
三元组损失的性能依赖于训练样本的选择,通常有以下策略:
- 随机选择:随机选取 Anchor、Positive 和 Negative,但可能包含大量“易分类”的样本,对模型优化帮助不大。
- 困难样本挖掘 (Hard Negative Mining):
- Positive:选择与 Anchor 距离最大的同类样本。
- Negative:选择与 Anchor 距离最小的异类样本。
- 半困难样本挖掘 (Semi-Hard Mining):
- Negative:选择与 Anchor 距离小于 Positive 的样本,但不违反约束条件。
4.2 训练过程
-
前向传播:
- 输入样本三元组 (A, P, N);
- 使用神经网络计算嵌入特征 (f(A), f§, f(N));
- 计算损失 (L(A, P, N))。
-
反向传播:
- 计算损失对嵌入向量的梯度;
- 更新模型参数,优化嵌入网络。
5. 重要性质与参数选择
5.1 边际值 (\alpha)
- (\alpha) 控制正负样本之间的最小距离差,常取 0.1 到 1.0。
- (\alpha) 太小可能导致正负样本间距离差异不明显,影响模型判别能力。
- (\alpha) 太大会使优化问题过于严格,导致模型难以收敛。
5.2 嵌入空间维度
嵌入空间的维度 (d) 决定了模型的表征能力:
- (d) 太低可能不足以区分复杂数据。
- (d) 太高会增加计算复杂度,且可能导致过拟合。
总结
三元组损失通过直接优化样本间的几何关系,使得嵌入空间具有良好的区分能力。在实际应用中,结合困难样本挖掘和适当的边际值设定,三元组损失可以显著提升模型性能。公式化的定义与几何推导为其提供了坚实的理论基础,广泛用于深度学习领域的多种任务中。
三元组损失函数实战
根据前面我们的PCA降维数据,使用cnn网络,结合三元组损失函数,我们设计一个可以进行二分类的分类器。
代码
import numpy as np
from sklearn.datasets import fetch_openml
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler, MinMaxScaler
import torch
import torch.nn as nn
import torch.optim as optim# 加载MNIST数据集
mnist = fetch_openml('mnist_784', version=1, as_frame=False)
X, y = mnist.data, mnist.target# 选择数字0的90张图片
digit_0_indices = np.where(y == '0')[0][:90]
X_0 = X[digit_0_indices]# 选择数字1-9各10张图片
X_others = []
y_others = []
for digit in range(1, 10):indices = np.where(y == str(digit))[0][:10]X_others.append(X[indices])y_others.extend([digit] * 10)# 合并所有数据
X_selected = np.vstack([X_0] + X_others)
y_selected = np.array(['0']*90 + y_others)# 数据预处理
minmax_scaler = MinMaxScaler()
X_minmax = minmax_scaler.fit_transform(X_selected)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_minmax)# 转换为PyTorch张量
X_tensor = torch.FloatTensor(X_scaled)
y_tensor = torch.LongTensor([int(label) for label in y_selected])# 定义Triplet Loss
class TripletLoss(nn.Module):def __init__(self, margin=1.0):super(TripletLoss, self).__init__()self.margin = margindef forward(self, anchor, positive, negative):distance_positive = (anchor - positive).pow(2).sum(1)distance_negative = (anchor - negative).pow(2).sum(1)losses = torch.relu(distance_positive - distance_negative + self.margin)return losses.mean()# 生成三元组
def get_triplets(X, y):triplets = []for i in range(len(X)):anchor = X[i]anchor_label = y[i]# 获取正例(同类样本)pos_indices = torch.where(y == anchor_label)[0]pos_indices = pos_indices[pos_indices != i] # 排除anchor本身if len(pos_indices) == 0:continuepositive = X[pos_indices[torch.randint(len(pos_indices), (1,))]]# 获取负例(不同类样本)neg_indices = torch.where(y != anchor_label)[0]negative = X[neg_indices[torch.randint(len(neg_indices), (1,))]]triplets.append((anchor, positive, negative))return triplets# 训练过程
criterion = TripletLoss(margin=2.0)
embedding = nn.Linear(784, 2, bias=False) # 直接学习到2维表示
optimizer = optim.Adam(embedding.parameters(), lr=0.001)# 训练循环
n_epochs = 100
for epoch in range(n_epochs):triplets = get_triplets(X_tensor, y_tensor)epoch_loss = 0for anchor, positive, negative in triplets:optimizer.zero_grad()# 前向传播anchor_emb = embedding(anchor)positive_emb = embedding(positive)negative_emb = embedding(negative)# 计算损失loss = criterion(anchor_emb, positive_emb, negative_emb)epoch_loss += loss.item()# 反向传播loss.backward()optimizer.step()if (epoch + 1) % 10 == 0:print(f'Epoch [{epoch+1}/{n_epochs}], Loss: {epoch_loss/len(triplets):.4f}')# 使用训练好的embedding进行降维
with torch.no_grad():X_embedded = embedding(X_tensor).numpy()# 可视化结果
plt.figure(figsize=(12, 8))
plt.style.use('default')# 修改颜色方案:红色表示0,蓝色表示其他所有数字
colors = ['#FF0000', '#1f77b4']# 计算类别中心点
centers = {}
for digit in range(10):mask = y_selected == str(digit)centers[digit] = np.mean(X_embedded[mask], axis=0)# 绘制连接线
for digit in range(1, 10):mask = y_selected == str(digit)points = X_embedded[mask]center = centers[digit]for point in points:plt.plot([point[0], center[0]], [point[1], center[1]], color=colors[1], alpha=0.1)# 画数字0的连接线
mask = y_selected == '0'
points = X_embedded[mask]
center = centers[0]
for point in points:plt.plot([point[0], center[0]], [point[1], center[1]], color=colors[0], alpha=0.1)# 绘制散点
for digit in range(1, 10):mask = y_selected == str(digit)plt.scatter(X_embedded[mask, 0], X_embedded[mask, 1], c=[colors[1]], label='Other digits (1-9)' if digit == 1 else "",alpha=0.8,s=150,edgecolors='white',linewidth=1)# 绘制数字0
mask = y_selected == '0'
plt.scatter(X_embedded[mask, 0], X_embedded[mask, 1], c=[colors[0]], label='Digit 0',alpha=0.8,s=150,edgecolors='white',linewidth=1)# 绘制类别中心点
for digit in range(10):plt.scatter(centers[digit][0], centers[digit][1], c=[colors[0] if digit == 0 else colors[1]], s=300,marker='*',edgecolors='black',linewidth=1.5)plt.title('MNIST Data Triplet-Enhanced Visualization (2D)', fontsize=14, pad=20)
plt.xlabel('First Dimension', fontsize=12)
plt.ylabel('Second Dimension', fontsize=12)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=10)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('triplet_visualization.png', dpi=300, bbox_inches='tight')
plt.close()
结果分析
可以看出,将数据成功的分为了两类。
总结
本文对 PCA(主成分分析) 和 三元组损失(Triplet Loss) 的理论和实践进行了梳理和总结。通过对 PCA 的数学推导和应用实例的讲解,我们展示了其在数据降维和特征提取中的强大能力,同时结合三元组损失的几何直观和实际案例,探讨了其在构建判别性嵌入空间中的重要作用。尽管这些方法已经广泛应用于机器学习领域,但在具体实践中,仍存在如非线性数据处理或困难样本选择的挑战。相信未来这些方法的结合和改进能为数据分析和深度学习提供更多可能。
作为刚开始学习相关技术的初学者,文中内容难免存在理解或描述不够准确的地方。如果您发现任何不足或有更好的见解,欢迎随时提出并一起探讨,非常期待和大家交流学习,共同进步!