失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 数据集特征提取_基于PCA算法实现鸢尾花数据集的特征提取任务

数据集特征提取_基于PCA算法实现鸢尾花数据集的特征提取任务

时间:2020-11-20 19:38:47

相关推荐

数据集特征提取_基于PCA算法实现鸢尾花数据集的特征提取任务

PCA算法的必要性

多变量大数据集无疑会为研究和应用提供丰富的信息,但是许多变量之间可能存在相关性,从而增加了问题分析的复杂性。如果分别对每个指标进行分析,分析往往是孤立的,不能完全利用数据中的信息,因此盲目减少指标会损失很多有用的信息,从而产生错误的结论。

因此如果可以在减少需要分析的指标同时,尽量减少原指标包含信息的损失,那么将有利于算法模型的搭建。由于各变量之间存在一定的相关关系,因此可以考虑将关系紧密的变量变成尽可能少的新变量,使这些新变量是两两不相关的,那么就可以用较少的综合指标分别代表存在于各个变量中的各类信息。PCA算法就属于这类降维算法。

我们所使用的数据集

Iris 鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例。数据集内包含 3 类共 150 条记录,每类各 50 个数据,每条记录都有 4 项特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度。数据集的部分数据如下所示:

可以看出这个数据集中的数据分为5列,也就是5个特征,5个维度,这5个列分别是:鸢尾花的花萼长度、花萼宽度、花瓣长度、 花瓣宽度、以及花的类别。这样的5个维度很难通过可视化的方式,所以下面我们将通过PCA算法来完成降维的操作,将5维数据将成2维。

数据的读取

下面我们先读取文件中的数据,并且为每列数据指定其列名,这样更加的有利于查看我们读取到数据。

import numpy as npimport pandas as pddf=pd.read_csv('iris.data')df.columns=['sepal_len','sepal_wid','petal_len','petal_wid','class']print(df.hean())

部分数据

可视化

可视化代码

可视化效果

数据的处理

下面我们对数据进行处理,也就是标准化我们的数据集,将数据属性(按列进行)减去其均值,并除以其方差。得到的结果是,对于每个属性/每列来说所有数据都聚集在0附近,方差为1

标准化

标准化完成之后,我们下面的任务是求出协方差矩阵,我们最终算出来的协方差矩阵中的每一个元素表示特征i和特征j之间的之间的协方差,协方差可以理解为两个特征之间的相关性,如果值为正就表示正相关,越大越正相关,如果值为负就表示负相关,越小就表示越负相关,如果值为0就表示不相关。下面我们求出这个样本的协方差矩阵。协方差矩阵的对角线为1,也就是自身和自身的相关系数都是1。

均值

然后使用协方差矩阵公式求出这个数据集的协方差矩阵。这个公式是我们自己写的,实际上在python中已经封装了这种类似的方法

协方差

使用np.cov传递过去数据集,就可以直接获取到这个数据集中的协方差,我们传递的参数要是X_std的转值值,转置完成之后我们获取到的新矩阵的每一行都是原矩阵中的每一列,也就是说现在的矩阵中的有四行,每一行为数据集中特征的所有数据。

求解特征向量和特征值

我们再来回顾一下我们的任务,我们这个数据集X是150*4的,我们的任务是将其变为150*2的,也就是将成两维,那么可以通过150*4*[4*2]=150*2来完成,所以我们下面的任务是如何构建出到这个[4*2]矩阵呢?

特征值和特征向量

我们使用已经封装好的np.linalg.eig方法来获取到了协方差矩阵的特征值和特征向量,一个特征值对应一个特征向量,所以四个特征值对应四个特征向量,也就是说特征值2.92442837,而这个特征值所对应的特征向量就是[ 0.52308496, -0.25956935, 0.58184289, 0.56609604]特征向量矩阵竖着看,每一列是一个特征矩阵,我们现在的任务是在这四个特征向量中选出两个特征向量(最具代表性的),我们的选择方案是:特征值越大对应的特征向量越重要。

我们第一步是将封装成一个列表,列表中的元素是元组,元组为(特征值,特征值所对的特征向量)然后按照特征值进行排序,排序的结果不仅是特征值的排序结果,同时也是特征向量的排序结果排序完成之后就是eig_pairs

eig_pairs[0]为(2.9244283691111144, array([ 0.52308496, -0.25956935, 0.58184289, 0.56609604]))eig_pairs[1]为(0.9321523302535064, array([-0.36956962, -0.92681168, -0.01912775, -0.06381646]))eig_pairs[0][1]为array([ 0.52308496, -0.25956935, 0.58184289, 0.56609604])eig_pairs[1][1]为array([-0.36956962, -0.92681168, -0.01912775, -0.06381646])

