news 2026/1/23 6:10:23

Day24 常见的降维方法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day24 常见的降维方法

@浙大疏锦行

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}") 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 import matplotlib.pyplot as plt import seaborn as sns import pandas as pd # ===================== 全局绘图设置(解决中文/负号显示) ===================== plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False sns.set(style="whitegrid", font='SimHei') # 模拟数据(如果你的X_train/y_train未定义,可先运行这段;否则注释掉) # 仅用于测试代码,实际使用时替换为你的真实数据 # from sklearn.datasets import make_classification # X_train, y_train = make_classification(n_samples=1000, n_features=20, random_state=42) # X_test, y_test = make_classification(n_samples=200, n_features=20, random_state=43) 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) # 用训练集的scaler # 步骤 2: PCA降维(方差解释率分析 + 维度选择) 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}") # ===================== 可视化1:PCA方差解释率分析(修正核心错误) ===================== plt.figure(figsize=(12, 6)) # 绘制单个主成分的方差解释率(修正切片逻辑) plt.subplot(1, 2, 1) # 第一步:先取前20个主成分的方差解释率 top20_var_ratio = pca_expl.explained_variance_ratio_[:20] # 第二步:基于前20个元素的长度构造range(核心修正!) plt.bar( range(1, len(top20_var_ratio)+1), # 修正:先切片数组,再取长度 top20_var_ratio, alpha=0.7, color='#1f77b4', label='单个主成分方差解释率' ) # 仅当保留95%方差的维度≤20时,才显示这条线(避免超出x轴范围) if n_components_to_keep_95_var <= 20: plt.axvline(x=n_components_to_keep_95_var, color='red', linestyle='--', label=f'保留95%方差所需维度: {n_components_to_keep_95_var}') plt.xlabel('主成分序号') plt.ylabel('方差解释率') plt.title('PCA单个主成分方差解释率(前20个)') plt.legend() plt.xticks(range(1, len(top20_var_ratio)+1)) # 适配前20个主成分的刻度 # 绘制累计方差解释率 plt.subplot(1, 2, 2) plt.plot( range(1, len(cumsum_variance)+1), cumsum_variance, color='#ff7f0e', linewidth=2, marker='o', markersize=4, label='累计方差解释率' ) plt.axhline(y=0.95, color='red', linestyle='--', label='95%方差阈值') plt.axvline(x=n_components_to_keep_95_var, color='red', linestyle='--') plt.xlabel('主成分数量') plt.ylabel('累计方差解释率') plt.title('PCA累计方差解释率曲线') plt.legend() plt.xlim(0, min(50, len(cumsum_variance))) # 限制x轴范围,更清晰 plt.tight_layout() plt.show() # ===================== 步骤 3: 执行PCA降维(选2维用于可视化,选10维用于建模) ===================== # 1. 降维到2维(用于可视化,PCA前2维解释方差最多) pca_vis = PCA(n_components=2, random_state=42) X_train_pca_vis = pca_vis.fit_transform(X_train_scaled_pca) X_test_pca_vis = pca_vis.transform(X_test_scaled_pca) # 测试集仅transform(避免数据泄露) # 2. 降维到10维(用于后续随机森林建模) pca_model = PCA(n_components=10, random_state=42) X_train_pca = pca_model.fit_transform(X_train_scaled_pca) X_test_pca = pca_model.transform(X_test_scaled_pca) print(f"PCA降维后(2维可视化):训练集{X_train_pca_vis.shape},测试集{X_test_pca_vis.shape}") print(f"PCA降维后(10维建模):训练集{X_train_pca.shape},测试集{X_test_pca.shape}") # ===================== 可视化2:PCA降维2D散点图 ===================== def plot_pca_2d(pca_data, labels, title, ax): """绘制PCA 2维散点图""" pca_df = pd.DataFrame({ 'PCA维度1': pca_data[:, 0], 'PCA维度2': pca_data[:, 1], '类别': labels }) sns.scatterplot( data=pca_df, x='PCA维度1', y='PCA维度2', hue='类别', palette='tab10', s=30, alpha=0.8, ax=ax ) ax.set_title(title, fontsize=12, fontweight='bold') ax.set_xlabel(f'PCA第一维度(解释率{pca_vis.explained_variance_ratio_[0]:.2%})') ax.set_ylabel(f'PCA第二维度(解释率{pca_vis.explained_variance_ratio_[1]:.2%})') ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left') # 创建画布,对比训练集和测试集的PCA分布 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 7)) plot_pca_2d(X_train_pca_vis, y_train, 'PCA训练集降维分布(2维)', ax1) plot_pca_2d(X_test_pca_vis, y_test, 'PCA测试集降维分布(2维)', ax2) fig.suptitle(f'PCA降维2D可视化(前2主成分,累计解释率{pca_vis.explained_variance_ratio_.sum():.2%})', fontsize=16, fontweight='bold') plt.tight_layout() plt.show() # ===================== 后续随机森林建模 ===================== start_time_pca_rf = time.time() # 训练随机森林(用10维PCA降维数据) rf_model_pca = RandomForestClassifier(random_state=42) rf_model_pca.fit(X_train_pca, y_train) # 测试集预测 rf_pred_pca = rf_model_pca.predict(X_test_pca) end_time_pca_rf = time.time() # 输出建模结果 print(f"\nPCA降维(10维)+ 随机森林 训练+预测耗时: {end_time_pca_rf - start_time_pca_rf:.4f} 秒") print("\nPCA + 随机森林 测试集分类报告:") print(classification_report(y_test, rf_pred_pca)) print("PCA + 随机森林 测试集混淆矩阵:") print(confusion_matrix(y_test, rf_pred_pca)) PCA降维(10维)+ 随机森林 训练+预测耗时: 0.1919 秒 PCA + 随机森林 测试集分类报告: precision recall f1-score support 0 0.84 0.90 0.87 29 1 0.90 0.84 0.87 32 accuracy 0.87 61 macro avg 0.87 0.87 0.87 61 weighted avg 0.87 0.87 0.87 61 PCA + 随机森林 测试集混淆矩阵: [[26 3] [ 5 27]] from sklearn.manifold import TSNE from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix import time import numpy as np import matplotlib.pyplot as plt # 用于可选的可视化 import seaborn as sns # 用于可选的可视化 # ===================== 新增:全局绘图设置(解决中文显示+样式) ===================== plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文显示 plt.rcParams['axes.unicode_minus'] = False # 负号显示 sns.set(style="whitegrid", font='SimHei') # 假设 X_train, X_test, y_train, y_test 已经准备好了 # 并且你的 X_train, X_test 是DataFrame或Numpy Array print(f"\n--- 3. t-SNE 降维 + 随机森林 ---") print(" 标准 t-SNE 主要用于可视化,直接用于分类器输入可能效果不佳。") # 步骤 1: 特征缩放 scaler_tsne = StandardScaler() X_train_scaled_tsne = scaler_tsne.fit_transform(X_train) X_test_scaled_tsne = scaler_tsne.transform(X_test) # 使用在训练集上fit的scaler # 步骤 2: t-SNE 降维 n_components_tsne = 2 # t-SNE可视化首选2维 tsne_model_train = TSNE(n_components=n_components_tsne, perplexity=30, # 常用的困惑度值 n_iter=1000, # 足够的迭代次数 init='pca', # 使用PCA初始化,通常更稳定 learning_rate='auto', # 自动学习率 (sklearn >= 1.2) random_state=42, # 保证结果可复现 n_jobs=-1) # 使用所有CPU核心 print("正在对训练集进行 t-SNE fit_transform...") start_tsne_fit_train = time.time() X_train_tsne = tsne_model_train.fit_transform(X_train_scaled_tsne) end_tsne_fit_train = time.time() print(f"训练集 t-SNE fit_transform 完成,耗时: {end_tsne_fit_train - start_tsne_fit_train:.2f} 秒") # 对测试集进行 fit_transform tsne_model_test = TSNE(n_components=n_components_tsne, perplexity=30, n_iter=1000, init='pca', learning_rate='auto', random_state=42, n_jobs=-1) print("正在对测试集进行 t-SNE fit_transform...") start_tsne_fit_test = time.time() X_test_tsne = tsne_model_test.fit_transform(X_test_scaled_tsne) end_tsne_fit_test = time.time() print(f"测试集 t-SNE fit_transform 完成,耗时: {end_tsne_fit_test - start_tsne_fit_test:.2f} 秒") print(f"t-SNE降维后,训练集形状: {X_train_tsne.shape}, 测试集形状: {X_test_tsne.shape}") # 步骤 3: 训练随机森林分类器 start_time_tsne_rf = time.time() rf_model_tsne = RandomForestClassifier(random_state=42) rf_model_tsne.fit(X_train_tsne, y_train) # 步骤 4: 在测试集上预测 rf_pred_tsne_manual = rf_model_tsne.predict(X_test_tsne) end_time_tsne_rf = time.time() print(f"t-SNE降维数据上,随机森林训练与预测耗时: {end_time_tsne_rf - start_time_tsne_rf:.4f} 秒") total_tsne_time = (end_tsne_fit_train - start_tsne_fit_train) + \ (end_tsne_fit_test - start_tsne_fit_test) + \ (end_time_tsne_rf - start_time_tsne_rf) print(f"t-SNE 总耗时 (包括两次fit_transform和RF): {total_tsne_time:.2f} 秒") print("\n手动 t-SNE + 随机森林 在测试集上的分类报告:") print(classification_report(y_test, rf_pred_tsne_manual)) print("手动 t-SNE + 随机森林 在测试集上的混淆矩阵:") print(confusion_matrix(y_test, rf_pred_tsne_manual)) # ===================== 核心新增:t-SNE 可视化 ===================== def plot_tsne_2d(tsne_data, labels, title, ax): """ 绘制2维t-SNE散点图 参数: tsne_data: t-SNE降维后的数组 (n_samples, 2) labels: 样本的类别标签 title: 图表标题 ax: 子图对象 """ # 将数据转为DataFrame,方便seaborn绘图 tsne_df = pd.DataFrame({ 't-SNE维度1': tsne_data[:, 0], 't-SNE维度2': tsne_data[:, 1], '类别': labels }) # 绘制散点图,不同类别用不同颜色 sns.scatterplot( data=tsne_df, x='t-SNE维度1', y='t-SNE维度2', hue='类别', palette='tab10', # 多类别配色方案 s=30, # 点的大小 alpha=0.8, # 透明度(避免点重叠遮挡) ax=ax ) ax.set_title(title, fontsize=12, fontweight='bold') ax.set_xlabel('t-SNE 第一维度', fontsize=10) ax.set_ylabel('t-SNE 第二维度', fontsize=10) ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left') # 图例放在图外侧,避免遮挡 # 创建画布,绘制训练集+测试集的t-SNE可视化 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 7)) # 绘制训练集t-SNE分布 plot_tsne_2d(X_train_tsne, y_train, f't-SNE训练集降维分布 (perplexity=30)', ax1) # 绘制测试集t-SNE分布(区分真实类别 vs 预测类别,可选二选一) # 方式1:测试集真实类别分布 plot_tsne_2d(X_test_tsne, y_test, f't-SNE测试集真实类别分布', ax2) # 方式2:测试集预测类别分布(如需对比,可替换ax2的绘图逻辑) # tsne_test_pred_df = pd.DataFrame({ # 't-SNE维度1': X_test_tsne[:, 0], # 't-SNE维度2': X_test_tsne[:, 1], # '真实类别': y_test, # '预测类别': rf_pred_tsne_manual # }) # sns.scatterplot(data=tsne_test_pred_df, x='t-SNE维度1', y='t-SNE维度2', # hue='真实类别', style='预测类别', s=30, alpha=0.8, ax=ax2) # ax2.set_title('t-SNE测试集真实类别(颜色) vs 预测类别(形状)', fontsize=12, fontweight='bold') # 整体标题 fig.suptitle(f't-SNE降维可视化(2维)', fontsize=16, fontweight='bold') plt.tight_layout() # 自动调整布局 plt.show() --- 3. t-SNE 降维 + 随机森林 --- 标准 t-SNE 主要用于可视化,直接用于分类器输入可能效果不佳。 正在对训练集进行 t-SNE fit_transform... 训练集 t-SNE fit_transform 完成,耗时: 0.79 秒 正在对测试集进行 t-SNE fit_transform... 测试集 t-SNE fit_transform 完成,耗时: 0.14 秒 t-SNE降维后,训练集形状: (242, 2), 测试集形状: (61, 2) t-SNE降维数据上,随机森林训练与预测耗时: 0.1832 秒 t-SNE 总耗时 (包括两次fit_transform和RF): 1.12 秒 手动 t-SNE + 随机森林 在测试集上的分类报告: precision recall f1-score support 0 0.11 0.10 0.11 29 1 0.21 0.22 0.22 32 accuracy 0.16 61 macro avg 0.16 0.16 0.16 61 weighted avg 0.16 0.16 0.16 61 手动 t-SNE + 随机森林 在测试集上的混淆矩阵: [[ 3 26] [25 7]] from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix import time import numpy as np # 假设你已经导入了 matplotlib 和 seaborn 用于绘图 (如果需要) import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 如果需要3D绘图 import seaborn as sns print(f"\n--- 4. LDA 降维 + 随机森林 ---") # 步骤 1: 特征缩放 scaler_lda = StandardScaler() X_train_scaled_lda = scaler_lda.fit_transform(X_train) X_test_scaled_lda = scaler_lda.transform(X_test) # 使用在训练集上fit的scaler # 步骤 2: LDA 降维 n_features = X_train_scaled_lda.shape[1] if hasattr(y_train, 'nunique'): n_classes = y_train.nunique() elif isinstance(y_train, np.ndarray): n_classes = len(np.unique(y_train)) else: n_classes = len(set(y_train)) max_lda_components = min(n_features, n_classes - 1) # 设置目标降维维度 n_components_lda_target = 10 if max_lda_components < 1: print(f"LDA 不适用,因为类别数 ({n_classes})太少,无法产生至少1个判别组件。") X_train_lda = X_train_scaled_lda.copy() # 使用缩放后的原始特征 X_test_lda = X_test_scaled_lda.copy() # 使用缩放后的原始特征 actual_n_components_lda = n_features print("将使用缩放后的原始特征进行后续操作。") else: # 实际使用的组件数不能超过LDA的上限,也不能超过我们的目标(如果目标更小) actual_n_components_lda = min(n_components_lda_target, max_lda_components) if actual_n_components_lda < 1: # 这种情况理论上不会发生,因为上面已经检查了 max_lda_components < 1 print(f"计算得到的实际LDA组件数 ({actual_n_components_lda}) 小于1,LDA不适用。") X_train_lda = X_train_scaled_lda.copy() X_test_lda = X_test_scaled_lda.copy() actual_n_components_lda = n_features print("将使用缩放后的原始特征进行后续操作。") else: print(f"原始特征数: {n_features}, 类别数: {n_classes}") print(f"LDA 最多可降至 {max_lda_components} 维。") print(f"目标降维维度: {n_components_lda_target} 维。") print(f"本次 LDA 将实际降至 {actual_n_components_lda} 维。") lda_manual = LinearDiscriminantAnalysis(n_components=actual_n_components_lda, solver='svd') X_train_lda = lda_manual.fit_transform(X_train_scaled_lda, y_train) X_test_lda = lda_manual.transform(X_test_scaled_lda) print(f"LDA降维后,训练集形状: {X_train_lda.shape}, 测试集形状: {X_test_lda.shape}") start_time_lda_rf = time.time() # 步骤 3: 训练随机森林分类器 rf_model_lda = RandomForestClassifier(random_state=42) rf_model_lda.fit(X_train_lda, y_train) # 步骤 4: 在测试集上预测 rf_pred_lda_manual = rf_model_lda.predict(X_test_lda) end_time_lda_rf = time.time() print(f"LDA降维数据上,随机森林训练与预测耗时: {end_time_lda_rf - start_time_lda_rf:.4f} 秒") print("\n手动 LDA + 随机森林 在测试集上的分类报告:") print(classification_report(y_test, rf_pred_lda_manual)) print("手动 LDA + 随机森林 在测试集上的混淆矩阵:") print(confusion_matrix(y_test, rf_pred_lda_manual)) --- 4. LDA 降维 + 随机森林 --- 原始特征数: 23, 类别数: 2 LDA 最多可降至 1 维。 目标降维维度: 10 维。 本次 LDA 将实际降至 1 维。 LDA降维后,训练集形状: (242, 1), 测试集形状: (61, 1) LDA降维数据上,随机森林训练与预测耗时: 0.1742 秒 手动 LDA + 随机森林 在测试集上的分类报告: precision recall f1-score support 0 0.72 0.90 0.80 29 1 0.88 0.69 0.77 32 accuracy 0.79 61 macro avg 0.80 0.79 0.79 61 weighted avg 0.80 0.79 0.79 61 手动 LDA + 随机森林 在测试集上的混淆矩阵: [[26 3]
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/25 12:31:15

