文章目录

  • 1 K均值聚类算法
  • 2 使用后处理来提高聚类性能
  • 3 二分K-均值算法
  • 4 示例:对地图上的点进行聚类
  • 5 总结
  • 6 补充
  • Supervised learning:目标变量实现存在

    • 输入X,预测/分类变量Y
  • Unsupervised learning:目标变量实现不存在

    • 从数据X中能发现什么?
    • 聚类与分类:分类的目标实现已经知道,聚类的类别没有预先定义,聚类有时也叫做“无监督分类”
  • Clustering聚类是一种无监督的学习, 它将相似的对
    象归到一个簇中, 将不相似对象归到不同簇中.

    • Similarity相似这一概念取决于所选择的相似度计算方法
    • K-Means 是发现给定数据集的 K 个簇的聚类算法, 之所以称之为K-均值:
    • 可以发现 K 个不同的簇, 且每个簇的中心采用簇中所含值的均值计算而成.
    • 簇个数 K 是用户指定的, 每一个簇通过其质心(centroid), 即簇中所有点的中心来描述.聚类与分类算法的最大区别在于, 分类的目标类别已知, 而聚类的目标类别是未知的.

1 K均值聚类算法

  • K-均值是发现给定数据集的k个簇的算法,每个簇通过其质心来描述。

    • 其优点为容易实现,但可能收敛到局部最小值,在大规模数据集上收敛较慢。
    • 随机确定k个初始点为质心,为每个点找距其最近的质心,并将其分配给该质心所对应的簇,每个簇的质心更新为该簇所有点的平均值。
    • 质心可用任意距离度量方式,但结果相应的受到距离度量方式影响。
    • 应用场景:主要用来聚类, 但是类别是未知的.例如: 对地图上的点进行聚类.
  • 簇: 所有数据点集合,簇中的对象是相似的。
  • 质心: 簇中所有点的中心(计算所有点的均值而来).
  • SSE: Sum of Sqared Error(平方误差和), SSE 值越小,表示越接近它们的质心. 由于对误差取了平方,因此更加注重那么远离中心的点
    伪代码:
创建K个点作为起始质心(通常是随机选择)
当任意一个点的簇分配结果发生改变时对数据集中的每个数据点对每个质心计算质心于数据点之间的距离将数据点分配到距其最近的簇对每一个簇,计算簇中所有点的均值并将均值作为质心

python代码

def loadDataSet(fileName):"""从文件加载数据集:param fileName: 文件名:return:数据矩阵"""dataMat = []fr = open(fileName)for line in fr.readlines():curLine = line.strip().split('\t')# 映射所有的元素为float(浮点型)类型fltLine = list(map(float, curLine))dataMat.append(fltLine)return dataMatdef distEclud(vecA, vecB):"""计算两个向量的欧式距离:param vecA: A向量:param vecB: B向量:return: 量向量之间的欧式距离"""return np.sqrt(sum(np.power(vecA - vecB, 2)))def randCent(dataSet, k):"""构建一个包含k个随机质心的集合:param dataSet: 数据集:param k: 质心数量:return: 质心集合"""col = np.shape(dataSet)[1]  # 列的数量centroids = np.mat(np.zeros((k, col)))  # 创建K个质心矩阵# 创建随机簇质心,并且在每一维的边界内for j in range(col):minJ = min(dataSet[:, j])  # 最小值rangeJ = float(max(dataSet[:, j]) - minJ)  # 范围 = 最大值 - 最小值centroids[:, j] = np.mat(minJ + rangeJ * np.random.rand(k, 1))  # 随机生成return centroidsdef kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):"""k_means聚类算法:param dataSet:数据集:param k:质心数量:param distMeas:距离计算方法,默认欧氏距离distEclud():param createCent:获得k个质心的方法,默认随机获取randCent():return:k个聚类,聚类结果及误差"""row = np.shape(dataSet)[0]  # 行数clusterAssment = np.mat(np.zeros((row, 2)))  # 创建一个与dataSet行数一样,但是有两列的矩阵,用来保存簇分配结果centroids = createCent(dataSet, k)  # 创建k个随机质心clusterChanged = True  # 聚类结果是否发生变化的布尔类型while clusterChanged:  # 只要聚类结果一直发生变化,就一直执行聚类算法,直至所有数据点聚类结果不变化clusterChanged = False  # 聚类结果变化布尔类型置为falsefor i in range(row):  # 循环每一个数据点并分配到最近的质心中去# 初始化最小距离最正无穷;最小距离对应索引为-1minDist = np.infminIndex = -1for j in range(k):  # 循环k个类的质心distJI = distMeas(centroids[j, :], dataSet[i, :])  # 计算数据点到质心的欧氏距离if distJI < minDist:  # 如果距离比minDist(最小距离)还小,更新minDist(最小距离)和质心的索引(index)# 当前距离定为当前最小距离;最小距离对应索引对应为j(第j个类)minDist = distJIminIndex = jif clusterAssment[i, 0] != minIndex:  # 当前聚类结果中第i个样本的聚类结果发生变化:布尔类型置为true,继续聚类算法clusterChanged = True  # 簇改变clusterAssment[i, :] = minIndex, minDist ** 2  # 更新当前变化样本的聚类结果和平方误差print(centroids)for cent in range(k):  # 更新质心ptsInClust = dataSet[np.nonzero(clusterAssment[:, 0].A == cent)[0]]  # 将数据集中所有属于当前质心类的样本通过条件过滤筛选出来centroids[cent, :] = np.mean(ptsInClust, axis=0)  # 将质心修改为簇# 返回k个聚类,聚类结果及误差return np.mat(centroids), clusterAssment