所以此时我们获取到的eig_pairs[0][1]和eig_pairs[1][1]就是我们想要获取到的特征向量,此时我们将其转成4*1,然后两个结合到一起就是我们想要的4*2矩阵了。

接下来我们要使用原始数据集矩阵乘以这个4*2矩阵,就是我们想要的降维之后的矩阵Y了。

当我们获取到Y的时候我们的PCA降维就完成了,我们的成功的将原来的数据集降成了两个维度的数据集。

代码实现

import numpy as npimport pandas as pdfrom matplotlib import pyplot as pltimport mathfrom sklearn.preprocessing import StandardScalerdf = pd.read_csv('iris.data')df.columns=['sepal_len', 'sepal_wid', 'petal_len', 'petal_wid', 'class']X = df.ix[:,0:4].valuesy = df.ix[:,4].valuesX_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)#创建一个(特征值,特征向量)元组列表eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))]print eig_pairs#特征向量从高到低排序eig_pairs.sort(key=lambda x: x[0], reverse=True)matrix_w = np.hstack((eig_pairs[0][1].reshape(4,1), eig_pairs[1][1].reshape(4,1)))Y = X_std.dot(matrix_w)print Y

特征的可视化

每个子图分别是每个特征在不同类型鸢尾花的情况

代码实现:

label_dict = {1: 'Iris-Setosa', 2: 'Iris-Versicolor', 3: 'Iris-Virgnica'}feature_dict = {0: 'sepal length [cm]', 1: 'sepal width [cm]', 2: 'petal length [cm]', 3: 'petal width [cm]'}plt.figure(figsize=(8, 6))for cnt in range(4): plt.subplot(2, 2, cnt+1) for lab in ('Iris-setosa', 'Iris-versicolor', 'Iris-virginica'): print cnt print y==lab print(X[y==lab, cnt]) print lab plt.hist(X[y==lab, cnt], label=lab, bins=10, alpha=0.3,) plt.xlabel(feature_dict[cnt]) plt.legend(loc='upper right', fancybox=True, fontsize=8)plt.tight_layout()plt.show()

寻找最优特征

我们刚才要找到两个特征值中特征值最大的那两个特征,我们前面的方案是排序sort的方式,如果从可视化的角度,为了让大家可以通过看图一眼就看出究竟哪几个的特征最大,我们可以使用如下这种方式:

选取特征最大

该图有两个,一个柱状图,一个折线图,柱状图为特征值,折线图中可以看出是逐渐增加的,这个折线图是这样的折线折线图的第一部分是第一个特征值,第二部分是第一个特征值+第二个特征值,第三部分是第一个特征值+第二个特征值+第三个特征值,第四部分是第三部分是第一个特征值+第二个特征值+第三个特征值++第四个特征值,这样我们就可以看哪哪一部分变化特别大了,就表示这这特征值大,这个特征值就是我们所需要的。

代码实现

tot = sum(eig_vals)#计算特征值和var_exp = [(i / tot) * 100 for i in sorted(eig_vals, reverse=True)]cum_var_exp = np.cumsum(var_exp)#逐渐累加plt.figure(figsize=(6, 4))#画图,柱状图是var_exp,折线图是cum_var_expplt.bar(range(4), var_exp, alpha=0.5, align='center', label='individual explained variance')plt.step(range(4), cum_var_exp, where='mid', label='cumulative explained variance')plt.ylabel('Explained variance ratio')plt.xlabel('Principal components')plt.legend(loc='best')plt.tight_layout()plt.show()

降维之后的效果

这个横轴表示特征sepal_len,纵轴表示sepal_wid,其中有三个颜色,每个颜色表示鸢尾花的类别,实现的代码为

plt.figure(figsize=(6, 4))for lab, col in zip(('Iris-setosa', 'Iris-versicolor', 'Iris-virginica'),('blue', 'red', 'green')): plt.scatter(X[y==lab, 0], X[y==lab, 1], label=lab, c=col)plt.xlabel('sepal_len')plt.ylabel('sepal_wid')plt.legend(loc='best')plt.tight_layout()plt.show()

上面我们只用了两个特征,可以看出红的和绿的分的不是很开,因为我们已经降维了Y,所以我们可以使用已经降维的数据来画图,效果为:

这样降维之后的数据画图,可以看出蓝色和绿色很是清晰。实现的代码为

Y = X_std.dot(matrix_w)plt.figure(figsize=(6, 4))for lab, col in zip(('Iris-setosa', 'Iris-versicolor', 'Iris-virginica'), ('blue', 'red', 'green')): plt.scatter(Y[y==lab, 0], Y[y==lab, 1], label=lab, c=col)plt.xlabel('Principal Component 1')plt.ylabel('Principal Component 2')plt.legend(loc='lower center')plt.tight_layout()plt.show()

如果觉得《数据集特征提取_基于PCA算法实现鸢尾花数据集的特征提取任务》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。