文章目录

  • 聚类算法
    • 1 k-Means算法
      • 1.1 基本概念
      • 1.2 k-Means算法原理
      • 1.3 k-Means算法的可视化演示
      • 1.4 实验
    • 2 DBSCAN算法
      • 2.1 基本概念
      • 2.2 DBSCAN算法原理
      • 2.3 DBSCAN算法的可视化演示
      • 2.4 实验
    • 总结

聚类算法

在机器学习中,若训练样本的标记信息未知,则称为无监督学习。无监督学习通过对无标记训练样本的学习来寻找这些数据的内在性质,其主要的工具就是聚类算法。

1 k-Means算法

k-Means算法也称为k-平均或k-均值算法,是一种聚类算法,它是一种基于相似性的无监督学习,通过比较样本之间的相似性,将较为相似的样本划分到同一个类别中。由于k-Means算法简单、易于实现的特点,故在图像分割中得到广泛的应用。

1.1 基本概念

簇:把数据分为几类,每一类就是一个簇,也是k的由来。

欧式距离(欧几里得距离):计算两个点之间的距离,即计算数据与指定点的距离的衡量。二维空间的两点欧式距离表示为:


两个n向量a和b之间的欧式距离:

该式也可以表示成向量运算的形式:

质心:每次分类后求得的均值。

1.2 k-Means算法原理

k-Means算法主要分为以下三个步骤:

  1. 初始化k个聚类中心,即将数据集分为k个簇,这个取值通常并不是一次性到位的,需要取值进行对比,最终得到一个最合适的取值,生成k个聚类中心。
  2. 计算出每个对象跟这k个中心的距离,假如x跟y这个中心的距离最小,那么x属于y这个中心。这一步就可以得到初步的k个聚类。

对于一个表示为m*n矩阵的样本,假设归为k个类,分别为{C1, C2, ···, Ck}。

  1. 在第二步得到的每个聚类分别计算出新的聚类中心,和旧的聚类中心进行对比,假如不相同则继续执行第二步,不断迭代,直到新旧两个中心相同,说明聚类不可变,已经成功。即求完质心后再求距离,不会有点进行浮动,这样相当于训练结束。

k-Means算法的目标是使得每一个样本X被划分到最相似的类别中,利用每个类别的 样本重新计算聚类中心Ck:

k-Means算法的停止条件是最终的聚类中心不再改变,此时所有的样本被划分到了最近的聚类中心所属的类别中:

其中样本X(i)数据集中的第i行,Cj表示的是第j个聚类中心。

1.3 k-Means算法的可视化演示

在演示模型中随机生成一些数据点,并以高斯分布的形式出现:


然后添加三个随机的质心作为初始化的点:


可以看到这三个点距离很近,就意味着他们可能并不能对这三堆数据进行正确的分组。换句话说就是初始点的选择会影响最终的分类结果。接下来就要用所有的数据对这个三个点求距离来看那些数据离哪个点最近。那么就认为他们是一类。


第一步之后,可以看到所有的数据点都被分类。接下来要对三堆数据重新求质心,即对他们每一类求均值。


更新完质心即新的质心到了图中的新位置。接下来做相同动作,针对新的三个质心求距离将数据重新分类。一直重复直到数据点不发生变化。


可以看出正是由于初始的质心选择不好,所以导致没有一个相对正确的结果。那么重新选择三个质心,完成上述的步骤。



可以看到重新选择了三个初始点,得到的结果相对正确了许多。

接下来选择不规则的图形进行演示。



上图对一个笑脸图进行分类发现得到的并不是我们想要的结果,那就说明k-Means算法对于任意形状的图形分类不一定得到正确的结果,因为它只是求一个距离的最小值并按这个距离来进行分类。

所以重新选择一个规则图形进行演示发现的确可以得到一个较好的分类结果。


但是观察上图,发现数据中有7个明显的圆,选择7个质心效果就比较好,但是如果只选择6个质心,如上图。可以发现他们对于多出来的一个圆的分类达不到想要的效果,分类效果确实不如7个质心。所以这就说明了在初始k值的选择对最后结果的影响还是比较大的。

1.4 实验

利用Python代码实现给定的随机数据点聚类分析。

