【Python机器学习实战】无监督学习之PCA和K-Means二连击

简介

无监督学习着重于发现数据本身的分布特点。与监督学习不同,无监督学习不需要对数据进行标记。

从功能上来看,无监督学习模型可以用于发现数据的“群落”(聚类),同时也可以寻找“离群”的样本,另外,对于特征维度非常高的数据样本,我们同样可以通过无监督的学习对数据进行降维(PCA),保留最具有区分性的低维度特征。这些都是在海量数据处理中非常实用的技术。

K均值(K-means)算法

K均值算法是数据聚类中最经典,也相对容易理解的模型。算法执行可以分层一下四个阶段:

  • 随机布设K个特征空间内的点作为初始的聚类中心;
  • 对每个数据的特征向量,从K个聚类中心中选择距离最近的一个,并把改数据标记为从属于这个聚类中心;
  • 在所有的数据都被标记过聚类中心后,根据这些数据被分配的类簇,重新对K个聚类中心做计算;
  • 如果一轮下来,所有的数据点从属的聚类中心与上一次的分配的类簇没有变化,那么迭代就可以停止,否则回到第二步继续循环。

主成分分析PCA

使用PCA进行降维的目的有两个:

  • 在实际项目中经常会有特征维度非常之高的训练样本,而往往又无法借助自己的领域知识人工地构建有效特征;
  • 在数据表现方面,我们无法用肉眼观测超过三个维度的特征,因此数据降维为数据的可视化提供了可能性。

问题引出

本文将继续使用对手写数字进行分类的数据,关于数据的相关内容可以参考我的另外一篇博客:sklearn实例-用支持向量机分类器(SVC)识别手写字体

代码实例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import adjusted_rand_score, classification_report
from sklearn.decomposition import PCA
from sklearn.svm import LinearSVC

digits_train = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/'
                           'optdigits/optdigits.tra', header=None)
digits_test = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/'
                           'optdigits/optdigits.tes', header=None)

X_train = digits_train[np.arange(64)]
y_train = digits_train[64]
X_test = digits_test[np.arange(64)]
y_test = digits_test[64]

#------------------直接用K均值进行聚类--------------------
kmeans = KMeans(n_clusters=10)
kmeans.fit(X_train, y_train)
y_pred = kmeans.predict(X_test)
print('使用ARI指标计算评估聚类性能:', adjusted_rand_score(y_test, y_pred)) #与Accuracy类似


#------------------使用PCA压缩数据至二维并可视化--------------------
#初始化PCA,并将64维的数据压缩至2维
estimator = PCA(n_components=2)
X_pca = estimator.fit_transform(X_train)

#定义一个能够将二维分类结果可视化的函数
def plot_pca_scatter():
    colors = ['black', 'blue', 'purple', 'yellow', 'white', 'red', 'lime', 'cyan', 'orange', 'gray']
    for i in  range(len(colors)):
        px = X_pca[:, 0][y_train.values == i]
        py = X_pca[:, 1][y_train.values == i]
        plt.scatter(px, py, color=colors[i])

    plt.legend(np.arange(10).astype(str))
    plt.xlabel('First Principle Component')
    plt.ylabel('Second Priciple Component')
    plt.show()

#调用该函数并将结果可视化
plot_pca_scatter()

#------------------PCA+线性SVC与SVC对比--------------------
#导入基于线性核函数的支持向量机分类器,并进行拟合
svc = LinearSVC()
svc.fit(X_train, y_train)
y_pred = svc.predict(X_test)

#用PCA将64维数据压缩至20维
estimator_new = PCA(n_components=20)
pca_X_train = estimator_new.fit_transform(X_train)
pca_X_test = estimator_new.fit_transform(X_test)

#再使用默认配置初始化LinearSVC,对压缩过的20维数据进行建模并作出预测
pca_svc = LinearSVC()
pca_svc.fit(X_train, y_train)
y_pca_pred = pca_svc.predict(X_test)

#对比两者的性能
print('The Accuracy of SVC:', svc.score(X_test, y_test))
print('The Accuracy of SVC after PCA:', pca_svc.score(X_test, y_test))

输出结果:

使用ARI指标计算评估聚类性能: 0.6632289468987028

The Accuracy of SVC: 0.9187534780189204
The Accuracy of SVC after PCA: 0.9287701725097385

在这里插入图片描述

小结

对于聚类算法,评估其性能可以考虑以下两种方式:①对于有标签的数据集,可以和上述代码一样采用Adjusted Rand Index(ARI),ARI指标计算方式与计算准确性(Accuracy)类似;②如果用于评估的数据没有所属类别,那么可以使用轮廓系数(Silhouette Coefficient)来度量聚类结果的质量,其取值为[-1, 1],数值越大表示聚类效果越好。

  • K-Means所采用的迭代式算法简单实用,但是缺陷在于容易收敛到局部最优解,还有必须预先设定簇的数量
  • 可以通过“肘部”观察法用于粗略预估相对合理的类簇个数。因为K-Means模型最终期望所有数据点到其所属的类簇距离的平方和趋于稳定,因此可以绘制一条曲线,x轴为k的大小,y轴为所有数据到其所属簇距离的平方和,然后找到肘部。
  • 对比PCA前后的SVC分类性能,可以发现两者差别并不大,大概失去了2%左右的预测准确性,但是却降低了68.75%的维度。
  • 经过大量实践证明,相较于损失少部分模型性能,维度压缩能节省大量用于模型训练的时间,使得PCA带来的模型综合效率变得更为划算。

猜你喜欢

转载自blog.csdn.net/weixin_43756456/article/details/86351409