机器学习笔记(八)-PCA降维Wine Data Set详细过程

原创不易,转载前请注明博主的连接地址:Blessy_Zhu https://blog.csdn.net/weixin_42555080
本次代码的环境:
运行平台: Windows
Python版本: Python3.x
IDE: PyCharmjava

1、 前言

在上一篇博文机器学习笔记(七)-主成分分析PCA 中,已经介绍了主成分分析PCA的基本内容。接下来的这篇文章,主要是经过一个多维的数据集,一步步去了解PCA的实现过程和原理。最后经过逻辑回归来拟合用PCA降维处理后的数据集。ios

2、数据集

本次选取数据集是UCI(网址:https://archive.ics.uci.edu/ml/datasets/ )上的数据集Wine Data Set (红酒数据集)。首先对这原始数据集进行简明扼要的介绍。
Wine Data Set主要是经过使用化学分析肯定葡萄酒的来源。数据集的相关信息以下表1-1所示:
在这里插入图片描述
Wine Data Set是由Stefan Aeberhard(电子邮件:stefan ‘@’ coral.cs.jcu.edu.au)捐助的。这些数据是对意大利同一地区种植的葡萄酒进行化学分析的结果,这些葡萄酒来自三个不一样的品种。该分析肯定了三种葡萄酒中每种葡萄酒中含有的13种成分的数量。不一样种类的酒品,它的成分也有所不一样,经过对这些成分的分析就能够对不一样的特定的葡萄酒进行分类分析。Wine Data Set原始 数据集共有178个样本数、3种数据类别、每一个样本的有13个属性。这13个属性分别是:酒精、苹果酸、灰、灰分的碱度、镁、总酚、黄酮类化合物、非黄烷类酚类、原花色素、颜色强度、色调、稀释葡萄酒的OD280 / OD31五、脯氨酸。web

3、准备工做

在展开内容介绍以前,先来回顾一下本次须要用到的数学知识。算法

3.1 均值(mean)、标准差(Standard Deviation)

假设咱们有个样本集X,其中的样本为X=[1,2,3,4,5],求平均值的公式以下:
在这里插入图片描述
在这里插入图片描述
X的平均值为:
在这里插入图片描述
Python实现方式是:数组

import numpy as np
X=np.array([1,2,3,4,5])
np.mean(X)

然而,样本均值对于极差较大的数据来讲,并不能很好的反应数据的性质,这样,就可使用样本均值来展现数据的分散程度:
在这里插入图片描述
Python代码实现是:less

import numpy as np
X=np.array([1,2,3,4,5])
np.std(X)

3.2 协方差(Covariance)

方差和标准差只能操做一维的数据集,可是实际样本通常会有不少维的=。高维数据,虽然更好的表示了数据的特征,可是对于数据的分析和可视化来讲倒是很大的难题。若是能够经过判断数据维度之间的关系,从而实现降维的目的,那就太好了。而协方差就是这个目标中的一个重要步骤。协方差是测量样本特征之间的关系,好比:样本有2个特征,一个是学习时间,一个是成绩,那么正常状况下,必定是你的学习时间越长,你的成绩越好。
假设有两个特征X,Y。计算它们之间的协方差公式为:
在这里插入图片描述
协方差具体的大小并不重要,可是它的正负是重要的。dom

  • 若是它的值是正的,这代表两个特征之间同时增长或减少;
  • 若是它的值是负的,这代表两个特征之间有一个增长而另外一个减少。
  • 若是它的值为0,则代表两个特征之间是独立的。

在真实数据集中,样本的维度不可能只有2个。在这种状况下用协方差矩阵表示。假设样本有n个特征,这里,用1,2,3,4,…,n来表示每一个特征。协方差矩阵以下所示:
在这里插入图片描述
上面C是一个n∗n维的矩阵,能够看到对角线上红色是本身与本身的协方差,也就是方差。而对角线两侧的协方差是对称的,所以协方差矩阵是一个关于对角线对称的方阵。
用以下两维数据:学习时间(Time)和分数(Score)的例子来演示一下协方差:
在这里插入图片描述
Python代码以下:机器学习

import numpy as np
T=np.array([9,15,25,14,10,18,0,16,5,19,16,20])
S=np.array([39,56,93,61,50,75,32,85,42,70,66,80])
T=T[:,np.newaxis] #构造为二维数组
S=S[:,np.newaxis]
X=np.hstack((T,S))
np.cov(X.T)

# 协方差输出以下
array([[  47.71969697,  122.9469697 ],
       [ 122.9469697 ,  370.08333333]])

从上面的输出结果能够看到,cov(T,S)=cov(S,T)=122.9469697,这是正数,所以说明学习时间越长,分数越高。svg

3.3 特征向量(Eigen vectors)与特征值(Eigen values)

v是一个非零向量,要想v是线性变换T的特征向量,则T(v)是一个标量值乘上v,它能够被写成以下形式:post

T(v)=λv (λ是一个标量,而且它也是关联着特征向量v的特征值)
若是线性变换T被表示成做为一个方阵A的变换,那么上面的等式能够写成以下形式:
Av=λv (v是列向量)
举个例子:假设上面的方阵A,则:
在这里插入图片描述
上面的(3@2)为特征向量,4为特征值。
这里须要注意一下几点:

  • 只有方阵才能求出特征向量,可是,并非每一个方阵都有特征向量。假设我有一个n * n的矩阵,那么就有n个特征向量。
  • 一个矩阵中的全部特征向量都是相互垂直的,不管数据集中有多少特征。
  • 向量的大小不能影响它是否是一个特征向量,可是,它的方向能够。所以,在咱们找到特征向量之后要把它们单位化,使全部的特征向量都有相同的长度。

4、PCA处理Wine Data Set

4.1 数据标准化

PCA对数据缩放是至关敏感的,所以,在实现PCA的时候,若是数据特征在不一样的范围上,要先对数据集标准化。可使用scikit-learn对数据进行标准化,代码以下:

import pandas as pd

df_wine = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data', header=None) # 加载葡萄酒数据集

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values # 把分类属性与常规属性分开
X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=0.3, random_state=0) # 把整个数据集的70%分为训练集,30%为测试集

