赵走x博客
网站访问量:151569
首页
书籍
软件
工具
古诗词
搜索
登录
深入浅出Python机器学习:31、自动特征选择
深入浅出Python机器学习:30、数据“升维”
深入浅出Python机器学习:29、数据表达
深入浅出Python机器学习:28、聚类算法
深入浅出Python机器学习:27、特征提取
深入浅出Python机器学习:26、数据降维
深入浅出Python机器学习:25、数据预处理
深入浅出Python机器学习:24、神经网络实例一一手写识别
深入浅出Python机器学习:23、神经网络的原理及使用
深入浅出Python机器学习:22、神经网络的前世今生
深入浅出Python机器学习:21、SVM 实例一一波士顿房价回归分析
深入浅出Python机器学习:20、SVM 的核函数与参数选择
深入浅出Python机器学习:19、支持向量机SVM 基本概念
深入浅出Python机器学习:18、随机森林实例一一要不要和中目亲对象进一步发展
深入浅出Python机器学习:17、随机森林
深入浅出Python机器学习:16、决策树
深入浅出Python机器学习:15、朴素贝叶斯实战一一判断肿瘤是良性还是恶性
深入浅出Python机器学习:14、朴素贝叶斯算法的不同方法
深入浅出Python机器学习:13、朴素贝叶斯基本概念
深入浅出Python机器学习:12、使用L1 正则化的线性模型一一套索回归
深入浅出Python机器学习:11、使用L2 正则化的线性模型一一岭回归
深入浅出Python机器学习:10、最基本的线性模型一一线性回归
深入浅出Python机器学习:9、线性模型的墓本概念
深入浅出Python机器学习:8、K 最近邻算法项目实战一一酒的分类
深入浅出Python机器学习:7、K最近邻算法用于回归分析
深入浅出Python机器学习:6、K最近邻算法处理多元分类任务
深入浅出Python机器学习:5、k最近邻算法在分类任务中的应用
深入浅出Python机器学习:4、K 最近邻算法的原理
深入浅出Python机器学习:3、一些必需库的安装及功能简介
深入浅出Python机器学习:2、基于python i吾言的环境配置
深入浅出Python机器学习:1、概述
人脸数据集加载faces = fetch_lfw_people()报错
31、直方图
74、插件开发:Android端API实现
Python3之socket编程--3:基于UDP的套接字
15、使用 jQuery 处理 Ajax 请求
深入浅出Python机器学习:28、聚类算法
资源编号:75928
人工智能
深入浅出Python机器学习
热度:109
可能读者朋友们还记得我们在第1章中就提到过,有监督学习主要用于分类和回归,而无监督学习的一个非常重要的用途就是对数据进行聚类。当然了,聚类和分类有一定的相似之处,分类是算法基于已有标签的数据进行学习并对新数据进行分类,而聚类则是在完全没有现有标签的情况下,由算法“猜测”哪些数据像是应该“堆”在一起的,并且让算法给不同的“堆”里的数据贴上一个数字标签。在本节中,我们会重点了解K均值C(k-Means ) 聚类、凝聚聚类,以及DBSCAN 这几个算法。
可能读者朋友们还记得我们在第1章中就提到过,有监督学习主要用于分类和回归,而无监督学习的一个非常重要的用途就是对数据进行聚类。当然了,聚类和分类有一定的相似之处,分类是算法基于已有标签的数据进行学习并对新数据进行分类,而聚类则是在完全没有现有标签的情况下,由算法“猜测”哪些数据像是应该“堆”在一起的,并且让算法给不同的“堆”里的数据贴上一个数字标签。在本节中,我们会重点了解K均值C(k-Means ) 聚类、凝聚聚类,以及DBSCAN 这几个算法。 # 1、 k均值聚类算法 在各种聚类算法中, K 均值聚类算法可以说是最简单的。但是简单不代表不好用, K均值绝对是在聚类中用的最多的算法。它的工作原理是这样的:假设我们的数据集中的样本因为特征不同,像小沙堆一样散布在地上, K 均值算法会在小沙堆上插上旗子。而第一遍插的旗子并不能很完美地代表沙堆的分布,所以K 均值还要继续,让每个旗子能够插到每个沙堆最佳的位置上,也就是数据点的均值上,这也是K 均值算法名字的由来。 接下来会一直重复上述的动作,直到找不出更好的位置,如图9 - 23 所示。  图9 - 23 K 均值算法对数据进行聚类 下面我们尝试用手工生成的数据集来展示一下K 均值聚类算法的工作原理,输入代码如下: ``` import matplotlib.pyplot as plt # 导入数据集生成工具 from sklearn.datasets import make_blobs # 生成分类数为1 的数据集 blobs = make_blobs(random_state=1, centers=1) X_blobs = blobs[0] # 绘制散点图 plt.scatter(X_blobs[:, 0], X_blobs[:, 1], c='r', edgecolors='k') # 显示图像 plt.show() ``` 这段代码,主要是生成一“坨”没有类别的数据点,并且用散点图把它们画出来。 运行代码,会得到如图9 - 24 所示的结果。  图9-2 4 使用make b l obs 生成的无分类数据 [结果分析]从图中可以看到,由于我们指定了make_blobs 的centers 参数为1 , 因此所有的数据都属于1类, 并没有差别。 下面我们使用K 均值来帮助这些数据进行聚类,输入代码如下: ``` import matplotlib.pyplot as plt # 导入数据集生成工具 from sklearn.datasets import make_blobs import numpy as np # 导入KMeans 工具 from sklearn.cluster import KMeans # 生成分类数为1 的数据集 blobs = make_blobs(random_state=1, centers=1) X_blobs = blobs[0] # #要求KMeans 将数据聚为3 类 kmeans = KMeans(n_clusters=3) # 拟合数据 kmeans.fit(X_blobs) # 下面是用来画图的代码 x_min, x_max = X_blobs[:, 0].min() - 0.5, X_blobs[:, 0].max() + 0.5 y_min, y_max = X_blobs[:, 1].min() - 0.5, X_blobs[:, 1].max() + 0.5 xx, yy = np.meshgrid(np.arange(x_min, x_max, .02), np.arange(y_min, y_max, .02)) Z = kmeans.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure(1) plt.clf() plt.imshow(Z, interpolation='nearest', extent=(xx.min(), xx.max(), yy.min(), yy.max()), cmap=plt.cm.summer, aspect='auto', origin='lower') plt.plot(X_blobs[:, 0], X_blobs[:, 1], 'r.', markersize=5) # 用蓝色叉号代表聚类的中心 centroids = kmeans.cluster_centers_ plt.scatter(centroids[:, 0], centroids[:, 1], marker='x', s=150, linewidths=3, color='b', zorder=10) plt.xlim(x_min, x_max) plt.ylim(y_min, y_max) plt.xticks(()) plt.yticks(()) # 显示图像 plt.show() ``` 会得到如图9-25 所示的结果。  图9-25 :使用K 均值算法进行的聚类 [结果分析]在上一段代码中,我们指定了K 均值的n_clusters 参数是3 ,所以K均值将数据点聚为3 类,图中的3 个蓝色的×号,就代表了K 均值对数据进行聚类的3个中心。 那么K 均值怎样来表示这些聚类呢?我们用下面这行代码来看一下。 ``` # 打印KMeansi进行聚类的标签 print('K均值的聚类标签:{}'.format(kmeans.labels_)) ``` 运行结果: ``` K均值的聚类标签:[2 2 0 1 1 1 2 2 0 1 2 1 2 0 2 1 1 2 0 0 1 0 2 2 2 2 1 2 2 2 0 0 2 2 1 0 1 0 2 0 1 2 0 0 1 1 1 2 0 2 0 2 1 0 1 1 0 1 1 2 1 0 1 2 0 1 0 0 2 1 1 2 1 1 1 2 1 2 2 0 1 0 1 1 0 2 1 2 0 0 1 2 0 0 1 1 2 1 1 2] ``` [结果分析] 从结果中可以看到, K 均值对数据进行的聚类和分类有些类似,是用0 、1 、2 三个数字来代表数据的类,并且储存在.labels_属性中。从好的一面来看, K 均值算法十分简单而且容易理解,但它也有很明显的局限性。例如,它认为每个数据点到聚类中心的方向都是同等重要的。这样一来,对于“形状”复杂的数据集来说, K 均值算法就不能很好地工作。在讲完后面的算法后,我们会详细对比它们的差异。 # 2、 凝聚聚类算法 要理解凝聚聚类算法其实很简单, 也很有意思。在夏天观察雨后的荷叶,会发现一个有意思的现象:在重力的作用下,荷叶上的小水珠会向荷叶中心聚集,并且凝聚成一个大水珠,这也可以用来形象地描述凝聚聚类算法。实际上,凝聚聚类算法是一揽子算法的集合,而这一揽子算法的共同之处是,它们首先将每个数据点看成是一个聚类,也就是荷叶上的小水珠,然后把相似的聚类进行合井,形成了一个较大的水珠。然后重复这个过程,直到达到了停止的标准。那么停止的标准是什么昵?在scikit-learn 中, 停止的标准是剩下的“大水珠”的数量。 下面我们还是用一个图像来对凝聚聚类算法的工作机制进行说明,输入代码如下: ``` import matplotlib.pyplot as plt # 导入dendrogram和ward工具 from scipy.cluster.hierarchy import dendrogram, ward # 导入数据集生成工具 from sklearn.datasets import make_blobs # 生成分类数为1 的数据集 blobs = make_blobs(random_state=1, centers=1) X_blobs = blobs[0] # 使用连线的方式进行可视化 linkage = ward(X_blobs) dendrogram(linkage) ax = plt.gca() # ax.add_patch() # 设定横纵轴标签 plt.xlabel('Sample index') plt.ylabel('Cluster distance') # 显示图像 plt.show() ``` 为了和K 均值算法进行比较,这里我们仍然使用了在K 均值算法中生成的数据集。 运行代码,会得到如图9-27 所示的结果。  图9-27 凝聚聚类算法工作原理展示 {结果分析] 从图9-27 中可以看到,凝聚聚类算法是自下而上, 不断地合并相似的聚类中心,以便让类别越来越少,同时每个聚类中心的距离也就原来越远。这种逐级生成的聚类方法称为Hierarchy clustering。 当然, 和K 均值聚类算法比较类似,凝聚聚类算法也无法对“形状”复杂的数据进行正确的聚类。因此接下来我们要介绍一个新的算法: DBSCAN 。 # 3、DBSCAN算法 如果只是看名字的话, 或许会觉得这个算法和“数据库扫描”有什么关系, 因为直观看起来,它像是DataBase Scan 的缩写。然而实际上并不是这样, 这个算法的全名称为“基于密度的有噪声应用空间聚类” ( Density-based spatial clustering of applications with noise )。这是一个很长且拗口的名字, 但是也反应了它的工作原理。DB SCAN 是通过对 特征空间内的密度进行检测, 密度大的地方它会认为是一个类,而密度相对小的地方它会认为是一个分界线。也正是由于这样的工作机制,使得DB SCAN 算法不需要像K 均值或者是凝聚聚类算法那样在一开始就指定聚类的数量n_clusters 。 下面我们再用之前make_blobs 生成的数据集来展示一下DBSCAN 的工作机制,输入代码如下: ``` # 导入DBSCAN from sklearn.cluster import DBSCAN import matplotlib.pyplot as plt # 导入数据集生成工具 from sklearn.datasets import make_blobs # 生成分类数为1 的数据集 blobs = make_blobs(random_state=1, centers=1) X_blobs = blobs[0] db = DBSCAN() # 使用DBSCAN 拟合数据 clusters = db.fit_predict(X_blobs) # 绘制散点图 plt.scatter(X_blobs[:, 0], X_blobs[:, 1], c=clusters, cmap=plt.cm.cool, s=60, edgecolors='k') # 设置横纵轴标签 plt.xlabel("Feature 0") plt.ylabel("Feature 1") # 显示图像 plt.show() ``` 运行代码, 会得到如图9-28 所示的结果。  图9 -28 DBSCAN 算法对make blobs 数据集的聚类结果 {结果分析] 从图9 -28 中,我们看到经过DBSCAN 的聚类, 数据点被标成了不同的深洗程度。那么是不是表示DBSCAN 把数据类聚成了两类呢? 我们试着输入代码如下: ``` # 打印聚类个数 print('聚类标签为:{}'.format(clusters)) ``` 运行结果: ``` 聚类标签为:[-1 0 -1 0 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 -1 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 -1 0 0 -1 0 0 -1 0 0 0 0 0 0 0 0 -1 0 0 0 -1] ``` [结果分析] 奇怪的是,在聚类标签中, 居然出现了一1 , 这是怎么回事呢?原来在DBSCAN 中,-1 代表该数据点是噪声。在图9-27 中,我们看到中间深色的数据点密度相对较大,因此DB SCAN 把它们归到一“坨”,而外围的浅色的数据点, DB SCAN 认为根本不属于任何一类,所以放进了“噪声”这个类别。 说到这里,就不能不提DB SCAN 中两个非常重要的参数: 一是eps ;一个是min_samples 。eps 指定的是考虑划入同一“坨”的样本距离有多远, eps 值设置得越大,则聚类所覆盖的数据点越多,反之则越少。默认情况下eps 的值为0 . 5 。接下来我们试着把eps 值调大一些,看会发生什么。输入代码如下: ``` # 导入DBSCAN from sklearn.cluster import DBSCAN import matplotlib.pyplot as plt # 导入数据集生成工具 from sklearn.datasets import make_blobs # 生成分类数为1 的数据集 blobs = make_blobs(random_state=1, centers=1) X_blobs = blobs[0] #设置DBSCAN的eps 参数为2 db = DBSCAN(eps=2) # 重新拟合数据 clusters = db.fit_predict(X_blobs) # 绘制散点图 plt.scatter(X_blobs[:, 0], X_blobs[:, 1], c=clusters, cmap=plt.cm.cool, s=60, edgecolors='k') # 设置横纵轴标签 plt.xlabel("Feature 0") plt.ylabel("Feature 1") # 显示图像 plt.show() ``` 在这段代码中, 我们手动指定了eps 值为2 ,运行代码会得到如图9-30 的结果。  图9-30 e ps 值为2 时DB S CAN 进行的聚类 [ 结果分析] 现在我们看到,所有的数据点都变成了浅色,这并不是说所有数据点都变成了噪声, 而是说所有的数据点都被归入同一“ 坨” 中。这是因为我们增加了eps的取值后, 让D SCAN 把距离更远的数据点也拉到这个聚类中了。 而min_samples 参数指定的是在某个数据点周围, 被看成是聚类核心点的个数,min_ samples 值越大, 则核心数据点越少, 噪声也就越多: 反之min_sample 值越小, 噪声也就越少。默认的min_samples 值是2 。下面我们用图形进行展示,输入代码如下: ``` # 导入DBSCAN from sklearn.cluster import DBSCAN import matplotlib.pyplot as plt # 导入数据集生成工具 from sklearn.datasets import make_blobs # 生成分类数为1 的数据集 blobs = make_blobs(random_state=1, centers=1) X_blobs = blobs[0] #设置DBSCAN的eps 参数为2 db = DBSCAN(min_samples=20) # 重新拟合数据 clusters = db.fit_predict(X_blobs) # 绘制散点图 plt.scatter(X_blobs[:, 0], X_blobs[:, 1], c=clusters, cmap=plt.cm.cool, s=60, edgecolors='k') # 设置横纵轴标签 plt.xlabel("Feature 0") plt.ylabel("Feature 1") # 显示图像 plt.show() ``` 现在我们指定了min_s amples 的值为20 ,运行代码, 将得到如图9 - 31 所示的结果。  图9-31 min samples 为20 的DB SCAN 聚类 {结果分析] 如果对比图9 -31 与图9-28 的话,你会发现,浅色的数据点变多了,也就是噪声变多了。而深色的数据点,也就是聚类中被划为类别1 的数据点变少了。 综上,虽然DB SCAN 并不需要我们在开始训练算法的时候就指定clusters 的数量,但是通过对eps 和min_samples 参数赋值,相当于间接地指定了clusters 的数量。尤其是eps 参数尤为重要,因为它规定了某一“地”的范围大小。而且在实际应用中,如果将数据集先用MinMaxScaler 或者S tandardScaler 进行预处理,那么DB SCAN 算法的表现会更好(因为这两种预处理方法把数据的范围控制得比较集中)。 # 4、 小结 在本章中,我们一起初步了解了数据预处理、数据降维、特征提取和聚类算法这几个方面的知识。对于机器学习来说,能够合理有效地对数据进行表达是至关重要的。因此数据预处理、降维、特征提取在我们对数据进行准备工作的过程中起着非常关键的作用。 而对于没有分类标签的数据来说,无监督学习的聚类算法可以帮助我们更好地理解数据集,并且为进一步训练模型打好基础。截至目前,读者朋友们基本已经对机器学习中常用的一些算法有了一定的了解,希望大家在阅读过后,可以尝试动手在scikit-learn 内置的一些数据集中进行实验一一学习一门技巧最好的办法就是使用它。 下一章中,我们会和读者朋友们一起就数据表达和特征工程这两个方面的知识进行探讨和研究,希望能够对大家有进一步的帮助。