打卡第二十二天
知识点回顾:
- LDA线性判别
- PCA主成分分析
- t-SNE降维
-
还有一些其他的降维方式,也就是最重要的词向量的加工,我们未来再说。
作业: 自由作业:探索下什么时候用到降维?降维的主要应用?或者让AI给你出题,群里的同学互相学习下。可以考虑对比下在某些特定数据集上t-SNE的可视化和PCA可视化的区别。
什么时候用到降维?降维的主要应用?
数据集类型
降维方法适用于多种类型的数据集,尤其是高维数据集。常见的数据集类型包括:
- 图像数据:图像数据通常具有高维度,每个像素点可以视为一个特征。降维可以用于图像压缩、特征提取等。
- 文本数据:文本数据经过向量化后(如TF-IDF、词袋模型)往往具有高维稀疏特征,降维可以用于文本分类、信息检索等。
- 基因数据:基因表达数据通常具有大量特征(基因),而降维可以帮助识别关键基因或模式。
- 金融数据:金融市场数据可能包含大量指标和时间序列,降维可以用于风险管理、投资组合优化等。
降维的应用场景
降维技术广泛应用于各个领域,主要目的是简化数据、减少计算复杂度、提高模型性能以及可视化高维数据。
- 数据可视化:降维可以将高维数据投影到二维或三维空间,便于直观展示和探索数据分布。
- 特征选择与提取:降维可以去除冗余特征,保留重要特征,提升机器学习模型的效率和精度。
- 图像处理:在图像识别和计算机视觉中,降维用于特征提取和图像压缩。
- 自然语言处理:文本数据降维可以用于主题建模、情感分析等任务。
- 生物信息学:降维用于分析基因表达数据,识别疾病相关的生物标志物。
- 推荐系统:降维可以简化用户-物品交互矩阵,提高推荐算法的性能。
常用的降维方法
常用的降维方法包括线性降维和非线性降维技术。
- 主成分分析(PCA):一种线性降维方法,通过正交变换将数据投影到低维空间。
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_reduced = pca.fit_transform(X)
- t-SNE:一种非线性降维方法,特别适用于高维数据的可视化。
from sklearn.manifold import TSNE
tsne = TSNE(n_components=2)
X_embedded = tsne.fit_transform(X)
- 线性判别分析(LDA):一种监督学习的降维方法,适用于分类任务。
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis(n_components=2)
X_reduced = lda.fit_transform(X, y)
- 自编码器(Autoencoder):一种基于神经网络的非线性降维方法。
from keras.layers import Input, Dense
from keras.models import Modelinput_layer = Input(shape=(input_dim,))
encoded = Dense(encoding_dim, activation='relu')(input_layer)
decoded = Dense(input_dim, activation='sigmoid')(encoded)
autoencoder = Model(input_layer, decoded)
autoencoder.compile(optimizer='adam', loss='binary_crossentropy')
autoencoder.fit(X, X, epochs=50, batch_size=256, shuffle=True)
降维方法的选择取决于具体任务和数据集特性,合理使用降维技术可以显著提升数据分析的效率和效果。
t-SNE降维和PCA降维的精度区别
我尝试了心脏病数据集,很显然心脏病数据集并不适应于t-sne降维
首先默认参数随机森林模型
import pandas as pd
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
data = pd.read_csv(r'C:\Users\许兰\Desktop\打卡文件\python60-days-challenge-master\heart.csv')
import warnings
warnings.filterwarnings("ignore")
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统常用黑体字体
plt.rcParams['axes.unicode_minus'] = False
discrete_features = data.select_dtypes(include=['object']).columns.tolist()
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)import numpy as np # 引入 numpy 用于计算平均值等
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold, cross_validate # 引入分层 K 折和交叉验证工具
from sklearn.metrics import make_scorer, accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report
import time
import warnings
warnings.filterwarnings("ignore")
print("--- 1. 默认参数随机森林 (训练集 -> 测试集) ---")
start_time = time.time()
rf_model_default = RandomForestClassifier(random_state=42)
rf_model_default.fit(x_train, y_train)
rf_pred_default = rf_model_default.predict(x_test)
end_time = time.time()
print(f"默认模型训练与预测耗时: {end_time - start_time:.4f} 秒")
print("\n默认随机森林 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred_default))
print("默认随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred_default))
print("-" * 50)
pca降维+随机森林
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}")n_components_pca = 12
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))
t-sne降维+随机森林
rom 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 Arrayprint(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 降维
# 我们将降维到与PCA相同的维度(例如10维)或者一个适合分类的较低维度。
# t-SNE通常用于2D/3D可视化,但也可以降到更高维度。
# 然而,降到与PCA一样的维度(比如10维)对于t-SNE来说可能不是其优势所在,
# 并且计算成本会显著增加,因为高维t-SNE的优化更困难。
# 为了与PCA的 n_components=10 对比,我们这里也尝试降到10维。
# 但请注意,这可能非常耗时,且效果不一定好。
# 通常如果用t-SNE做分类的预处理(不常见),可能会选择非常低的维度(如2或3)。# n_components_tsne = 10 # 与PCA的例子保持一致,但计算量会很大
n_components_tsne = 3 # 更典型的t-SNE用于分类的维度,如果想快速看到结果# 如果你想严格对比PCA的10维,可以将这里改为10,但会很慢# 对训练集进行 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_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) # 注意这里是 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))
@浙大疏锦行