# 下面3行代码把数据集标准化为单位方差和0均值
sc = StandardScaler()
X_train_std = sc.fit_transform(X_train)
X_test_std = sc.fit_transform(X_test)

4.2 计算协方差矩阵

由于每一个样本有13个属性,因此协方差矩阵的维数应该是13 * 13的方阵:

import numpy as np
cov_mat = np.cov(X_train_std.T)

4.3 求协方差矩阵的特征向量和特征值

协方差矩阵是方阵,因此咱们能够计算它的特征向量和特征值。

import numpy as np
eigen_vals, eigen_vecs = np.linalg.eig(cov_mat)
# 下面的输出为eigen_vals
array([ 4.8923083 ,  2.46635032,  1.42809973,  1.01233462,  0.84906459,
        0.60181514,  0.52251546,  0.08414846,  0.33051429,  0.29595018,
        0.16831254,  0.21432212,  0.2399553 ])

因为特征向量是单位向量。可是,这些方向单位向量,哪一个方向上保留的方差最大呢?这其实并不难,求出的特征值的意义就是特征向量的大小,所以只要找出最大特征值所对应的特征向量就能够知道哪一个方向保留的方差最大。
接下来通方差解释率(variance explained ratios),也就是每一个特征值占全部特征值和的比,来展现不一样维度对数据描述的贡献值。

tot = sum(eigen_vals) # 求出特征值的和
var_exp = [(i / tot) for i in sorted(eigen_vals, reverse=True)] # 求出每一个特征值占的比例(降序)
cum_var_exp = np.cumsum(var_exp) # 返回var_exp的累积和

import matplotlib.pyplot as plt