import numpy as np
import random
import matplotlib.pyplot as pltdef k_means(data, k):sample_num = data.shape[0]center_index = random.sample(range(sample_num), k)cluster_cen = data[center_index, :]is_change = 1cat = np.zeros(sample_num)while is_change:is_change = 0for i in range(sample_num):min_distance = 100000min_index = 0for j in range(k):sub_data = data[i, :] - cluster_cen[j, :]distance = np.inner(sub_data, sub_data)if distance < min_distance:min_distance = distancemin_index = j + 1if cat[i] != min_index:is_change = 1cat[i] = min_indexfor j in range(k):cluster_cen[j] = np.mean(data[cat == j + 1], axis = 0)return cat, cluster_cenif __name__ == '__main__':cov = [[1,0], [0,1]]mean1 = [1,-1] x1 = np.random.multivariate_normal(mean1, cov, 200)mean2 = [5.5,-4.5]x2 = np.random.multivariate_normal(mean2, cov, 200)mean3 = [1,4]x3 = np.random.multivariate_normal(mean3, cov, 200)mean4 = [6,4.5]x4 = np.random.multivariate_normal(mean4, cov, 200)mean5 = [9,0.0]x5 = np.random.multivariate_normal(mean5, cov, 200)X = np.vstack((x1,x2,x3,x4,x5))fig1 = plt.figure(1)p1 = plt.scatter(x1[:,0], x1[:,1],marker = 'o', color = 'r', label = 'x1')p2 = plt.scatter(x2[:,0], x2[:,1],marker = '+', color = 'm', label = 'x2')p3 = plt.scatter(x3[:,0], x3[:,1],marker = 'x', color = 'b', label = 'x3')p4 = plt.scatter(x4[:,0], x4[:,1],marker = '*', color = 'g', label = 'x4')p5 = plt.scatter(x5[:,0], x5[:,1],marker = '+', color = 'y', label = 'x5')plt.title('original data')plt.legend(loc = 'upper right')cat, cluster_cen = k_means(X,5)print('the number of cluster 1:', sum(cat ==1))print('the number of cluster 2:', sum(cat ==2))print('the number of cluster 3:', sum(cat ==3))print('the number of cluster 4:', sum(cat ==4))print('the number of cluster 5:', sum(cat ==5))fig2 = plt.figure(2)for i, m, lo, label in zip(range(5), ['o', '+', 'x', '*', '+'], ['r', 'm', 'b', 'g', 'y'], ['x1', 'x2', 'x3', 'x4', 'x5']):p = plt.scatter(X[cat == (i + 1), 0], X[cat == (i + 1), 1], marker = m, color = lo, label = label)plt.legend(loc = 'upper right')plt.title('the clusting result')plt.show()

这张图片显示的是打印出的每一类的数据点的个数。


这两张图分别表示原始的数据点的分布和聚类后的分布结果,可以看出通过k-Means聚类将图中的数据点较为均匀的分成5类。

可以改变参数观察实验结果:



上面两张图分别是分6类和分4类的实验结果,可以明显看出当分成6类时均匀想过明显不如5个中心的效果要好。而当只有4个聚类中心时发现左侧两簇距离明显很近而右边两簇距离较远,效果也不如5个聚类中心。

2 DBSCAN算法

DBSCN算法可以用力解决k-Means算法中的一些不好聚类的问题,例如前文实验中的笑脸图,k-Means无法对这种特殊形状来分组。

2.1 基本概念

DBSCAN算法是一种基于密度的聚类算法。这个密度就是指一个点周围包含的点的个数。
这类密度聚类算法一般假定类别可以由样本分布的紧密程度决定。同一类样本之间是紧密相连的,也就是说在该类别任意样本周围不远处一定有同类别的样本存在。通过将紧密相连的样本划为一类就得到了一个聚类类别。通过将所有各组紧密相连的样本划分为各个不同的类别,就得到了最终的所有聚类类别结果。

核心点:某个点的密度达到算法设定的阈值。例如在这个点邻域中的点的个数超过了设定值,那么这个点就是一个核心点。

距离阈值:点的半径r,即设定邻域的大小。

直接密度可达:某点a在点b的r距离阈值内,且b是核心点,则称a,b直接密度可达。

密度可达:如果点a和b直接密度可大,b和c直接密度可达,并且a和c不是直接密度可达,则称a和c密度可达。

2.2 DBSCAN算法原理

DBSCAN的聚类定义很简单,即由密度可达关系导出的最大密度相连的样本集合,即为最终聚类的一个类别或者说是一个簇。

它的方法很简单,它任意选择一个没有类别的核心对象作为种子,然后找到所有这个核心对象能够密度可达的样本集合,即为一个聚类簇。接着继续选择另一个没有类别的核心对象去寻找密度可达的样本集合,这就得到另一个聚类簇,一直运行到所有核心对象都有类别为止。

