k-means是无监督的聚类算法,k-means指的是 每个簇的中心即簇中所包含的值的均值。可使用k-means算法实现音调的分类与可视化 、文本文档聚类等用途。
算法原理:
- 选择k个初始中心点;
- 将每个初始点与每个点进行比较,如果与第n个点距离最近,则标记为n;
- 将标记为n的一类数据,计算他们每个特征的均值;
- 重复第二步和第三步,直到每个特征列的均值变化小于所给定的值,或者是达到了最大迭代次数。
k值选取:
- 层次聚类或者使用Canopy算法进行聚类
- 根据实际需求选取:衣服的尺寸分为(M,L,S)三种
- 肘部法则(Elbow Method)
初始质心的选取:
- 随机选取
- 层次聚类:划分k个层次,计算出每个簇对应的质心即初始质心;
- k-means++
距离度量:
- 欧式距离
- 余弦相似度
聚类的评估标准——轮廓系数(Silhouette Coefficient)
轮廓系数结合了聚类的凝聚度(Cohesion)和分离度(Separation),用于评估类的密集与分散程度。该值处于-1~1之间,值越大,表示聚类效果越好。计算公式如下:
ai为计算样本i到同簇其他样本的平均距离,
计算样本i到其他某簇Cj 的所有样本的平均距离bij,称为样本i与簇Cj 的不相似度。
轮廓系数所反映的聚类效果:
- si接近1,则说明样本i聚类合理;
- si接近-1,则说明样本i更应该分类到另外的簇;
- 若si 近似为0,则说明样本i在两个簇的边界上
使用代码自定义实现k-means:
#计算欧式距离
def distanceEuclid(pointA,pointB):
return sqrt( sum( power(pointA-pointB,2 ) ) )
#随机生成中心点
def randCenter( dataSet,k):
m,n = shape(dataSet)
centers = mat( zeros((k,n)) ) #k个质心 n列
for j in range(n): #每循环一次 产生一个列的值
#找最小值与最大值
minJ = min( dataSet[:,j])
maxJ = max( dataSet[:,j])
rangeJ = float(maxJ-minJ)
#print( random.rand(k,1)) # k个 从0到1
centers[:,j] = minJ + rangeJ* random.rand(k,1)
return centers
#k-means实现
def myKmeans(dataSet,k,distMea = distanceEuclid, initCenter = randCenter):
'''
参数列表:
dataSet: 数据集
k: 分类的簇的数量
distMea: 距离算法
initCenter: 中心点
'''
m,n = shape( dataSet )
#zeros(m,2) -> 生成m行2列,m行对应每条数据,2列中的第一列表示每条数据属于哪个簇,第二列表示每条数据距中心点距离
clusterAssment = mat(zeros((m,2)))
#生成初始化质心
centers = initCenter(dataSet,k)
clusterChanged = True
#簇是否改变
while clusterChanged:
clusterChanged=False
#循环每个点,计算它与质心的距离
for i in range(m):
minDistance = inf #计算第i个点到每个质心的最小距离,并保存
minIndex = -1 #到哪个质心的距离最小保存索引
for j in range(k): #循环,取每个质心点
#计算第i个点到第i个质心的距离
distance = distMea(centers[j,:],dataSet[i,:])
#是否为最小距离
if distance<minDistance:
minDistance = distance
minIndex = j
#判断当前 第i个点是否要更改质心点
if clusterAssment[i,0] != minIndex: #索引不相等 更改簇
clusterChanged = True
clusterAssment[i,0] = minIndex
clusterAssment[i,1] = minDistance**2 #距离
print('第',i , '条数据运行结果:',clusterAssment[i])
#循环所有的簇 重新计算质心
for cent in range(k):
flag = clusterAssment[:,0].A == cent# clusterAssment[;,0] 数据编号
pointsInCluster = dataSet[ nonzero(flag)[0] ]
centers[cent,:]=mean(pointsInCluster,axis = 0) #k-means
return centers,clusterAssment
Reference:
sklearn官网: https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans
k值选取: https://www.codercto.com/a/26692.html
几种初始化质心的方式: https://blog.csdn.net/xiaoxik/article/details/79023439
距离度量: https://blog.csdn.net/les000lie/article/details/89503537
轮廓系数: https://scikit-learn.org/stable/modules/generated/sklearn.metrics.silhouette_score.html