一.kmeans聚类:

基本方法流程

1.首先随机初始化k个中心点

2.将每个实例分配到与其最近的中心点,开成k个类

3.更新中心点,计算每个类的平均中心点

4.直到中心点不再变化或变化不大或达到迭代次数

优缺点:该方法简单,执行速度较快。但其对于离群点处理不是很好,这是可以去除离群点。kmeans聚类的主要缺点是随机的k个初始中心点的选择不够严谨,因为是随机,所以会导致聚类结果准确度不稳定。

二.kmeans++聚类:

kmeans++方法是针对kmeans的主要缺点进行改进,通过在初始中心点的选择上改进不足。

中心点的选择:

1.首先随机选择一个中心点

2.计算每个点到与其最近的中心点的距离为dist,以正比于dist的概率,随机选择一个点作为中心点加入中心点集中,重复直到选定k个中心点

对于正比于dist的概率随机选择一个数据点作为新的中心点的理解有一个英文资料解释如下:

3.计算同kmeans方法

三.评估方法

误差平方和可以评估每次初始中心点选择聚类的优劣,公式如下:

计算每个点到它自己的类的中心点的距离的平方和,外层是不同类间的和。根据每次初始点的选择聚类结果计算SSE,SSE值越小结果越好。

四.代码

 #!/usr/bin/python