但是需要考虑以下的三个问题:

  1. 一些异常样本点或者说少量游离于簇外的样本点,它们不在任何一个核心对象的周围,这些点被标记为噪声点。
  2. 如何度量某样本点和核心对象样本的距离,一般采用最近邻思想。
  3. 某些样本可能到两个核心对象的距离都小于距离阈值,但这两个核心对象由于不是密度可达又不属于同一聚类簇,那么一般来说采用先来后到的思想。这就说明DBSCAN并不是一个完全稳定的算法。

2.3 DBSCAN算法的可视化演示

选择高斯分布的数据


此时默认的距离阈值是1,密度阈值是4。开始运行该算法。



算法开始运行后会在数据点中随机寻找一个点作为核心点以1为半径开始画圈,当第一堆再也找不到核心点之后,就在这一堆以外的数据中随机选择核心点继续开始迭代分组。它相比与k-Means更智能的地方就在于不断自主的扩展、传播来进行分组。最后图中的白色圆点就是噪声点。

修改半径观察分组结果。

将半径扩大后发现分组效果更好,这是由于增大半径后囊括进行的数据就更多了,减少了噪声点。

接下来观察笑脸图的分组情况,选择距离阈值为1,密度阈值为4。


可以看到此时笑脸中的数据点被分为5组。这里发现,正式由于半径距离阈值的选择不够恰当,就导致笑脸脸部圆圈被分为了两组,而非我们想要获取的一组的样式,不是特别正确,但是眼睛和嘴部相对正确。

接下来调节距离阈值为1.22,密度阈值设为2,观察结果。

此时分类的效果就比较正确,可见DBSCAN算法对初始值设定的要求是很高的,初始值选择恰当得到的效果肯定更好。

对于初始值的选择问题,下图更能说明问题。


这里我们取密度阈值为4,发现只有右上部分一些点可以得到正确的划分,而其他点全部被归为噪声点,能分的组比不能分的组还要少。将距离阈值改为2,半径改为1.74,发现分组效果确实是好了一些。足以说明,对于距离阈值和密度阈值的初始值选择在这个算法中是非常重要的。

2.4 实验

用Python代码实现密度聚类。

输入一组数据集,每三个是一组,分别是西瓜的编号、密度和含糖量。

data = """1,0.697,0.46,2,0.774,0.376,3,0634,0.264,4,0.608,0.318,5,0.556,0.215,6,0.403,0.237,7,0.481,0.149,8,0.437,0.211,9,0.666,0.091,10,0.243,0.267,11,0.245,0.057,12,0.343,0.099,13,0.639,0.161,14,0.657,0.198,15,0.36,0.3716,0.593,0.042,17,0.719,0.103,18,0.359,0.188,19,0.339,0.241,20,0.282,0.257"""

接下来数据处理,dataest是30个样本的列表。

a = data.split(',')
dataset = [(float(a[i]), float(a[i + 1])) for i in range(1, len(a - 1), 3)]

计算欧几里得距离,a,b分别为两个元组。

def dist(a, b):return math.sqrt(math.pow(a[0] - b[0], 2) + math.pow(a[1] - b[1], 2))

算法模型。

def DBSCAN(D, e, Minpts):T = set()k = 0C = []P = set(D)for d in D:if len([i for i in D if dist(d, i) <= e]) >= Minpts:T.add(d)while len(T):P_old = Po = list(T)[np.random.randint(0, len(T))]P = P - set(o)Q = []Q.append(o)while len(Q):q = Q[0]Nq = [i for i in D if dist(q,i) <= e]if len(Nq) >= Minpts:S = P & set(Nq)Q += (list(S))P = P - SQ.remove(q)k += 1Ck = list(P_old - P)T = T - set(Ck)C.append(Ck)return C

画图,画出DBSCAN算法对随机数据进行聚类的效果。

def draw(C):colValue = ['r','y','g','b','c','k','m']for i in range(len(C)):coo_X = []coo_Y = []for j in range(len(C[i])):coo_X.append(C[i][j][0])coo_Y.append(C[i][j][1])pl.scatter(coo_X, coo_Y, marker = 'x', color = colValue[i % len(colValue)], label = i)pl.legend(loc = 'upper right')pl.show()C = DBSCAN(dataset, 0.11, 5)
draw(C)

得到的结果如图所示:
下面利用Python代码对随机数据进行DBSCAN聚类分析:

