Kaggle:使用MNIST数据集进行PCA降维和LDA降维

  关于PCA(主成分分析,Principal components analysis),这里有非常通俗易懂的文章解释:主成份分析(PCA)最详细和全面的诠释,这里就不多啰嗦了,下面主要介绍PCA算法和LDA算法在MNIST数据集上的应用。
  主要参考的是Kaggle上的一篇Kernel,也可以直接去看这篇Kernel,这里附上链接:Interactive Intro to Dimensionality Reduction


python代码:

导入一些基本的库

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

import plotly.offline as py
py.init_notebook_mode(connected=True)
import plotly.graph_objs as go
import plotly.tools as tls
import seaborn as sns
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import matplotlib

# Import PCA
from sklearn.decomposition import PCA

PCA

  简而言之,PCA是一种线性变换算法,它试图将我们数据的原始特征投射到更小的特征集合(或子空间)上,同时保留大部分信息。为了做到这一点,算法试图在新的子空间中找到最合适的方向/角度(即主成分),该主成分能最大化方差。为什么要最大化方差呢?请看本文的第一个链接。

MNIST数据集

  MNIST数据集是计算机视觉中的数字数据集,基本上算是机器学习中的入门级数据集了,可以到Kaggle上下载:MNIST Dataset。

#载入数据集,查看维度
train = pd.read_csv('../input/train.csv')
print(train.shape) #(42000, 785)

#将训练集的特征和标签分开
target = train['label']
train = train.drop("label",axis=1)# Drop the label feature

计算特征向量

  先将数据对每个特征进行标准化处理得到X_std,然后计算出协方差矩阵cov_mat,计算协方差矩阵的特征值eig_vals和特征向量 eig_vecs。并把每个特征值与它对应的特征向量绑定起来作为一个特征对eig_pairs,按特征值的大小对特征对进行从大到小排序。
  之后计算特征值的和tot以及每个特征占特征值和的比例var_exp,特征值占特征值和的累计比例cum_var_exp

#将数据集进行标准化处理
from sklearn.preprocessing import StandardScaler
X = train.values
X_std = StandardScaler().fit_transform(X)

# 计算协方差矩阵的特征值和特征向量
mean_vec = np.mean(X_std, axis=0)
cov_mat = np.cov(X_std.T)
eig_vals, eig_vecs = np.linalg.eig(cov_mat)
#创建(特征值,特征向量)元组对 的列表
# Create a list of (eigenvalue, eigenvector) tuples
eig_pairs = [ (np.abs(eig_vals[i]),eig_vecs[:,i]) for i in range(len(eig_vals))]

# Sort the eigenvalue, eigenvector pair from high to low
eig_pairs.sort(key = lambda x: x[0], reverse= True)

# Calculation of Explained Variance from the eigenvalues
tot = sum(eig_vals) #特征值的和
var_exp = [(i/tot)*100 for i in sorted(eig_vals, reverse=True)] #单个特征值所占的比重
cum_var_exp = np.cumsum(var_exp) # 特征值累计比重

画出特征值比例图以及特征值累计比例图

  具体代码可以参考原文,这里就不贴了。
Kaggle:使用MNIST数据集进行PCA降维和LDA降维_第1张图片
  上图右上角的小图与大图是一样的,只是做了个缩放。黄色线和绿色线是特征值的累计比例,可以看出累计比例是100%的,没有问题。黑色线和红色线是单个特征值的比例。横坐标到784为止,代表784维特征。
  正如我们所看到的,在我们的784个特性或列中,大约90%的解释方差可以用200以上的特性来描述。因此,如果想在这上面实现一个PCA,提取前200个特征将是一个非常符合逻辑的选择,因为它们已经占了大约90%的信息。

可视化特征向量

  如上所述,由于PCA方法试图捕获最大方差的最优方向(特征向量)。因此,可视化这些方向及其相关特征值可能是有用的。为了快速实现,这里只会提取PCA特征值前30个(使用Sklearn的 .components_ 方法)特征向量。

# 调用 SKlearn的 PCA 方法
n_components = 30
pca = PCA(n_components=n_components).fit(train.values)

eigenvalues = pca.components_.reshape(n_components, 28, 28)

#提取PCA主成分(特征值),仔细想想应该是特征向量
eigenvalues = pca.components_

#画图
n_row = 4
n_col = 7