Pock免费快捷键大全:解锁MacBook Touch Bar的终极生产力指南

Pock免费快捷键大全&#xff1a;解锁MacBook Touch Bar的终极生产力指南 【免费下载链接】pock Widgets manager for MacBook Touch Bar 项目地址: https://gitcode.com/gh_mirrors/po/pock 想要让MacBook Touch Bar真正发挥其潜力吗&#xff1f;Pock作为一款完全免费的…

作者头像 李华
网站建设 2026/1/17 11:50:59

Oblivion Desktop跨平台通知系统:从技术挑战到优雅解决方案

在网络工具开发过程中&#xff0c;开发者面临着一个关键挑战&#xff1a;如何在复杂的网络环境下为用户提供及时、准确且不干扰的操作反馈。Oblivion Desktop作为一款基于Electron的跨平台桌面应用&#xff0c;通过创新的通知系统架构&#xff0c;成功解决了这一难题。 【免费下…

作者头像 李华
网站建设 2026/1/20 9:41:59

IO方面学习总结

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、异常1.异常分类2.异常流程3.异常的作用4.异常的处理方式JVM默认处理方案5.自己处理捕获异常6.抛出异常二、方法引用1.要求&#xff1a;2.方法引用的分类三、…

作者头像 李华
网站建设 2026/1/20 11:07:09