import numpy as np
import matplotlib.pyplot as plt
cs = ['black', 'blue', 'brown', 'red', 'yellow', 'green']
class NpCluster(object):def __init__(self):self.key = []self.value = []def append(self, data):if str(data) in self.key:returnself.key.append(str(data))self.value.append(data)def exist(self, data):if str(data) in self.key:return Truereturn Falsedef __len__(self):return len(self.value)def __iter__(self):self.times = 0return selfdef __next__(self):try:ret = self.value[self.times]self.times += 1return retexcept IndexError:raise StopIteration()
def create_sample():np.random.seed(10)  # 随机数种子,保证随机数生成的顺序一样n_dim = 2num = 100a = 3 + 5 * np.random.randn(num, n_dim)b = 30 + 5 * np.random.randn(num, n_dim)c = 60 + 10 * np.random.randn(1, n_dim)data_mat = np.concatenate((np.concatenate((a, b)), c))ay = np.zeros(num)by = np.ones(num)label = np.concatenate((ay, by))return {'data_mat': list(data_mat), 'label': label}def region_query(dataset, center_point, eps):result = NpCluster()for point in dataset:if np.sqrt(sum(np.power(point - center_point, 2))) <= eps:result.append(point)return resultdef dbscan(dataset, eps, min_pts):noise = NpCluster()visited = NpCluster()clusters = []for point in dataset:cluster = NpCluster()if not visited.exist(point):visited.append(point)neighbors = region_query(dataset, point, eps)if len(neighbors) < min_pts:noise.append(point)else:cluster.append(point)expand_cluster(visited, dataset, neighbors, cluster, eps, min_pts)clusters.append(cluster)for data in clusters:print(data.value)plot_data(np.mat(data.value), cs[clusters.index(data)])if noise.value:plot_data(np.mat(noise.value), 'green')plt.show()def plot_data(samples, color, plot_type='o'):plt.plot(samples[:, 0], samples[:, 1], plot_type, markerfacecolor=color, markersize=14)def expand_cluster(visited, dataset, neighbors, cluster, eps, min_pts):for point in neighbors:if not visited.exist(point):visited.append(point)point_neighbors = region_query(dataset, point, eps)if len(point_neighbors) >= min_pts:for expand_point in point_neighbors:if not neighbors.exist(expand_point):neighbors.append(expand_point)if not cluster.exist(point):cluster.append(point)init_data = create_sample()
dbscan(init_data['data_mat'], 10, 3)

得到的效果如图所示:

由上图可以看出,对于随机生成的不规则数据点,DBSCAN算法可以很好的对数据点进行划分,对于单独的一个噪声点可以较好的将其区分出来。

若是改变距离阈值和密度阈值,得到的效果并不是很满意,会有一些临近的数据点被错误的认为成噪声点。

总结

聚类算法的思想是将数据划分为若干个不相交的子集,称为簇,每个簇潜在对应某一个概念。但是聚类算法只生成簇结构,每个簇所代表的概念的语义由使用者自己解释。也就是说聚类算法并不会告诉你:它生成的这些簇分别代表什么意义,它只会告诉你算法已经将数据集划分为这些不相关的簇了。

这类算法作为一种探索性的分析方法,用来分析数据的内在特点,寻找数据之间的分布规律,同时在分类的处理过程中,首先对需要分类的数据进行聚类,然后对聚类出的结果的每一个簇进行分类,实现的是对数据的预处理。

k-Means算法就是通过某种相似性度量的方法,将较为相似的个体划分到同一个类别中。对于不同的应用场景,有着不同的相似性度量方法,为了度量样本X和样本Y之间的相似性一般会定义一个距离函数来分析相似性。虽然算法思想和计算都很简单,但是k的选取是需要不断实验的,同时如果在数据量特别大的时候,要计算每个点的欧式距离计算量过于巨大。对任意图像的处理结果也不好确定,毕竟只是以距离作为衡量标准,将相近的作为一组。

DBSCAN算法是一种很典型的密度聚类算法,相比于k-Means算法既适用于凸样本集也适用于非凸样本集。也就是样本集的密度不均匀、聚类间距相差很大时,用DBSCAN算法并不是很合适。与k-Means相比最大的不同就是在于不需要输入类别数k,其最大的优势更是在于可以发现任意形状的聚类簇,同时可以在聚类的同时发现异常点,聚类的结果偏差也不是很大,但是需要对距离阈值和密度阈值联合调参。

