机器学习基础教程第三章 降维、特征提取与流形学习

您所在的位置:网站首页 张量数据的特征提取与分类实验报告 机器学习基础教程第三章 降维、特征提取与流形学习

机器学习基础教程第三章 降维、特征提取与流形学习

2024-07-10 02:26| 来源: 网络整理| 查看: 265

3.4降维、特征提取与流形学习

3.4.1主成分分析

将 PCA 应用于 cancer 数据集并可视化 PCA 最常见的应用之一就是将高维数据集可视化。正如第 1 章中所说,对于有两个以上特 征的数据,很难绘制散点图。对于 Iris(鸢尾花)数据集,我们可以创建散点图矩阵(见 第 1 章图 1-3),通过展示特征所有可能的两两组合来展示数据的局部图像。但如果我们想 要查看乳腺癌数据集,即便用散点图矩阵也很困难。这个数据集包含 30 个特征,这就导 致需要绘制 30 * 14 = 420 张散点图!我们永远不可能仔细观察所有这些图像,更不用说试 图理解它们了。 不过我们可以使用一种更简单的可视化方法——对每个特征分别计算两个类别(良性肿瘤 和恶性肿瘤)的直方图。 from sklearn.datasets import load_digits import matplotlib.pyplot as plt from sklearn.decomposition import PCA import numpy as np import mglearn from sklearn.datasets import load_breast_cancer cancer=load_breast_cancer() fig, axes = plt.subplots(15, 2, figsize=(10, 20)) malignant = cancer.data[cancer.target == 0] benign = cancer.data[cancer.target == 1] ax = axes.ravel() for i in range(30): _, bins = np.histogram(cancer.data[:, i], bins=50) ax[i].hist(malignant[:, i], bins=bins, color=mglearn.cm3(0), alpha=.5) ax[i].hist(benign[:, i], bins=bins, color=mglearn.cm3(2), alpha=.5) ax[i].set_title(cancer.feature_names[i]) ax[i].set_yticks(()) ax[0].set_xlabel("Feature magnitude") ax[0].set_ylabel("Frequency") ax[0].legend(["malignant", "benign"], loc="best") fig.tight_layout()

乳腺癌数据集中每个类别的特征直方图 在这里插入图片描述

利用 PCA,我们可以获取到主要的相互作用,并得到稍为完整的图像。我们可以找到前两 个主成分,并在这个新的二维空间中用散点图将数据可视化。 在应用 PCA 之前,我们利用 StandardScaler 缩放数据,使每个特征的方差均为 1:

from sklearn.preprocessing import StandardScaler from sklearn.datasets import load_breast_cancer cancer = load_breast_cancer() scaler = StandardScaler() scaler.fit(cancer.data) X_scaled = scaler.transform(cancer.data) from sklearn.decomposition import PCA pca = PCA(n_components=2) pca.fit(X_scaled) X_pca = pca.transform(X_scaled) print("Original shape: {}".format(str(X_scaled.shape))) print("Reduced shape: {}".format(str(X_pca.shape)))

在这里插入图片描述

现在我们可以对前两个主成分作图

# 对第一个和第二个主成分作图,按类别着 plt.figure(figsize=(8, 8)) mglearn.discrete_scatter(X_pca[:, 0], X_pca[:, 1], cancer.target) plt.legend(cancer.target_names, loc="best") plt.gca().set_aspect("equal") plt.xlabel("First principal component") plt.ylabel("Second principal component") print("PCA component shape: {}".format(pca.components_.shape)) print("PCA components:\n{}".format(pca.components_))

利用前两个主成分绘制乳腺癌数据集的二维散点图

在这里插入图片描述 PCA 是一种无监督方法,在寻找旋转方向时没有用到任何类别信息。它 只是观察数据中的相关性。对于这里所示的散点图,我们绘制了第一主成分与第二主成分 的关系,然后利用类别信息对数据点进行着色。你可以看到,在这个二维空间中两个类别 被很好地分离。这让我们相信,即使是线性分类器(在这个空间中学习一条直线)也可以 在区分这个两个类别时表现得相当不错。我们还可以看到,恶性点比良性点更加分散,这 一点也可以在图 3-4 的直方图中看出来。 PCA 的一个缺点在于,通常不容易对图中的两个轴做出解释。主成分对应于原始数据中的 方向,所以它们是原始特征的组合。但这些组合往往非常复杂,这一点我们很快就会看 到。在拟合过程中,主成分被保存在 PCA 对象的 components_ 属性中:

在这里插入图片描述

我们还可以用热图将系数可视化(图 3-6),这可能更容易理解:

plt.matshow(pca.components_, cmap='viridis') plt.yticks([0, 1], ["First component", "Second component"]) plt.colorbar() plt.xticks(range(len(cancer.feature_names)), cancer.feature_names, rotation=60, ha='left') plt.xlabel("Feature") plt.ylabel("Principal components") plt.show()

图 3-6:乳腺癌数据集前两个主成分的热图 在这里插入图片描述

3.4.3 用t-SNE进行流形学习 流形学习算法主要用于可视化,因此很少用来生成两个以上的新特征。其中一些算法(包 括 t-SNE)计算训练数据的一种新表示,但不允许变换新数据。这意味着这些算法不能用于测试集:更确切地说,它们只能变换用于训练的数据。流形学习对探索性数据分析是很 有用的,但如果最终目标是监督学习的话,则很少使用。t-SNE 背后的思想是找到数据的 一个二维表示,尽可能地保持数据点之间的距离。t-SNE 首先给出每个数据点的随机二维 表示,然后尝试让在原始特征空间中距离较近的点更加靠近,原始特征空间中相距较远的 点更加远离。t-SNE 重点关注距离较近的点,而不是保持距离较远的点之间的距离。换句 话说,它试图保存那些表示哪些点比较靠近的信息。 我们将对 scikit-learn 包含的一个手写数字数据集 2 应用 t-SNE 流形学习算法。在这个数 据集中,每个数据点都是 0 到 9 之间手写数字的一张 8×8 灰度图像。图 3-20 给出了每个 类别的一个例子。

digits = load_digits() fig, axes = plt.subplots(2, 5, figsize=(10, 5), subplot_kw={'xticks': (), 'yticks': ()}) for ax, img in zip(axes.ravel(), digits.images): ax.imshow(img)

digits 数据集的示例图 在这里插入图片描述 我们用 PCA 将降到二维的数据可视化。我们对前两个主成分作图,并按类别对数据点着 色

# 构建一个PCA模型 pca = PCA(n_components=2) pca.fit(digits.data) # 将digits数据变换到前两个主成分的方向上 digits_pca = pca.transform(digits.data) colors = ["#476A2A", "#7851B8", "#BD3430", "#4A2D4E", "#875525", "#A83683", "#4E655E", "#853541", "#3A3120", "#535D8E"] plt.figure(figsize=(10, 10)) plt.xlim(digits_pca[:, 0].min(), digits_pca[:, 0].max()) plt.ylim(digits_pca[:, 1].min(), digits_pca[:, 1].max()) for i in range(len(digits.data)): # 将数据实际绘制成文本,而不是散点 plt.text(digits_pca[i, 0], digits_pca[i, 1], str(digits.target[i]), color = colors[digits.target[i]], fontdict={'weight': 'bold', 'size': 9}) plt.xlabel("First principal component") plt.ylabel("Second principal component")

利用前两个主成分绘制 digits 数据集的散点图

在这里插入图片描述 实际上,这里我们用每个类别对应的数字作为符号来显示每个类别的位置。利用前两个主 成分可以将数字 0、6 和 4 相对较好地分开,尽管仍有重叠。大部分其他数字都大量重叠 在一起。 我们将 t-SNE 应用于同一个数据集,并对结果进行比较。由于 t-SNE 不支持变换新数据, 所以 TSNE 类没有 transform 方法。我们可以调用 fit_transform 方法来代替

from sklearn.manifold import TSNE tsne = TSNE(random_state=42) # 使用fit_transform而不是fit,因为TSNE没有transform方法 digits_tsne = tsne.fit_transform(digits.data) plt.figure(figsize=(10, 10)) plt.xlim(digits_tsne[:, 0].min(), digits_tsne[:, 0].max() + 1) plt.ylim(digits_tsne[:, 1].min(), digits_tsne[:, 1].max() + 1) for i in range(len(digits.data)): # 将数据实际绘制成文本,而不是散点 plt.text(digits_tsne[i, 0], digits_tsne[i, 1], str(digits.target[i]), color = colors[digits.target[i]], fontdict={'weight': 'bold', 'size': 9}) plt.xlabel("t-SNE feature 0") plt.xlabel("t-SNE feature 1") plt.show()

利用 t-SNE 找到的两个分量绘制 digits 数据集的散点图 在这里插入图片描述

t-SNE 的结果非常棒。所有类别都被明确分开。数字 1 和 9 被分成几块,但大多数类别都 形成一个密集的组。要记住,这种方法并不知道类别标签:它完全是无监督的。但它能够 找到数据的一种二维表示,仅根据原始空间中数据点之间的靠近程度就能够将各个类别明 确分开。 t-SNE 算法有一些调节参数,虽然默认参数的效果通常就很好。你可以尝试修改 perplexity 和 early_exaggeration,但作用一般很小。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3