2 使用后处理来提高聚类性能

  • Poor clusters: K-均值的缺点是需要预先确定簇的数目k,如何确定k的选择是否正确是比较重要的问题。K-均值算法收敛但聚类效果较差的原因是K-均值算法可能收敛到了局部最小值而非全局最小值。Local minimum

    • 一种度量聚类效果的指标是SSE(sum of squared error,误差平方和)。SSE值越小表示数据点越接近于它们的质心,聚类效果也越好。可通过增加簇的个数降低SSE,但不符合聚类的目标:保持簇数目不变的情况下提高簇的质量
    • 可以对生成的簇进行后处理,将具有最大SSE值的簇划分成两个簇。将最大簇包含的点过滤出来并在这些点上运行k-均值算法。也可以将两个簇进行合并

3 二分K-均值算法

  • 二分K-均值算法能克服K-均值算法收敛于局部最小值的问题

    • 首先将所有点作为一个簇,然后将该簇一分为二
    • 选择其中一个簇继续划分,选择哪个取决于对其划分是否可以最大程度降低SSE(平方和误差)的值
    • 不断重复划分,直到用户指定的簇数目为止。
      伪代码:
将所有点看成一个簇
当簇数目小于k时
对于每一个簇计算总误差在给定的簇上面进行K-均值聚类(k=2)计算将该簇一分为二之后的总误差
选择使得误差最小的那个簇进行划分操作
  • 另一种做法是选择SSE 最大的簇进行划分,直到簇数目达到用户指定的数目位置。
    python代码
