一、降维的概念
降维是一种减少数据集中特征数量 的技术,目的是减少计算复杂性,同时尽量保留原始数据的重要信息。降维通常用于高维数据集,其中可能包含成千上万个特征。降维可以分为两类:一类是特征选择,指从现有特征中选择一个子集的过程,不创建新的特征;另一类是特征提取,通过转换原始特征空间以生成新的特征表示。本文主要介绍后者。
二、常见的降维方法
1、主成分分析(Principal Component Analysis, PCA)
主成分分析(Principal Component Analysis,PCA)是一种统计方法,用于通过正交变换将可能相关的变量转换为一组值数量更少的线性不相关变量(称为主成分)。PCA的目的是找到数据中的主要变化方向,并将数据投影到这些方向上,以保留最多的数据方差 。这些方向被称为主成分,它们是原始数据集的线性组合 。设有一个数据集X,其中是n个样本中的一个,p是特征(变量)的数量。PCA的计算如下:
(1)中心化数据
其中,是X的列均值。
(2)计算协方差矩阵
(3)求解特征值和特征向量
其中是特征值,是对应的特征向量。
(4)选择主成分
选择k个最大的特征值对应的特征向量,构成矩阵V。
(5)构造新特征空间
其中,Y就是降维后的新数据。
python
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_wine
# 加载红酒数据集
data = load_wine()
X = data.data
y = data.target
# 数据预处理,标准化特征
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 初始化PCA,设置降维后的维度,例如降至2维
pca = PCA(n_components=2)
# 训练PCA模型并降维
X_pca = pca.fit_transform(X_scaled)
# 查看降维后的数据
print("降维后的数据:")
print(X_pca)
# 还原数据可以使用inverse_transform方法
X_reconstructed = pca.inverse_transform(X_pca)
# 查看主成分解释的方差比例
print("主成分解释的方差比例:")
print(pca.explained_variance_ratio_)
# 可视化降维后的数据
import matplotlib.pyplot as plt
colors = ['red', 'green', 'blue']
markers = ['s', 'x', 'o']
for color, marker, i in zip(colors, markers, [0, 1, 2]):
plt.scatter(X_pca[y == i, 0], X_pca[y == i, 1], c=color, label=data.target_names[i], marker=marker)
plt.title('PCA of Wine Dataset')
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.legend()
plt.show()
2、线性判别分析(Linear Discriminant Analysis, LDA)
线性判别分析(Linear Discriminant Analysis,简称LDA)是一种有监督学习的降维技术**(主题模型也有个叫LDA的,全称是隐含狄利克雷分布,注意区分!)** ,它的目标是寻找一个特征的线性组合 ,以最大化类间的差异和最小化类内的差异。LDA的原理基于寻找最佳的投影方向,使得在这个方向上,不同类别的数据点尽可能地分离(最大化类间距离),同时同类数据点尽可能地靠近(最小化类内距离)。
给定一个数据集,其中包含k个类别,每个类别j有个样本,是类别j的样本均值向量,是类别j的协方差矩阵。LDA试图找到一个线性组合的方向w,以最大化类间散度矩阵与类内散度矩阵的比例:
其中,是全局样本均值,是类别j中的样本数量,是类别j中的样本集合。优化目标可以表示为:
可以通过求解的最大特征值对应的特征向量来找到w。
python
import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_wine
import matplotlib.pyplot as plt
# 加载红酒数据集
wine = load_wine()
X = wine.data
y = wine.target
# 数据预处理,标准化特征
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 初始化LDA,设置降维后的维度,例如降至2维
lda = LDA(n_components=2)
# 训练LDA模型并降维
X_lda = lda.fit_transform(X_scaled, y)
# 查看降维后的数据
print("降维后的数据:")
print(X_lda)
# 还原数据可以使用inverse_transform方法
X_reconstructed = lda.inverse_transform(X_lda)
# 可视化降维后的数据
colors = ['red', 'green', 'blue']
markers = ['s', 'x', 'o']
plt.figure()
for i, color, marker in zip(range(3), colors, markers):
plt.scatter(X_lda[y == i, 0], X_lda[y == i, 1], c=color, label=wine.target_names[i], marker=marker)
plt.title('LDA of Wine Dataset')
plt.xlabel('LD1')
plt.ylabel('LD2')
plt.legend()
plt.show()
3、t-分布随机邻域嵌入(t-SNE)
t-SNE(t-distributed Stochastic Neighbor Embedding)是一种非线性降维算法,其工作原理主要包括以下几个步骤:
(1)计算高维空间的概率分布
首先,t-SNE通过高斯分布(正态分布)计算高维空间中数据点之间的相似度,使用条件概率来表达点与点之间的相似度。
(2)映射到低维空间:
其次,t-SNE通过优化一个目标函数,将高维空间中的数据点映射到低维空间(通常是2维或3维),同时尝试保持高维空间中的概率分布与低维空间中的概率分布尽可能相似。
(3)优化目标函数
t-SNE使用**KL散度(Kullback-Leibler divergence)**作为目标函数来度量高维和低维空间的概率分布之间的差异,并通过梯度下降法来最小化这个差异。目标函数定义如下:
其中,是高维空间中数据点和之间的条件概率。是低维空间中数据点和之间的条件概率。
(4)使用t分布
在低维空间中,t-SNE使用t分布而不是高斯分布来计算点之间的相似度,这有助于解决数据点在低维空间中的拥挤问题。
python
from sklearn.manifold import TSNE
from sklearn.datasets import load_wine
import matplotlib.pyplot as plt
# 加载红酒数据集
wine = load_wine()
X = wine.data
y = wine.target
# 初始化t-SNE模型,设置降维后的维度为2
tsne = TSNE(n_components=2, random_state=0)
# 训练t-SNE模型并降维
X_tsne = tsne.fit_transform(X)
# 可视化降维后的数据
plt.figure(figsize=(8, 6))
for i in range(3):
plt.scatter(X_tsne[y == i, 0], X_tsne[y == i, 1], label=wine.target_names[i])
plt.legend()
plt.title('t-SNE projection of Wine dataset')
plt.xlabel('t-SNE feature 1')
plt.ylabel('t-SNE feature 2')
plt.show()
4、奇异值分解(Singular Value Decomposition, SVD)
奇异值分解(Singular Value Decomposition, SVD)是一种的矩阵分解方法。SVD通过保留最大的几个奇异值(对应于矩阵Σ的非零元素)及其对应的左右奇异向量来实现。这些奇异值代表了数据中最重要的方差,而舍弃较小的奇异值则相当于去除了噪声和冗余信息。SVD能够将任意一个矩阵分解为三个特定的矩阵,其数学表达式定义为:
其中:
- A是一个m×n的矩阵。
- U是一个m×m的正交矩阵,其列向量称为左奇异向量。
- Σ(通常用大写的希腊字母Σ表示)是一个m×n的对角矩阵,对角线上的元素称为奇异值,按降序排列。
- 是一个n×n矩阵的转置,V的列向量称为右奇异向量,也是一个正交矩阵。
python
import numpy as np
from sklearn.datasets import load_wine
from sklearn.decomposition import TruncatedSVD
import matplotlib.pyplot as plt
# 加载红酒数据集
wine = load_wine()
X = wine.data
y = wine.target
# 初始化TruncatedSVD模型,设置降维后的维度为2
svd = TruncatedSVD(n_components=2)
# 训练SVD模型并降维
X_svd = svd.fit_transform(X)
# 可视化降维后的数据
plt.figure(figsize=(8, 6))
for i in range(3):
plt.scatter(X_svd[y == i, 0], X_svd[y == i, 1], label=wine.target_names[i])
plt.legend()
plt.title('SVD projection of Wine dataset')
plt.xlabel('SVD feature 1')
plt.ylabel('SVD feature 2')
plt.show()
5、umap(Uniform Manifold Approximation and Projection)
UMAP(Uniform Manifold Approximation and Projection)是一种用于降维的非线性技术,它适合于高维数据的可视化。UMAP的目标是在低维空间中保持高维空间中数据点的局部和全局结构。UMAP的数学公式涉及到构建一个高维的模糊简单复形(fuzzy simplicial complex),然后通过优化过程找到其在低维空间的最佳表示。这个过程可以表示为:
(1)构造高维图
(2)计算边权重
其中,是点和之间的距离,是基于邻近点的距离确定的尺度参数。
(3)优化低维嵌入
其中和是低维空间中的点,q是低维空间中的概率分布。
(注意umap库安装指令应该写:pip install umap-learn)
python
import umap
from sklearn.datasets import load_wine
import matplotlib.pyplot as plt
# 加载红酒数据集
wine = load_wine()
X = wine.data
y = wine.target
# 初始化UMAP对象
reducer = umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, random_state=42)
# 执行降维
embedding = reducer.fit_transform(X)
# 可视化降维结果
plt.figure(figsize=(10, 8))
plt.scatter(embedding[:, 0], embedding[:, 1], c=y, cmap='Spectral', s=5)
plt.colorbar()
plt.title('UMAP projection of Wine dataset')
plt.xlabel('Component 1')
plt.ylabel('Component 2')
plt.show()
三、总结
降维方法在探索性数据分析阶段非常有用,不论是通过降维可视化查看数据分布,还是可视化给老板看。不同的降维方法也有其适用场景,对于NLP任务,笔者常用的是umap降维,经验上看它在文本表示降维方面表现更好,以及它速度较快,比其他方法效率高不少;而对于数值型数据挖掘,PCA、t-SNE都是不错的方法。