Python训练营打卡DAY21

发布于:2025-05-11 ⋅ 阅读:(9) ⋅ 点赞:(0)

知识点回顾:

  1. LDA线性判别
  2. PCA主成分分析
  3. t-sne降维

还有一些其他的降维方式,也就是最重要的词向量的加工,我们未来再说

作业:

自由作业:探索下什么时候用到降维?降维的主要应用?或者让ai给你出题。可以考虑对比下在某些特定数据集上t-sne的可视化和pca可视化的区别。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")

plt.rcParams['font.sans-serif'] = ['SimHei']  
plt.rcParams['axes.unicode_minus'] = False    
data = pd.read_csv('heart.csv')
data.head()
data.isnull().sum()

from sklearn.model_selection import train_test_split
X = data.drop(['target'], axis=1)  
y = data['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
# 对训练集和测试集进行标准化
X_train = scaler.fit_transform(X_train)
X_test= scaler.transform(X_test)
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 #用于忽略警告信息
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
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) ---")
# 选择降到10维,或者你可以根据解释方差来选择,例如:
pca_expl = PCA(random_state=42)
pca_expl.fit(X_train)
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)
X_test_pca = pca_manual.transform(X_test) # 使用在训练集上fit的pca

print(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))

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 # 用于可选的可视化

# 假设 X_train, X_test, y_train, y_test 已经准备好了
# 并且你的 X_train, X_test 是DataFrame或Numpy Array

print(f"\n--- 3. t-SNE 降维 + 随机森林  ---")
print("       标准 t-SNE 主要用于可视化,直接用于分类器输入可能效果不佳。")
n_components_tsne = 2
# 对训练集进行 fit_transform
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)
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) # 注意这里是 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}")

start_time_tsne_rf = time.time()
# 步骤 3: 训练随机森林分类器
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)) #有点拉跨

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 降维 + 随机森林 ---")
n_features = X_train.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.copy() # 使用缩放后的原始特征
    X_test_lda = X_test.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.copy()
        X_test_lda = X_test.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, y_train)
        X_test_lda = lda_manual.transform(X_test)
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))

什么时候用到降维?

1. 数据维度过高(High-Dimensional Data)
  • 当特征空间非常大(如基因组数据、图像像素、文本特征等),计算复杂、存储耗费大。
  • 高维数据容易导致“维度灾难”,模型难以训练且易出现过拟合。
2. 降噪与特征提取
  • 降维可以帮助剔除不相关或冗余信息,突出主要信息,提高模型性能和稳定性。
3. 数据可视化
  • 高维数据难以理解,通过降维(如t-SNE、PCA)降低到2或3维,方便直观观察数据分布、类别关系、潜在结构。
4. 提升模型效率
  • 降低特征数,有助于减小模型复杂度、提升训练速度,减少存储需求。
5. 改善模型表现
  • 在某些情况下,降维能减少过拟合,增强模型泛化能力。

机器学习中的降维应用

  • 特征预处理:先用PCA、t-SNE等方法降低维度,再用传统分类器(SVM、随机森林等)进行学习。
  • 数据可视化:理解数据结构,定义数据的潜在类别分布。

简单总结

  • 什么时候用:高维数据、可视化、去噪、模型效率
  • 主要应用
    • 提升模型性能
    • 降低计算成本
    • 改善可视化和理解
    • 作为前置预处理,简化后续模型输入

自我反思 

 数据降维和数据筛选在特征处理如何选择,谁先谁后?

一般建议:先做特征筛选,再做降维

原因:
  1. 简化任务
    先筛选出较少的、具有较大影响力的特征,能显著减少数据的复杂度。

  2. 避免冗余信息干扰降维
    在大量无关或冗余的特征存在时,降维算法(如PCA)可能会受到干扰,导致低维表示不够聚焦于关键信息。

  3. 提高效率
    筛选后,降维的计算量大幅降低,加快分析速度。

  4. 便于理解和解释
    选择出的特征更易理解和解读。

对于需要特征对结果标签作可解释性分析的,尽量用特征筛选,特征降维处理高位复杂数据但改变特征表现形式。


网站公告

今日签到

点亮在社区的每一天
去签到