# Plot the first 8 eignenvalues
plt.figure(figsize=(13,12))
for i in list(range(n_row * n_col)):
#     for offset in [10, 30,0]:
#     plt.subplot(n_row, n_col, i + 1)
    offset =0
    plt.subplot(n_row, n_col, i + 1)
    plt.imshow(eigenvalues[i].reshape(28,28), cmap='jet')
    title_text = 'Eigenvalue ' + str(i + 1)
    plt.title(title_text, size=6.5)
    plt.xticks(())
    plt.yticks(())
plt.show()

Kaggle:使用MNIST数据集进行PCA降维和LDA降维_第2张图片
  上面的小块描绘了PCA方法为我们的MNIST数据集生成的前30个最优方向或主成分轴。有趣的是,当把第一个分量“特征值1”与第28分量“特征值28”进行比较时,很明显,在寻找最大方差中生成了更复杂的方向或成分,从而使新特征子空间的方差最大化。

用Sklearn实现PCA算法

  现在使用Sklearn工具包,实现主成分分析算法如下:

# Delete our earlier created X object
del X
# 值采用前6000个样本来加速计算
X= train[:6000].values
del train
# 标准化数据
X_std = StandardScaler().fit_transform(X)

# Call the PCA method with 5 components. 
pca = PCA(n_components=5)
pca.fit(X_std)
X_5d = pca.transform(X_std)

# "Target"也要取前6000个
Target = target[:6000]

  X_std为标准化后的数据,shape为(6000,784),X_5d为降维之后的数据,shape为(6000,5)

画前2个主成分的散点图

  当涉及到这些降维的方法时,散点图是最常用的,因为它们允许对聚类(如果有的话)进行大而方便的可视化,而这正是我们在绘制前2个主成分时所要做的事情。下面是以5个主成分中的第一个主成分和第二个主成分为横纵坐标画的散点图,代码可以看原文。
Kaggle:使用MNIST数据集进行PCA降维和LDA降维_第3张图片
  正如从散点图中观察到的那样,你可以从颜色的集体斑点中分辨出一些明显的簇。这些簇群表示了不同的点潜在地代表了不同的数字。但是,由于PCA算法是无监督算法,上面的图之所以有颜色,是因为画图时加上了数据集的标签,如果不加数据集的标签,是看不到这些颜色的。那么,如果没有加入颜色,我们如何能够将我们的数据点分离到新的特征空间中呢?
  首先,我们用Sklearn建立了KMeans聚类方法,并使用fit_predict方法计算集群中心,并预测第一个和第二个PCA投影的成分指标(看看是否可以观察到任何可感知的簇群)。KMeans聚类散点图:

from sklearn.cluster import KMeans # KMeans clustering 
# Set a KMeans clustering with 9 components ( 9 chosen sneakily ;) as hopefully we get back our 9 class labels)
kmeans = KMeans(n_clusters=9)
# Compute cluster centers and predict cluster indices
X_clustered = kmeans.fit_predict(X_5d)

Kaggle:使用MNIST数据集进行PCA降维和LDA降维_第4张图片
  从视觉上看,KMeans算法生成的簇群似乎在簇群之间提供了更清晰的划分,相比之下,我们的PCA投影中添加了类标签。这并不奇怪,因为PCA是一种无监督的方法,因此它并不能优化分离类别。然而,分类的任务是由我们将要讨论的下一个方法完成的。

LDA

  LDA像PCA一样,也是一种线性变换方法,通常用于降维任务。但与非监督学习算法不同,LDA属于监督学习方法。由于LDA的目标是提供关于类标签的有用信息,LDA将通过计算成分坐标轴(线性鉴别器)来最大化不同类之间的距离。
  简而言之,二者区别是:LDA与PCA的对比,PCA选择样本点投影具有最大方差的方向,LDA选择分类性能最好的方向:
  Sklearn工具包也自带了内置LDA函数,因此我们调用LDA模型如下:

lda = LDA(n_components=5)
# Taking in as second argument the Target as labels
X_LDA_2D = lda.fit_transform(X_std, Target.values )

  LDA实现的语法非常类似于PCA的语法。使用一次调用fit和transform方法,它将LDA模型与数据相拟合,然后通过应用LDA维度缩减来实现转换。然而,由于LDA是一种有监督的学习算法,所以对于用户必须提供的方法有第二个参数,这将是类标签,在本例中是数字的目标标签。

LDA可视化散点图

Kaggle:使用MNIST数据集进行PCA降维和LDA降维_第5张图片
  从上面的散点图中,我们可以看到,在使用LDA时,与使用类标签实现PCA相比,数据点更清晰地聚集在一起。这是拥有类标签来监督学习的方法的内在优势。简而言之,为正确的工作选择合适的工具。

你可能感兴趣的:(机器学习)