def bikmeans(dataSet, k, distMeas=distEclud):"""二分K-均值聚类算法:param dataSet:数据集:param k:质心数量:param distMeas:距离计算方法,默认欧氏距离distEclud():return:"""numSamples = dataSet.shape[0]  # 获得数据集的样本数clusterAssment = np.mat(np.zeros((numSamples, 2)))  # 初始化一个元素值0的(numSamples,2)矩阵centroid0 = np.mean(dataSet, axis=0).tolist()[0]  # 列表中的第一个列表元素:即全部数据每个属性centList = [centroid0]  # 当前聚类列表为将数据集聚为一类for j in range(numSamples):  # 遍历每个数据集样本clusterAssment[j, 1] = (distMeas(np.mat(centroid0), dataSet[j, :])) ** 2  # 计算当前聚为一类时各个数据点距离质心的平方距离while len(centList) < k:  # 循环,直至二分k-均值达到k类为止lowestSSE = np.inf  # 将当前最小平方误差置为正无穷for i in range(len(centList)):  # 遍历当前每个聚类# 通过数组过滤筛选出属于第i类的数据集合ptsInCurrCluster = dataSet[np.nonzero(clusterAssment[:, 0].A == i)[0], :]# 对该类利用二分k-均值算法进行划分,返回划分后结果,及误差centroidMat, splitClusAss = kMeans(ptsInCurrCluster, 2, distMeas)sseSplit = sum(splitClusAss[:, 1])  # 计算该类划分后两个类的误差平方和# 计算数据集中不属于该类的数据的误差平方和sseNotSplit = sum(clusterAssment[np.nonzero(clusterAssment[:, 0].A != i)[0], 1])print("sseSplit,and notSplit:", sseSplit, sseNotSplit)if (sseSplit + sseNotSplit) < lowestSSE:  # 划分第i类后总误差小于当前最小总误差bestCentToSplit = i  # 第i类作为本次划分类bestNewCents = centroidMat  # 第i类划分后得到的两个质心向量bestClustAss = splitClusAss.copy()  # 复制第i类中数据点的聚类结果即误差值lowestSSE = sseSplit + sseNotSplit  # 将划分第i类后的总误差作为当前最小误差# 数组过滤筛选出本次2-均值聚类划分后类编号为1数据点,将这些数据点类编号变为当前类个数+1,作为新的一个聚类bestClustAss[np.nonzero(bestClustAss[:, 0].A == 1)[0], 0] = len(centList)# 同理,将划分数据集中类编号为0的数据点的类编号仍置为被划分的类编号,使类编号连续不出现空缺bestClustAss[np.nonzero(bestClustAss[:, 0].A == 0)[0], 0] = bestCentToSplitprint("the bestCentToSplit is:", bestCentToSplit)print("the len of bestClustAss is :", len(bestClustAss))centList[bestCentToSplit] = bestNewCents[0, :].tolist()[0]  # 更新质心列表中的变化后的质心向量centList.append(bestNewCents[1, :].tolist()[0])  # 添加新的类的质心向量# 更新clusterAssment列表中参与2-均值聚类数据点变化后的分类编号,及数据该类的误差平方clusterAssment[np.nonzero(clusterAssment[:, 0].A == bestCentToSplit)[0], :] = bestClustAssreturn np.mat(centList), clusterAssment

4 示例:对地图上的点进行聚类

  • 使用Yahho!PlaceFinder API收集数据,将目标地点地址转换为经纬度,用matplotlib构建一个二维数据图,包含簇、位置和地图。
  • 将俄勒冈州的70个地点聚类,地址列表为portlandClubs.txt。可以在Yahoo开发者网络进行注册,创建一个桌面应用以获取appid。
  • 书上给出的yahooAPI的baseurl已经改变,并且yahoo目前placefinder需要OAuth2验证。
  • 直接使用places.txt,使用这些点聚类(下载地址)

python代码:

def distSLC(vecA, vecB):"""球面距离计算及簇绘图函数:param vecA::param vecB::return:"""a = np.sin(vecA[0, 1] * np.pi / 180) * np.sin(vecB[0, 1] * np.pi / 180)b = np.cos(vecA[0, 1] * np.pi / 180) * np.cos(vecB[0, 1] * np.pi / 180) * np.cos(np.pi * (vecB[0, 0] - vecA[0, 0]) / 180)return np.arccos(a + b) * 6371.0def clusterClubs(numClust=5):""":param numClust::return:"""datList = []for line in open('places.txt').readlines():  # 解析文本数据中的每一行中的数据特征值lineArr = line.split('\t')datList.append(([float(lineArr[4]), float(lineArr[3])]))dataMat = np.mat(datList)# 利用2-均值聚类算法进行聚类myCentroids, clustAssing = bikmeans(dataMat, numClust, distMeas=distSLC)fig = plt.figure()rect = [0.1, 0.1, 0.8, 0.8]scatterMarkers = ['s', 'o', '^', '8', 'p', 'd', 'v', 'h', '>', '<']axprops = dict(xticks=[], yticks=[])ax0 = fig.add_axes(rect, label='ax0', **axprops)# imgP = plt.imread('portland.png')# ax0.imshow(imgP)ax1 = fig.add_axes(rect, label='ax1', frameon=False)for i in range(numClust):ptsInCurrCluster = dataMat[np.nonzero(clustAssing[:, 0].A == i)[0], :]markerStyle = scatterMarkers[i % len(scatterMarkers)]ax1.scatter(ptsInCurrCluster[:, 0].flatten().A[0], ptsInCurrCluster[:, 1].flatten().A[0],marker=markerStyle, s=90)ax1.scatter(myCentroids[:, 0].flatten().A[0], myCentroids[:, 1].flatten().A[0], marker='+', s=300)plt.show()