# -*- coding: utf-8 -*-
import math
import codecs
import random #k-means和k-means++聚类,第一列是label标签,其它列是数值型数据
class KMeans: #一列的中位数
def getColMedian(self,colList):
tmp = list(colList)
tmp.sort()
alen = len(tmp)
if alen % 2 == 1:
return tmp[alen // 2]
else:
return (tmp[alen // 2] + tmp[(alen // 2) - 1]) / 2 #对数值型数据进行归一化,使用绝对标准分[绝对标准差->asd=sum(x-u)/len(x),x的标准分->(x-u)/绝对标准差,u是中位数]
def colNormalize(self,colList):
median = self.getColMedian(colList)
asd = sum([abs(x - median) for x in colList]) / len(colList)
result = [(x - median) / asd for x in colList]
return result '''
1.读数据
2.按列读取
3.归一化数值型数据
4.随机选择k个初始化中心点
5.对数据离中心点距离进行分配
'''
def __init__(self,filePath,k):
self.data={}#原始数据
self.k=k#聚类个数
self.iterationNumber=0#迭代次数
#用于跟踪在一次迭代改变的点
self.pointsChanged=0
#误差平方和
self.SSE=0
line_1=True
with codecs.open(filePath,'r','utf-8') as f:
for line in f:
# 第一行为描述信息
if line_1:
line_1=False
header=line.split(',')
self.cols=len(header)
self.data=[[] for i in range(self.cols)]
else:
instances=line.split(',')
column_0=True
for ins in range(self.cols):
if column_0:
self.data[ins].append(instances[ins])# 0列数据
column_0=False
else:
self.data[ins].append(float(instances[ins]))# 数值列
self.dataSize=len(self.data[1])#多少实例
self.memberOf=[-1 for x in range(self.dataSize)] #归一化数值列
for i in range(1,self.cols):
self.data[i]=self.colNormalize(self.data[i]) #随机从数据中选择k个初始化中心点
random.seed()
#1.下面是kmeans随机选择k个中心点
#self.centroids=[[self.data[i][r] for i in range(1,self.cols)]
# for r in random.sample(range(self.dataSize),self.k)]
#2.下面是kmeans++选择K个中心点
self.selectInitialCenter() self.assignPointsToCluster() #离中心点距离分配点,返回这个点属于某个类别的类型
def assignPointToCluster(self,i):
min=10000
clusterNum=-1
for centroid in range(self.k):
dist=self.distance(i,centroid)
if dist<min:
min=dist
clusterNum=centroid
#跟踪改变的点
if clusterNum!=self.memberOf[i]:
self.pointsChanged+=1
#误差平方和
self.SSE+=min**2
return clusterNum #将每个点分配到一个中心点,memberOf=[0,1,0,0,...],0和1是两个类别,每个实例属于的类别
def assignPointsToCluster(self):
self.pointsChanged=0
self.SSE=0
self.memberOf=[self.assignPointToCluster(i) for i in range(self.dataSize)] # 欧氏距离,d(x,y)=math.sqrt(sum((x-y)*(x-y)))
def distance(self,i,j):
sumSquares=0
for k in range(1,self.cols):
sumSquares+=(self.data[k][i]-self.centroids[j][k-1])**2
return math.sqrt(sumSquares) #利用类中的数据点更新中心点,利用每个类中的所有点的均值
def updateCenter(self):
members=[self.memberOf.count(i) for i in range(len(self.centroids))]#得到每个类别中的实例个数
self.centroids=[
[sum([self.data[k][i] for i in range(self.dataSize)
if self.memberOf[i]==centroid])/members[centroid]
for k in range(1,self.cols)]
for centroid in range(len(self.centroids))] '''迭代更新中心点(使用每个类中的点的平均坐标),
然后重新分配所有点到新的中心点,直到类中成员改变的点小于1%(只有不到1%的点从一个类移到另一类中)
'''
def cluster(self):
done=False
while not done:
self.iterationNumber+=1#迭代次数
self.updateCenter()
self.assignPointsToCluster()
#少于1%的改变点,结束
if float(self.pointsChanged)/len(self.memberOf)<0.01:
done=True
print("误差平方和(SSE): %f" % self.SSE) #打印结果
def printResults(self):
for centroid in range(len(self.centroids)):
print('\n\nCategory %i\n=========' % centroid)
for name in [self.data[0][i] for i in range(self.dataSize)
if self.memberOf[i]==centroid]:
print(name) #kmeans++方法与kmeans方法的区别就是初始化中心点的不同
def selectInitialCenter(self):
centroids=[]
total=0
#首先随机选一个中心点
firstCenter=random.choice(range(self.dataSize))
centroids.append(firstCenter)
#选择其它中心点,对于每个点找出离它最近的那个中心点的距离
for i in range(0,self.k-1):
weights=[self.distancePointToClosestCenter(x,centroids)
for x in range(self.dataSize)]
total=sum(weights)
#归一化0到1之间
weights=[x/total for x in weights] num=random.random()
total=0
x=-1
while total<num:
x+=1
total+=weights[x]
centroids.append(x)
self.centroids=[[self.data[i][r] for i in range(1,self.cols)] for r in centroids] def distancePointToClosestCenter(self,x,center):
result=self.eDistance(x,center[0])
for centroid in center[1:]:
distance=self.eDistance(x,centroid)
if distance<result:
result=distance
return result #计算点i到中心点j的距离
def eDistance(self,i,j):
sumSquares=0
for k in range(1,self.cols):
sumSquares+=(self.data[k][i]-self.data[k][j])**2
return math.sqrt(sumSquares) if __name__=='__main__':
kmeans=KMeans('filePath',3)
kmeans.cluster()
kmeans.printResults()

参考:1.machine.learning.an.algorithmic.perspective.2nd.edition.

    2.a programmer's guide to data mining

kmeans与kmeans++的python实现的更多相关文章

  1. K-Means clusternig example with Python and Scikit-learn(推荐)

    https://www.pythonprogramming.net/flat-clustering-machine-learning-python-scikit-learn/ Unsupervised ...

  2. 4. K-Means和K-Means++实现

    1. K-Means原理解析 2. K-Means的优化 3. sklearn的K-Means的使用 4. K-Means和K-Means++实现 1. 前言 前面3篇K-Means的博文从原理.优化 ...

  3. K-Means ++ 和 kmeans 区别

    Kmeans算法的缺陷 聚类中心的个数K 需要事先给定,但在实际中这个 K 值的选定是非常难以估计的,很多时候,事先并不知道给定的数据集应该分成多少个类别才最合适Kmeans需要人为地确定初始聚类中心 ...

  4. Spark2.0机器学习系列之9: 聚类(k-means,Bisecting k-means,Streaming k-means)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:      (1)K-means      (2)Latent Dirichlet allocation (LDA)  ...

  5. K-means聚类算法及python代码实现

    K-means聚类算法(事先数据并没有类别之分!所有的数据都是一样的) 1.概述 K-means算法是集简单和经典于一身的基于距离的聚类算法 采用距离作为相似性的评价指标,即认为两个对象的距离越近,其 ...

  6. kmeans算法思想及其python实现

    第十章 利用k-均值聚类算法对未标注的数据进行分组 一.导语 聚类算法可以看做是一种无监督的分类方法,之所以这么说的原因是它和分类方法的结果相同,区别它的类别没有预先的定义.簇识别是聚类算法中经常使用 ...

  7. K-means clustering (K-means聚类)

    问题: K-所有值聚类是无监督学习算法 设数据集.当中,. 如果这个数据能够分为类. 把这个问题模型化: , 当中代表第类的聚点(中心点.均值). 该模型能够用EM算法进行训练: 初始化,. E步:固 ...

  8. 机器学习算法与Python实践之(五)k均值聚类(k-means)

    机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学 ...

  9. Python—kmeans算法学习笔记

    一.   什么是聚类 聚类简单的说就是要把一个文档集合根据文档的相似性把文档分成若干类,但是究竟分成多少类,这个要取决于文档集合里文档自身的性质.下面这个图就是一个简单的例子,我们可以把不同的文档聚合 ...

随机推荐

  1. 与高精死杠的几天——记两道简单的高精dp

    (同样也是noip往年的题 1​.矩阵取数游戏 题目链接[Luogu P1005 矩阵取数游戏] \(\mathcal{SOLUTION}:\) 通过对题目条件的分析,我们可以发现,每一行取数对答案的 ...

  2. 2019中山纪念中学夏令营-Day1[JZOJ]

    T1 题目描述: 1999. Wexley接苹果(apple) (File IO): input:apple.in output:apple.out 时间限制: 1000 ms  空间限制: 1280 ...

  3. Erasing Substrings CodeForces - 938F (字符串dp)

    大意: 给定字符串$s$, 长度为$n$, 取$k=\lfloor log2(n)\rfloor$, 第$i$次操作删除一个长度为$2^{i-1}$的子串, 求一种方案使得, $k$次操作后$s$的字 ...

  4. leecode刷题(31) -- 回文数

    leecode刷题(31) -- 回文数 回文数 判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: 输 ...

  5. 梳理common-io工具包

    title: 梳理common-io工具包 comments: false date: 2019-08-28 14:21:58 description: 对common-io工具包中的常用类进行整理, ...

  6. weex 轮播如何使用?

    下面的内容是你必须要掌握的 1.怎么让banner的宽度和屏幕的宽度相等 2.怎么让banner自动轮播和轮播间隔 3.如何添加指示器 4.如何设置指示器的颜色和大小 5.点击轮播图时触发事件 6.检 ...

  7. 黑马java课程视频java学习视频

    资料获取方式,关注公总号RaoRao1994,查看往期精彩-所有文章,即可获取资源下载链接 更多资源获取,请关注公总号RaoRao1994

  8. 解压速度更快, Zstandard 1.4.1 发布

    zstd 1.4.1 发布了,zstd 又叫 Zstandard,它是一种快速无损压缩算法,主要应用于 zlib 级别的实时压缩场景,并且具有更好的压缩比.zstd 还可以以压缩速度为代价提供更强的压 ...

  9. 华为ensp问题:云映射本地网卡,直连路由器可以ping通,pc却不行?

    拓扑图:cloud 云映射本机物理网卡:192.168.56.1     R1可以Ping通,所有Pc都不行,路由表也存在路由信息,不知道什么问题?

  10. Jmeter 常见逻辑控制器详解

    简介 Jmeter有很多逻辑控制器,可以控制请求的执行顺序和执行逻辑,本文就Jmeter常见的逻辑控制器做一个详细的描述,并通过示例让大家了解逻辑控制器的作用.   代码的逻辑分支通常有: 条件判断I ...