# 下面的代码都是绘图的,涉及的参数建议去查看官方文档
plt.bar(range(len(eigen_vals)), var_exp, width=1.0, bottom=0.0, alpha=0.5, label='individual explained variance')
plt.step(range(len(eigen_vals)), cum_var_exp, where='post', label='cumulative explained variance')
plt.ylabel('Explained variance ratio')
plt.xlabel('Principal components')
plt.legend(loc='best')
plt.show()

在这里插入图片描述
这里须要介绍一下Cumulative explained variance(累计解释总方差)和Individual explained variance(单个解释方差)这两个概念:

  • Individual explained variance(单个解释方差):就是单个属性(好比上图中的第一个属性)对数据描述的贡献值,也就是说,属性0,30%-40%的几率能够准确描述样本。
  • Cumulative explained variance(累计解释总方差):将每一个属性的贡献值加起来,其最大值为100%。也就是说,上图的样本有13个属性,那么这13个属性能够100%描述样本。即彻底表明原来的变量信息(固然这是不可能的)

从上图能够看到了,其实2个特征就已经保留了数据集的大部分信息,可见在实际应用中,大部分的特征都是冗余的。注意,PCA是无监督学习算法,这就意味着它会忽视类标签信息(即分类属性)。

4.4 特征变换(Feature transformation)

上面已经成功地把协方差方阵转换成了特征向量和特征值,如今把葡萄酒数据集映射到新的主成分坐标轴。为了数据的可视化,把数据集映射到2个保留最多方差的主成分。所以,须要从大到小排序特征值,选出前2个特征值对应的特征向量,并用这2个特征向量构建映射矩阵,用这个映射矩阵把数据集转换到2维空间。

eigen_pairs =[(np.abs(eigen_vals[i]),eigen_vecs[:,i]) for i in range(len(eigen_vals))] # 把特征值和对应的特征向量组成对
eigen_pairs.sort(reverse=True) # 用特征值排序

下面,选出前2对来构建映射矩阵,可是在实际应用中,应该权衡计算效率和分类器之间的性能来选择恰当的主成分数量。

first = eigen_pairs[0][1]
second = eigen_pairs[1][1]
first = first[:,np.newaxis]
second = second[:,np.newaxis]
w = np.hstack((first,second))

如今,已经构建出了13×2维的映射矩阵 W,接下来能够用这个映射矩阵来转换训练集X_train_std(124×13维)到只包含2个特征的子空间,用X_train_pca=X_train_stdW,如今这个2维的新空间可视化了,代码以下:

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
X_train_pca = X_train_std.dot(w) # 转换训练集
colors = ['r', 'b', 'g']
markers = ['s', 'x', 'o']
for l, c, m in zip(np.unique(y_train), colors, markers):
    plt.scatter(X_train_pca[y_train==l, 0], X_train_pca[y_train==l, 1], c=c, label=l, marker=m) # 散点图
plt.xlabel('PC 1')
plt.ylabel('PC 2')
plt.legend(loc='lower left')
plt.show()

在这里插入图片描述
如今,能够看到数据是线性可分的。

五 LR实现Wine Data Set数据分类

from sklearn.linear_model import LogisticRegression
from sklearn.decomposition import PCA
pca = PCA(n_components=2) # 保留2个主成分
lr = LogisticRegression() # 建立逻辑回归对象
X_train_pca = pca.fit_transform(X_train_std) # 把原始训练集映射到主成分组成的子空间中
X_test_pca = pca.transform(X_test_std) # 把原始测试集映射到主成分组成的子空间中
lr.fit(X_train_pca, y_train) # 用逻辑回归拟合数据
plot_decision_regions(X_train_pca, y_train, classifier=lr)
lr.score(X_test_pca, y_test) # 0.98 在测试集上的平均正确率为0.98
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.legend(loc='lower left')
plt.show()

在这里插入图片描述
从上图能够看出,用PCA压缩数据之后,依然很好对样本进行分类。

6、总结

本篇文章主要介绍了PCA降维Wine Data Set的详细过程。这篇文章就到这里了,欢迎大佬们多批评指正,也欢迎你们积极评论多多交流。
 

 
在这里插入图片描述