DAY 21 常见的降维算法
知识点回顾:
- LDA线性判别
- PCA主成分分析
- t-sne降维
# 先运行之前预处理好的代码
import pandas as pd
import pandas as pd #用于数据处理和分析,可处理表格数据。
import numpy as np #用于数值计算,提供了高效的数组操作。
import matplotlib.pyplot as plt #用于绘制各种类型的图表
import seaborn as sns #基于matplotlib的高级绘图库,能绘制更美观的统计图形。
import warnings
warnings.filterwarnings("ignore")# 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统常用黑体字体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
data = pd.read_csv('data.csv') #读取数据# 先筛选字符串变量
discrete_features = data.select_dtypes(include=['object']).columns.tolist()
# Home Ownership 标签编码
home_ownership_mapping = {'Own Home': 1,'Rent': 2,'Have Mortgage': 3,'Home Mortgage': 4
}
data['Home Ownership'] = data['Home Ownership'].map(home_ownership_mapping)# Years in current job 标签编码
years_in_job_mapping = {'< 1 year': 1,'1 year': 2,'2 years': 3,'3 years': 4,'4 years': 5,'5 years': 6,'6 years': 7,'7 years': 8,'8 years': 9,'9 years': 10,'10+ years': 11
}
data['Years in current job'] = data['Years in current job'].map(years_in_job_mapping)# Purpose 独热编码,记得需要将bool类型转换为数值
data = pd.get_dummies(data, columns=['Purpose'])
data2 = pd.read_csv("data.csv") # 重新读取数据,用来做列名对比
list_final = [] # 新建一个空列表,用于存放独热编码后新增的特征名
for i in data.columns:if i not in data2.columns:list_final.append(i) # 这里打印出来的就是独热编码后的特征名
for i in list_final:data[i] = data[i].astype(int) # 这里的i就是独热编码后的特征名# Term 0 - 1 映射
term_mapping = {'Short Term': 0,'Long Term': 1
}
data['Term'] = data['Term'].map(term_mapping)
data.rename(columns={'Term': 'Long Term'}, inplace=True) # 重命名列
continuous_features = data.select_dtypes(include=['int64', 'float64']).columns.tolist() #把筛选出来的列名转换成列表# 连续特征用中位数补全
for feature in continuous_features: mode_value = data[feature].mode()[0] #获取该列的众数。data[feature].fillna(mode_value, inplace=True) #用众数填充该列的缺失值,inplace=True表示直接在原数据上修改。# 最开始也说了 很多调参函数自带交叉验证,甚至是必选的参数,你如果想要不交叉反而实现起来会麻烦很多
# 所以这里我们还是只划分一次数据集data.drop(columns=['Id'], inplace=True) # 删除 Loan ID 列
data.info() # 查看数据集的信息,包括数据类型和缺失值情况
特征降维(Feature Dimensionality Reduction)是机器学习与数据分析中的关键预处理技术,旨在通过减少数据集的特征数量(维度),在保留核心信息的前提下简化数据结构。以下是其核心要点:
🧠 一、定义与目的
- 核心概念
特征降维是将高维数据(如数千个特征)映射到低维空间(如几十个特征)的过程。例如,图像数据从256×256像素(65536维)压缩至几十维,同时保留关键特征。其核心目标包括:- 避免维数灾难:高维数据导致计算复杂、距离度量失效。
- 去除噪声与冗余:剔除无关或弱相关特征,提升数据质量。
- 提升效率与可解释性:降低计算成本,加速模型训练,并便于数据可视化。
⚙️ 二、主要方法分类
特征降维技术可分为两类策略:
-
特征选择(Feature Selection)
- 原理:从原始特征中筛选最具代表性的子集(如通过统计指标或模型评估)。
- 常用方法:
- 过滤法(Filter):基于方差、相关系数等(如低方差过滤法)。
- 嵌入法(Embedded):结合模型训练自动选择特征(如L1正则化、决策树)。
- 包裹法(Wrapper):通过迭代评估特征子集对模型性能的影响(如递归特征消除)。
-
特征提取(Feature Extraction)
- 原理:通过数学变换将原始特征投影到新空间,生成低维新特征。
- 典型算法:
- 线性方法:主成分分析(PCA)、线性判别分析(LDA)。
- 非线性方法:t-SNE、UMAP(适用于复杂流形结构数据)。
- 深度学习驱动:自动编码器(Autoencoder)。
🌐 三、应用场景
特征降维广泛应用于以下领域:
- 图像处理:PCA用于人脸识别(Eigenfaces),压缩图像数据。
- 生物医学:基因表达数据分析中,t-SNE可视化单细胞RNA测序结果。
- 自然语言处理:潜在语义分析(LSA)压缩文本特征,提取主题。
- 金融风控:PCA构建资产收益率的主成分因子,降低模型复杂度。
- 工业监控:传感器数据降维后实时检测设备异常。
📊 四、技术优势与挑战
优势 | 挑战 |
---|---|
✔️ 提升模型泛化能力与效率 | ❗ 信息损失风险(需平衡维度与信息保留) |
✔️ 增强数据可视化效果(如2D/3D投影) | ❗ 非线性数据需复杂方法(如t-SNE计算成本高) |
✔️ 降低存储与传输开销 | ❗ 方法选择依赖问题背景(如LDA需类别标签) |
💎 总结
特征降维通过特征选择或特征提取,解决高维数据的计算与信息冗余问题,是提升机器学习模型性能的关键步骤。实际应用中需结合数据特性(如线性/非线性、有无标签)选择合适方法,并评估降维后信息的完整性。
from sklearn.model_selection import train_test_split
X = data.drop(['Credit Default'], axis=1) # 特征,axis=1表示按列删除
y = data['Credit Default'] # 标签from sklearn.model_selection import train_test_split
X = data.drop(['Credit Default'], axis=1) # 特征,axis=1表示按列删除
y = data['Credit Default'] # 标签
# 按照8:2划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 80%训练集,20%测试集
from sklearn.ensemble import RandomForestClassifier #随机森林分类器from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score # 用于评估分类器性能的指标
from sklearn.metrics import classification_report, confusion_matrix #用于生成分类报告和混淆矩阵
import warnings #用于忽略警告信息
warnings.filterwarnings("ignore") # 忽略所有警告信息
# --- 1. 默认参数的随机森林 ---
# 评估基准模型,这里确实不需要验证集
print("--- 1. 默认参数随机森林 (训练集 -> 测试集) ---")
import time # 这里介绍一个新的库,time库,主要用于时间相关的操作,因为调参需要很长时间,记录下会帮助后人知道大概的时长
start_time = time.time() # 记录开始时间
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train) # 在训练集上训练
rf_pred = rf_model.predict(X_test) # 在测试集上预测
end_time = time.time() # 记录结束时间print(f"训练与预测耗时: {end_time - start_time:.4f} 秒")
print("\n默认随机森林 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred))
print("默认随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred))
# 确保这些库已导入,你的原始代码中可能已经包含了部分
import time
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler # 特征缩放
from sklearn.decomposition import PCA # 主成分分析
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA # 线性判别分析
# UMAP 需要单独安装: pip install umap-learn
import umap # 如果安装了 umap-learn,可以这样导入from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix# 你的 X_train, X_test, y_train, y_test 应该已经根据你的代码准备好了
# 我们假设你的随机森林模型参数与基准模型一致,以便比较降维效果
# rf_params = {'random_state': 42} # 如果你的基准模型有其他参数,也在这里定义
# 为了直接比较,我们使用默认的 RandomForestClassifier 参数,除了 random_state
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
import time
import numpy as np # 确保numpy导入# 假设 X_train, X_test, y_train, y_test 已经准备好了print(f"\n--- 2. PCA 降维 + 随机森林 (不使用 Pipeline) ---")# 步骤 1: 特征缩放
scaler_pca = StandardScaler()
X_train_scaled_pca = scaler_pca.fit_transform(X_train)
X_test_scaled_pca = scaler_pca.transform(X_test) # 使用在训练集上fit的scaler# 步骤 2: PCA降维
# 选择降到10维,或者你可以根据解释方差来选择,例如:
pca_expl = PCA(random_state=42)
pca_expl.fit(X_train_scaled_pca)
cumsum_variance = np.cumsum(pca_expl.explained_variance_ratio_)
n_components_to_keep_95_var = np.argmax(cumsum_variance >= 0.95) + 1
print(f"为了保留95%的方差,需要的主成分数量: {n_components_to_keep_95_var}")
# 我们测试下降低到10维的效果
n_components_pca = 10
pca_manual = PCA(n_components=n_components_pca, random_state=42)X_train_pca = pca_manual.fit_transform(X_train_scaled_pca)
X_test_pca = pca_manual.transform(X_test_scaled_pca) # 使用在训练集上fit的pcaprint(f"PCA降维后,训练集形状: {X_train_pca.shape}, 测试集形状: {X_test_pca.shape}")
start_time_pca_manual = time.time()
# 步骤 3: 训练随机森林分类器
rf_model_pca = RandomForestClassifier(random_state=42)
rf_model_pca.fit(X_train_pca, y_train)# 步骤 4: 在测试集上预测
rf_pred_pca_manual = rf_model_pca.predict(X_test_pca)
end_time_pca_manual = time.time()print(f"手动PCA降维后,训练与预测耗时: {end_time_pca_manual - start_time_pca_manual:.4f} 秒")print("\n手动 PCA + 随机森林 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred_pca_manual))
print("手动 PCA + 随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred_pca_manual))