Kronos金融预测模型三版本深度评测:从3.2M到86M参数的性能跃迁

Kronos金融预测模型三版本深度评测&#xff1a;从3.2M到86M参数的性能跃迁 【免费下载链接】Kronos Kronos: A Foundation Model for the Language of Financial Markets 项目地址: https://gitcode.com/GitHub_Trending/kronos14/Kronos 在量化投资领域&#xff0c;模型…

作者头像 李华
网站建设 2026/1/22 14:34:54

清华virtuoso简明教程PDF资源完整指南

探索virtuoso软件的奥秘&#xff0c;从这里开始&#xff01;《清华virtuoso简明教程》PDF文档为您呈现&#xff0c;助您轻松掌握软件的核心操作与技巧。无论您是初学者还是进阶用户&#xff0c;这份详实而清晰的教程都将成为您学习道路上的得力助手。 【免费下载链接】清华virt…

作者头像 李华
网站建设 2025/12/26 12:13:11

Visual Basic 鼠标事件

除了常用的Click和DblClick事件之外&#xff0c;有些程序还需要对鼠标指针的位置和状态变化做出响应&#xff0c;因此需要使用鼠标事件MouseUp&#xff0c;MouseDown和MouseMove。当鼠标指针位于窗体上方时&#xff0c;窗体将识别鼠标事件。当鼠标指针在控件上方时&#xff0c;…

作者头像 李华