机器学习——聚类算法相关推荐

  1. 炼数成金数据分析课程---17、机器学习聚类算法(后面要重点看)

    炼数成金数据分析课程---17.机器学习聚类算法(后面要重点看) 一.总结 一句话总结: 大纲+实例快速学习法 主要讲解常用聚类算法(比如K-means等)的原理及python代码实现:后面学习聚类的 ...

  2. 基于机器学习聚类算法寻找美国职业篮球联赛NBA中的超级强队

    聚类算法 聚类算法是机器学习中经典的非监督学习算法之一,相比于分类算法,聚类不依赖预定义的样本标签,而是让算法通过对数据的学习从而找到其内部的规律,该算法对有相同特征的样本进行聚类,聚类的时候,我们并 ...

  3. 机器学习 —— 聚类算法

    K均值算法(K-means)聚类 一.K-means算法原理 聚类的概念:一种无监督的学习,事先不知道类别,自动将相似的对象归到同一个簇中. K-Means算法是一种聚类分析(cluster anal ...

  4. 周志华机器学习——聚类算法。

    聚类算法 聚类算法是一种经典的无监督学习方法,无监督学习的目标是通过对无标记训练样本的学习,发掘和揭示数据集本身的潜在结构与j规律,即不依赖于训练数据集的类标记信息.聚类则试图将数据集的样本划分为若干 ...

  5. 机器学习 聚类算法总结

    目录 一.聚类算法简述 二.K-Means算法实现案例一--简单实现 三.K-Means算法实现案例二--案例实现 四.K-Means算法实现案例三 五. 轮廓系数 六.CH系数 七.聚类实现图像压缩 ...

  6. 机器学习----聚类算法

    1.聚类算法介绍 1.1 聚类算法在现实中的应用 用户画像,广告推荐,搜索引擎的流量推荐,恶意流量识别 基于位置信息的商业推送,新闻聚类,筛选排序 图像分割,降维,识别:离群点检测:信用卡异常消费:发 ...

  7. 机器学习---聚类算法

    目录 [写在前面] 1.确认安装有scikit-learn库 2.使用 make _ classification ()建立数据集 3.使用模型进行分类 头文件汇总 亲和力传播 聚合聚类 BIRCH ...

  8. 机器学习--聚类算法(无监督学习)--K-Menas/BIRCH/CURE/DBSCAN/MDCA算法理论

    目录 一 聚类算法概述 1 聚类的概念 2 聚类算法的评价指标 1)轮廓系数(无需目标属性的评价指标) 二 基于划分的聚类算法(K-Means) 1 K-Means算法 1)算法流程 2)算法的优缺点 ...

  9. 机器学习——聚类算法的C++简易实现(k=3)

    #include <iostream> #include <math.h> using namespace std;//定义数据集 double dataSet[30][2] ...

最新文章

  1. IP 管理,几多欣喜几多忧
  2. 西南科技大学智能车竞赛 线上比赛
  3. spring boot整合mail
  4. 服务器lIS绑定网站,DataList 中动态绑定服务器子控件的代码
  5. this ts 方法获取_vue+typescript项目中用this.$refs和原生方法获取的dom有什么区别
  6. ScrollView HorizontalScrollView
  7. _Linux进程信号详解
  8. JAVA能做flash游戏吗_FLASH+JAVA开发实时网络游戏 (转:闪客帝国)
  9. Python Day2
  10. 如何修改hosts文件权限
  11. html登陆滑动验证,JavaScript实现登录滑块验证
  12. iconfont添加新图标_IconFont图标引用的方法步骤(代码)
  13. 高考前最后一天,AI 监考老师已就位
  14. Markdown常用字体 大小 颜色和背景设置
  15. win10投影到电脑无法成功,一直显示即将投影
  16. svm 预测标签的概率输出
  17. 用tableau绘制地图
  18. 图像检测与分割标注文件XML/JSON/TXT一键批量转换编辑软件
  19. 综述 | 一文读懂自然语言处理NLP(附学习资料)
  20. 创建图层-只是保存lyr,此路不通

热门文章

  1. 【DIY】送给儿子的感应小夜灯,DIY小夜灯,无需编程,用人体红外感应传感器制作小夜灯...
  2. C语言常用宏定义(#define)使用方法
  3. 【PC工具】图片压缩哪家强!tinyPNG图片压缩工具
  4. 【PC工具】chrome浏览器插件vimium:传说上网可以不用鼠标。VIM入门工具,妈妈再也不用担心我学不会vim了...
  5. 射频篇(一) 模拟、射频器件学习(1) —— 晶振(OSC)
  6. 基于小波shint/DCT编码压缩解压缩的FPGA实现
  7. 十二、linux LED初始化
  8. C++抽象基类和纯虚成员函数
  9. 在iview项目中添加echarts3
  10. CSS margin详解