1.6 降维

降维算法即将高维数据投射到低维空间,并尽可能地保留最多的信息。这类算法既可以用于去除高维数据的冗余信息,也可以用于数据的可视化。比如我们可以使用降维算法将鸢尾花数据集的数据分布情况直观地展现出来。鸢尾花数据本身有4个特征,也就是一个四维空间的数据,因为四维空间是无法直接观测的,所以需要将数据降到三维空间才可以查看。

1.6.1 PCA降维

首先可以尝试使用最常用的降维方法PCA(主成分分析)对鸢尾花数据集进行降维展示,将数据集从四维降到三维的代码如下:

>>> from sklearn.datasets import load_iris
>>> from sklearn.decomposition import PCA
>>> from mpl_toolkits.mplot3d import Axes3D
>>> data = load_iris()
>>> x = data['data']
>>> y = data['target']
>>> # n_components表示主成分维度
>>> pca = PCA(n_components=3)
>>> # 将数据降成三维
>>> x_3d = pca.fit_transform(x)
>>> fig = plt.figure()
>>> plt.subplot(121)
<matplotlib.axes._subplots.AxesSubplot object at 0x000000000FDA3860>
>>> ax = Axes3D(fig)
>>> for i,item in enumerate(x_3d):
...     ax.scatter(item[0],item[1],item[2],color = colors[y[i]],marker = markers[y[i]])
...
>>> plt.show()

上述代码中的fit_transform方法将模型训练和数据转换合并在一起,方便调用。降维后,三维鸢尾花数据如图1-11所示。

图 1-11 使用PCA将鸢尾花数据集降维至三维

在图1-11所示的三维空间中我们可以看到,鸢尾花数据的3个类别之间呈现出相互分离的状态,可以较容易地找到数据的分类界面。

接下来继续把数据降到二维空间,查看有何变化,将鸢尾花数据集从四维降到二维的代码如下,降维后的结果如图1-12所示:

>>> pca2d = PCA(n_components=2)
>>> x_2d = pca2d.fit_transform(x)
>>> plt.figure()
<Figure size 640x480 with 0 Axes>
>>> for i,item in enumerate(x_2d):
...     plt.scatter(item[0],item[1],color = colors[y[i]],marker = markers[y[i]])
...
>>> plt.show()

图 1-12 使用PCA将鸢尾花数据集降维至二维

从图1-12可以看到,降到二维之后,鸢尾花数据集仍然具有很好的可分性,这就达到了降维过程中尽量保留有用信息的要求。

最后再尝试把数据降到一维,从四维降到一维的代码如下,降维后的结果如图1-13所示:

>>> pca1d = PCA(n_components=1)
>>> x_1d = pca1d.fit_transform(x)
>>> plt.figure()
<Figure size 640x480 with 0 Axes>
>>> for i,item in enumerate(x_1d):
...     plt.scatter(item[0],0,color = colors[y[i]],marker = markers[y[i]])
...
>>> plt.show()

图 1-13 使用PCA将鸢尾花数据集降维至一维

从图1-13中可以看到,降到一维之后,鸢尾花数据集中的两个分类出现了比较明显的交叠现象,不能通过某个阈值将数据很好地进行分类。

1.6.2 LDA降维

除了PCA,sklearn还提供了一个降维方法:LDA(线性判别分析)。使用LDA也可以对鸢尾花数据集进行降维可视化。

因为LDA只能将数据降维到 [1, 类别数-1),所以在鸢尾花任务中,无法使用LDA将数据降维到三维,最高只能做二维展示。降维展示代码如下,降维结果如图1-14所示:

>>> from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
>>> lda = LDA(n_components=2)
>>> x_2d = lda.fit_transform(x,y)
>>> plt.figure()
<Figure size 640x480 with 0 Axes>
>>> for i,item in enumerate(x_2d):
...     plt.scatter(item[0],item[1],color = colors[y[i]],marker = markers[y[i]])
...
>>> plt.show()

图 1-14 使用LDA将鸢尾花数据集降维至二维

对比图1-14与图1-12,也可以看出,使用LDA降维之后的数据比使用PCA降维之后的数据的可分性更好。

那么继续做一维降维,会得到什么样的效果呢?以下是使用LDA进行四维转一维的代码,降维结果如图1-15所示:

>>> lda = LDA(n_components=1)
>>> x_1d = lda.fit_transform(x,y)
>>> plt.figure()
<Figure size 640x480 with 0 Axes>
>>> for i,item in enumerate(x_1d):
...     plt.scatter(item[0],0,color = colors[y[i]],marker = markers[y[i]])
...
>>> plt.show()

图 1-15 使用LDA将鸢尾花数据集降维至一维

从图1-15中可以看到,将鸢尾花数据集降维到一维之后,虽然有两个类别相距较近,但是几乎看不出来任何重叠。

两种方法最大的区别是PCA是无监督学习算法,而LDA是监督学习算法,这一点从二者fit_transform方法的输入参数可以看出。

PCA的降维原则是保留方差较大的维度,降维方差较小的维度,而LDA的降维原则是保证降维后,类内方差最小,类间方差最大。因此,LDA降维之后的数据可分性较强。可见,在有标签的情况下,应该尽量使用LDA进行降维或者可视化。