5 总结

  • 无监督学习指事先不知道要寻找的内容,没有目标变量
  • 聚类将数据点归到多个簇中,可以使用多种方法计算相似度,实际使用时也应多次运行取较优结果。
  • K-均值算法是一种广泛使用的聚类算法,k是用户指定的要创建的簇的数目,该算法非常有效但容易受到初始簇质心的影响(k值选择不当,可能聚类效果不佳)。可以使用二分K-均值聚类算法获得更好的效果

6 补充

如何选择聚类个数?

  • k-means是以最小化样本与质点平方误差作为目标函数,将每个簇的质点与簇内样本点的平方距离误差和称为畸变程度(distortions),对于一个簇,它的畸变程度越低,代表簇内成员越紧密,畸变程度越高,代表簇内结构越松散。

    • 畸变程度会随着类别的增加而降低,但对于有一定区分度的数据,在达到某个临界点时畸变程度会得到极大改善,之后缓慢下降,这个临界点就可以考虑为聚类性能较好的点(肘部法则elbow method)

该方法十分直观,但很难用数学公式量化,随意性较大学术界提出了一种数学上更为严谨的方法决定聚类个数:轮廓分析silhoutte analysis(定量分析聚类质量)

  • 应用示例

    • 异常检测

      • 明显有别于正常数据的异常值的发现(反欺诈、网络安全)
      • 缺少标签变量、不知道其特征 → \rightarrow →聚类分析(非监督学习、适于没有标签、聚类中心也反映了相应类别的主要特征:聚类中心的距离反应两个类别的整体差异)
    • 图片压缩
      • 图像处理中,常用k-means聚类中心替代原始像素点(保留了图片主要特征、也有效进行了压缩 → \rightarrow →即向量量化)
  • 凝聚聚类:许多基于相同原则构建的聚类算法。

    • 算法首先声明每个点是自己的簇,然后合并两个最相似的簇,直到满
      足某种停止准则为止 → \rightarrow →合并相似的簇,直到仅剩下指定个数的簇
    • 链接准则:规定如何度量最相似的簇
  • 由于算法的工作原理,凝聚算法不能对新数据点做出预测

  • 层次聚类与树状图:

    • 凝聚聚类生成了所谓的层次聚类(hierarchical clustering)
    • 聚类过程迭代进行,每个点都从一个单点簇变为属于最终的某个簇。每个中间步骤都提供了数据的一种聚类(簇的个数也不相同)。
    • 例:图中的叠加显示了图中所有可能的聚类,有助于深入了解每个簇如何分解为较小的簇
    • 但它依赖于数据的二维性质,因此不能用于具有两个以上特征的数据集 → \rightarrow →另一个将层次聚类可视化的工具,叫作树状图(dendrogram),它可以处理多维数据集

DBSCAN

  • Kmeans无法识别具有复杂形状的簇(two_moons数据集:两个半月形)
  • 另一个非常有用的聚类算法:DBSCAN
    • 优点:不需要用户先验的设置簇的个数、可划分复杂形状的簇还可以找出不属于任何簇的点
    • 缺点:比凝聚聚类和kmeans稍慢但仍可以和扩展到相对较大数据集
  • 原理:识别特征空间的“拥挤”区域的点 → \rightarrow →密集区域
    • 簇形成数据的密集区域,并由相对较空区域分隔开

