版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/keyue123/article/details/81197381
K-Means聚类算法是一种基于距离的聚类算法,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则,最终的目标就是根据输入参数K,将数据对象分为K个簇。算法采用误差平方和准则函数作为聚类准则函数。
基本思想:
1、指定需要划分的簇的个数K值
2、随机选取K个初始聚类中心
3、计算各个数据到这K个初始聚类中心的距离,把数据对象划分到最近的聚类中心所处的簇中
4、计算每一组的平均值,作为新的聚类中心
5、重复2~4直至中心点不再发生变化
一般情况下我们都是使用欧式几何距离作为聚类的目标函数:
实例分析:
利用K-Means方法,将下面的数据分为两类:
坐标点 | X | Y |
---|---|---|
A | 15 | 17 |
B | 12 | 18 |
C | 14 | 15 |
D | 13 | 16 |
E | 12 | 15 |
F | 16 | 12 |
G | 4 | 6 |
H | 5 | 8 |
I | 5 | 3 |
J | 7 | 4 |
K | 7 | 2 |
L | 6 | 5 |
python代码实现解析:
#!/usr/bin/python
#coding=utf-8
from numpy import *
from math import sqrt
import codecs
# 获取样本集
def LoadData():
f = codecs.open("k-means.txt", mode='r+')
lines = f.readlines()
data = []
for line in lines:
curline = line.strip().split(', ') # 用逗号把数据分开
frline = map(float, curline)
data.append(frline) # 将数据放在列表中
data = mat(data) # 将列表转为矩阵
print data
return data
# 计算距离量度
def distEclud(vecA, vecB):
distance = sqrt(sum(power((vecA - vecB),2))) # 计算欧氏距离
return distance
# 随机生成K个初始点
def randCent(dataSet, k):
n = shape(dataSet)[1] # 获取数据矩阵行数
center = mat(zeros((k, n))) # 产生新的填充为0的矩阵
for j in range(n):
rangeJ = float(max(dataSet[:, j]) - min(dataSet[:, j])) # 计算数据范围
center[:, j] = min(dataSet[:, j]) + rangeJ * random.rand(k, 1) # 随机产生一个在数据范围类的聚类中心
print "初始质点: "
print center
return center
# dataSet 样本集
# k 簇个数
# distMeas 距离量度,默认欧式距离
# randCent 初始点选取
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
m = shape(dataSet)[0] # 样本数
clusterAssment = mat(zeros((m, 2))) # 创建矩阵并清零
center = createCent(dataSet, k) # 随机生成K个初始点
clusterChanged = True
while clusterChanged:
clusterChanged = False
for i in range(m):
minDist = inf
minIndex = -1
for j in range(k):
distJI = distMeas(dataSet[i, :], center[j, :]) # 计算点到各个聚类中心的距离
if distJI < minDist:
minDist = distJI # 计算到各个聚类中心的最短欧氏距离
minIndex = j
if clusterAssment[i, 0] != minIndex: # 判断是否收敛
clusterChanged = True
clusterAssment[i, :] = minIndex, minDist ** 2
for cent in range(k): # 更新聚类中心
dataCent = dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]] # nonzero 非零数组位置
center[cent, :] = mean(dataCent, 0) # 求列平均值
print "均值后质点: "
print center
return center
# 主函数
def main():
dataSet = LoadData()
k = 2
kMeans(dataSet, k)
if __name__ == '__main__':
main()
最终获取到的两个聚类中心:
[john@localhost K-means]$ python K-means.py
[[ 15. 17.]
[ 12. 18.]
[ 14. 15.]
[ 13. 16.]
[ 12. 15.]
[ 16. 12.]
[ 4. 6.]
[ 5. 8.]
[ 5. 3.]
[ 7. 4.]
[ 7. 2.]
[ 6. 5.]]
初始质点:
[[ 12.65495833 4.14865393]
[ 9.30725565 2.9332491 ]]
均值后质点:
[[ 13.66666667 15.5 ]
[ 5.66666667 4.66666667]]
没有均值之前的散点图,红色为第一次随机生成的质点,即聚类中心,蓝色为数据集。
计算均值之前的散点图,红色为均值之后的质点。