本文目录导读:

- 主成分分析(PCA)- 最常用的线性降维
- t-SNE - 非线性降维,适合可视化
- 线性判别分析(LDA)- 监督降维
- 自动编码器(Autoencoder)- 深度学习降维
- 对比不同降维方法
- 实战案例:高维数据降维
- 选择建议
我来介绍几种Python实现数据降维的常用方法,并给出具体案例:
主成分分析(PCA)- 最常用的线性降维
导入库和数据准备
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
# 加载数据
iris = load_iris()
X = iris.data
y = iris.target
feature_names = iris.feature_names
print("原始数据形状:", X.shape)
print("特征名称:", feature_names)
PCA实施
# 1. 数据标准化(PCA对尺度敏感)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 2. 应用PCA
pca = PCA()
X_pca = pca.fit_transform(X_scaled)
# 查看解释方差比
print("各主成分解释方差比:", pca.explained_variance_ratio_)
print("累计解释方差比:", np.cumsum(pca.explained_variance_ratio_))
# 可视化解释方差
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.bar(range(1, 5), pca.explained_variance_ratio_)
plt.xlabel('主成分')
plt.ylabel('解释方差比')'各主成分解释方差比')
plt.subplot(1, 2, 2)
plt.plot(range(1, 5), np.cumsum(pca.explained_variance_ratio_), 'bo-')
plt.xlabel('主成分数量')
plt.ylabel('累计解释方差比')'累计解释方差比')
plt.grid(True)
plt.tight_layout()
plt.show()
# 降维到2维
pca_2d = PCA(n_components=2)
X_pca_2d = pca_2d.fit_transform(X_scaled)
print("\n降维到2维后的数据形状:", X_pca_2d.shape)
print("2个主成分解释方差比:", pca_2d.explained_variance_ratio_)
print("累计解释方差比:", sum(pca_2d.explained_variance_ratio_))
# 可视化降维结果
plt.figure(figsize=(8, 6))
colors = ['red', 'blue', 'green']
for i, color in enumerate(colors):
plt.scatter(X_pca_2d[y == i, 0], X_pca_2d[y == i, 1],
c=color, label=iris.target_names[i])
plt.xlabel('第一主成分')
plt.ylabel('第二主成分')'PCA降维到2D')
plt.legend()
plt.grid(True)
plt.show()
t-SNE - 非线性降维,适合可视化
from sklearn.manifold import TSNE
# t-SNE降维
tsne = TSNE(n_components=2, random_state=42, perplexity=30)
X_tsne = tsne.fit_transform(X_scaled)
print("t-SNE降维后数据形状:", X_tsne.shape)
# 可视化
plt.figure(figsize=(8, 6))
for i, color in enumerate(colors):
plt.scatter(X_tsne[y == i, 0], X_tsne[y == i, 1],
c=color, label=iris.target_names[i])
plt.xlabel('t-SNE特征1')
plt.ylabel('t-SNE特征2')'t-SNE降维到2D')
plt.legend()
plt.grid(True)
plt.show()
线性判别分析(LDA)- 监督降维
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# LDA降维(注意:LDA是监督方法,需要标签)
lda = LinearDiscriminantAnalysis(n_components=2)
X_lda = lda.fit_transform(X_scaled, y)
print("LDA降维后数据形状:", X_lda.shape)
# 可视化
plt.figure(figsize=(8, 6))
for i, color in enumerate(colors):
plt.scatter(X_lda[y == i, 0], X_lda[y == i, 1],
c=color, label=iris.target_names[i])
plt.xlabel('LDA特征1')
plt.ylabel('LDA特征2')'LDA降维到2D')
plt.legend()
plt.grid(True)
plt.show()
自动编码器(Autoencoder)- 深度学习降维
from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import train_test_split
# 使用简单的神经网络实现自动编码器
class SimpleAutoencoder:
def __init__(self, input_dim, encoding_dim):
self.input_dim = input_dim
self.encoding_dim = encoding_dim
# 编码器:从输入到编码层
self.encoder = MLPRegressor(
hidden_layer_sizes=(8, encoding_dim),
activation='relu',
max_iter=1000,
random_state=42
)
# 解码器:从编码层到输出
self.decoder = MLPRegressor(
hidden_layer_sizes=(encoding_dim, 8),
activation='relu',
max_iter=1000,
random_state=42
)
self.encoded_data = None
def fit(self, X):
# 训练编码器
self.encoder.fit(X, X) # 自监督学习
# 获取编码表示
self.encoded_data = self.encoder.transform(X)
# 训练解码器
self.decoder.fit(self.encoded_data, X)
return self
def transform(self, X):
return self.encoder.transform(X)
def reconstruct(self, X):
encoded = self.encoder.transform(X)
return self.decoder.transform(encoded)
# 使用自动编码器
ae = SimpleAutoencoder(input_dim=4, encoding_dim=2)
ae.fit(X_scaled)
# 获取降维结果
X_ae = ae.transform(X_scaled)
print("自动编码器降维后数据形状:", X_ae.shape)
# 可视化
plt.figure(figsize=(8, 6))
for i, color in enumerate(colors):
plt.scatter(X_ae[y == i, 0], X_ae[y == i, 1],
c=color, label=iris.target_names[i])
plt.xlabel('编码特征1')
plt.ylabel('编码特征2')'自动编码器降维到2D')
plt.legend()
plt.grid(True)
plt.show()
对比不同降维方法
# 比较不同方法的性能
methods = {
'PCA': PCA(n_components=2),
't-SNE': TSNE(n_components=2, random_state=42),
'LDA': LinearDiscriminantAnalysis(n_components=2)
}
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
for ax, (name, method) in zip(axes, methods.items()):
if name == 'LDA':
X_transformed = method.fit_transform(X_scaled, y)
else:
X_transformed = method.fit_transform(X_scaled)
for i, color in enumerate(colors):
ax.scatter(X_transformed[y == i, 0], X_transformed[y == i, 1],
c=color, label=iris.target_names[i], alpha=0.7)
ax.set_title(f'{name}降维结果')
ax.legend()
ax.grid(True)
plt.tight_layout()
plt.show()
实战案例:高维数据降维
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
# 生成高维数据
X_high, y_high = make_classification(
n_samples=200,
n_features=50,
n_informative=10,
n_redundant=10,
random_state=42
)
print("高维数据形状:", X_high.shape)
# 标准化
scaler = StandardScaler()
X_high_scaled = scaler.fit_transform(X_high)
# 使用PCA降维
pca_high = PCA(n_components=0.95) # 保留95%的方差
X_high_pca = pca_high.fit_transform(X_high_scaled)
print("\n保留95%方差所需的主成分数:", X_high_pca.shape[1])
print("各主成分解释方差比:", pca_high.explained_variance_ratio_)
# 比较降维前后的分类性能
# 原始数据
rf_original = RandomForestClassifier(random_state=42)
score_original = cross_val_score(rf_original, X_high_scaled, y_high, cv=5)
# 降维后数据
rf_reduced = RandomForestClassifier(random_state=42)
score_reduced = cross_val_score(rf_reduced, X_high_pca, y_high, cv=5)
print("\n原始数据分类准确率: {:.2f} (+/- {:.2f})".format(
score_original.mean(), score_original.std() * 2))
print("降维后数据分类准确率: {:.2f} (+/- {:.2f})".format(
score_reduced.mean(), score_reduced.std() * 2))
- PCA:最常用的线性降维,适合数据各维度相关性较高的情况
- t-SNE:非线性降维,擅长保持数据的局部结构,主要用於可视化
- LDA:监督降维,最大化类间距离,最小化类内距离
- 自动编码器:适合复杂非线性结构的数据,但需要较多数据
选择建议
- 特征数量多且线性相关 → PCA
- 需要可视化高维数据 → t-SNE
- 有标签数据,分类任务 → LDA
- 数据复杂且数据量大 → 自动编码器
- 需要保持全局结构 → PCA
- 需要保持局部结构 → t-SNE
通过上述案例,你可以根据具体需求选择合适的降维方法,降维不仅能减少计算复杂度,还能去除噪声、可视化数据分布、提升模型性能。