机器学习实战——K均值相关推荐

  1. 百面机器学习—7.K均值算法、EM算法与高斯混合模型要点总结

    文章目录 一.总结K均值算法步骤 二.如何合理选择K值? 三.K均值算法的优缺点是什么? 四.如何对K均值算法进行调优? 五.EM算法解决什么问题? 六.EM算法流程是什么? 六.EM算法能保证收敛嘛 ...

  2. 机器学习实验 - K均值聚类

    目录 一.报告摘要 1.1 实验要求 1.2 实验思路 1.3 实验结论 二.实验内容 2.1 方法介绍 2.2 实验细节 2.2.1 实验环境 2.2.2 实验过程 2.2.3 实验与理论内容的不同 ...

  3. 人工智障学习笔记——机器学习(8)K均值聚类

    一.概念 K均值聚类(K-means)是硬聚类算法,是典型的基于原型的目标函数聚类方法的代表,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则.K-means算 ...

  4. 机器学习之K均值(K-Means)算法

    1.K-Means简介 K均值(K-Means)算法是无监督的聚类方法,实现起来比较简单,聚类效果也比较好,因此应用很广泛.K-Means算法针对不同应用场景,有不同方面的改进.我们从最传统的K-Me ...

  5. sklearn机器学习:K均值聚类

    K-Means 均值聚类聚类算法可以说是最简单但是使用最广的一种聚类算法了,原理也简单易懂,sklearn中提供了很多聚类算法的实现,所以这里就学习一下K-Means算法.接下来会介绍一些关键性的概念 ...

  6. 【进阶版】 机器学习之K均值聚类、层次聚类、密度聚类、实战项目含代码(15)

    目录 欢迎订阅本专栏,持续更新中~ 本专栏前期文章介绍! 机器学习配套资源推送 进阶版机器学习文章更新~ 点击下方下载高清版学习知识图册 项目要求 数据透视 代码实战 维度太多,利用PCA降维的思想进 ...

  7. 模式识别和机器学习实战-K近邻算法(KNN)- Python实现 - 约会网站配对效果判断和手写数字识别

    文章目录 前言 一. k-近邻算法(KNN) 1.算法介绍 2.举个例子--电影分类 3.步骤描述 4.来了--代码实现 二.实战之约会网站配对效果判断 1.导入数据 2.分析数据 3.数据归一化 4 ...

  8. 机器学习之K均值的SSE和轮廓系数

    前文回顾: 肘部法:SSE误差平方和 SSE(sum of the squared errors)是对簇松散度的衡量,作为目标函数其实是一个严格的坐标下降(Coordinate Decendet)过程 ...

  9. 机器学习算法之 K 均值聚类

    机器学习算法之 K 均值聚类 本文我们来学习一下另一种经常听到的机器学习算法-- K 均值聚类. 这个名字确实跟"K 近邻"有些相像,但是要明确的是,"K 近邻" ...

最新文章

  1. full calendar mysql_fullcalendar 及mysql数据库的工作日管理
  2. showModalDialog 页面上GridView的分页问题
  3. 线性表的链式表示——双链表
  4. 外部导入方式添加背景图_在PS中如何添加灯光效果
  5. dw按钮图片滚动js_轮播图--swiper插件/原生js/jQuery
  6. 1.信号处理之:kill(),alarm(),pause()函数
  7. h5 时间控件问题,怎么设置type =datetime-local 的值
  8. mysql定义shell变量_shell 变量的定义,赋值,运算
  9. 点在不规则图形内算法python_目标检测算法中规则矩形和不规则四边形IOU的Python实现...
  10. MyEclipse8.6安装svn插件
  11. [思维导图学习五] 思维导图在企业培训中的应用[转]
  12. Matlab代码:综合能源系统(IES)的优化调度
  13. Tomcat 设置系统默认文件编码
  14. 如何把python代码翻译成中文-Python:谷歌翻译20次的程序如何实现?
  15. 如何学习 JavaScript
  16. scrapy框架学习之demo2
  17. oracle中 ''dual'' 的含义
  18. ET篇:ETBook笔记(1.2 为什么使用C# .net core做服务端?)
  19. 吾父马达加斯加之旅-1
  20. Agent with Warm Start and Adaptive Dynamic Termination for Plane Localization in 3D Ultrasound

热门文章

  1. Android gradle阿里云仓库
  2. WPS表格-快速展开全部隐藏行
  3. 第一个被赋予公明身份的机器人_史上首次 沙特授予“女性”机器人索菲娅公民身份...
  4. jQuery实现五星好评
  5. RSA算法的Python实现(模幂运算——原始算法)
  6. 风华贴片电容命名规则
  7. 合肥工业大学计算机与信息学院学生会宗旨,合肥工业大学宣城校区第一届学生会成立大会召开...
  8. 关于Handle的一些介绍
  9. 宽带加速方法!网速提高30%-200%
  10. CocoStudio基础教程(3)在程序中处理cocoStudio导出动画