在做Kmeans算法的时候,聚类类别数是由参数k决定的,而在做这个算法的时候,k值在传参时是由人为指定的,也就是自己想分成几类就分成几类,但是这样做下来并不严谨,我们不知道k值指定为多少的时候分类效果是最好的,所以我查找了很多关于k值的选择的资料,常见的方法有手肘法则和轮廓系数,但是用这两个方法基本上都是通过作图来观察如何选k值,最后还是需要人为输入传参的k值。
最重要的来了,自动确定k值的Kmeans聚类!,写出一个能自动确定最好分类效果的k值的算法并返回k值,作为最后传参的值,我同样也查了很多资料,找到了一个博主的文档:
我用#CSDN#这个app发现了有技术含量的博客,小伙伴们求同去《Kmeans算法 python实现》, 一起来围观吧 https://blog.csdn.net/m0_37783096/article/details/79704517?utm_source=app&app_version=4.21.1
但是里面代码并不完整,就导致有些地方看不懂。
在这里呢,我自我介绍一下,本人是一名读计算机专业的大学生,对于机器学习算法就学到一些基础知识,想请看到我发布的问题的朋友能帮忙解决一下我所提出的问题。我把完整代码上传,求在这方面厉害的朋友帮忙写一个自动确定k值并返回这个值的算法。
import numpy as np
import pandas as pd
import random
import matplotlib.pyplot as plt
import matplotlib as mpl
def loadDataSet():
data = np.random.uniform(-6,6,size=(500,2))
return data
# 中心点在k个样本点中随机选取
def createCent(dataSet, k):
center = random.sample(list(dataSet), k)
return np.array(center)
# 计算聚类中心和数据点之间的距离
def evaDistan(vectA, vectB):
return np.sqrt(np.sum(np.power((vectA - vectB), 2)))
def kMeans(dataSet, k, evaDistance, createCenter):
numSamples = np.shape(dataSet)[0]
clusterAssment = np.mat(np.zeros((numSamples, 2)))
clusterCenter = createCenter(dataSet, k)
changeFlag = True
while changeFlag:
changeFlag = False
for i in range(numSamples):
minDist = float("inf"); minIndex = -1
for j in range(k):
distJI = evaDistance(clusterCenter[j, :], dataSet[i, :])
if distJI < minDist:
minDist = distJI; minIndex = j
if clusterAssment[i, 0] != minIndex:
changeFlag = True
clusterAssment[i, :] = minIndex, minDist ** 2
# 重新计算聚类中心
for cent in range(k):
sameCluster = dataSet[np.nonzero(clusterAssment[:, 0].A == cent)[0]]
clusterCenter[cent, :] = np.mean(sameCluster, axis=0)
return clusterCenter, clusterAssment
def show(dataSet, labelSet, k, clusterCenter):
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False
fig = plt.figure(figsize=(20, 18))
plt.subplot(221)
for i in range(np.shape(dataSet)[0]):
plt.scatter(dataSet[i, 0], dataSet[i, 1], color='black')
plt.xlabel(u'X', fontsize=18)
plt.ylabel(u'Y', fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.title(u"无聚类结果", fontsize=18)
plt.subplot(222)
"""
's' : 方块状, 'o' : 实心圆, '^' : 正三角形, 'v' : 反正三角形, '+' : 加号
'*' : 星号, 'x' : x号, 'p' : 五边形, '1' : 三脚架标记, '2' : 三脚架标记
"""
mark = ['sr', 'ob', '^g', '*y', '+m', 'vc', 'xk', 'pb', '<r', 'pg', '*k', '^g']
for i in range(np.shape(dataSet)[0]):
plt.plot(dataSet[i, 0], dataSet[i, 1], mark[labelSet[i]], markersize=6)
for lei in range(k):
plt.plot(clusterCenter[lei][0], clusterCenter[lei][1], mark[lei], markersize=15)
plt.xlabel(u'X', fontsize=18)
plt.ylabel(u'Y', fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.title(u"聚类结果", fontsize=18)
plt.grid(True)
plt.show()
if __name__ == "__main__":
dataSet = loadDataSet()
k = 4
clusterCenter, clusterAssment = kMeans(dataSet, k, evaDistance=evaDistan, createCenter=createCent)
labelSet = [int(x[0]) for x in clusterAssment]
show(dataSet, labelSet, k, clusterCenter)
这是人为指定的k值,希望各位以我上传的代码来帮忙写一个自动确定k值的算法
十分感谢
kmeans算法中的K是无法自动确定的,这是kmeans算法的本质决定的。你能做的要么是换其它算法,要么是在kmeans之前通过其它方式来设定K值
不存在题主期望的“自动确定k值的K-means聚类”。如果一定要避开设置k值,建议题主尝试均值飘移聚类(Mean Shift),这也是基于质心的算法,和K-means聚类非常相似,但不需要指定集群数量。另外,还可以尝试基于密度的空间聚类(DBSCAN),同样不需要预先指定集群数量。
下面的代码分别使用K-means聚类和均值飘移聚类对同一个团状簇实施聚类,结果是一致的。
# -*- encoding: utf-8 -*-
"""
《Python高手修炼之道》- k均值聚类和均值漂移聚类
"""
from sklearn import datasets as dss
from sklearn.cluster import KMeans
from sklearn.cluster import MeanShift
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['FangSong']
plt.rcParams['axes.unicode_minus'] = False
X_blob, y_blob = dss.make_blobs(n_samples=[300,400,300], n_features=2)
y_kms = KMeans(init='k-means++', n_clusters=3).fit_predict(X_blob)
msm = MeanShift()
msm.fit(X_blob)
plt.subplot(121)
plt.title('K-means聚类')
plt.scatter(X_blob[:,0], X_blob[:,1], c=y_kms)
plt.subplot(122)
plt.title('MeanShift聚类')
plt.scatter(X_blob[:,0], X_blob[:,1], c=msm.labels_)
plt.show()
自动确定 K值的聚类,理论上没有的。比如说将中国人分类,分成几类最好?理论上就没有最佳的分类数量。
但是,在实践中是有办法的。基本思想是,更多分类应该能使误差平方和(均方差,平均距离)显著下降,否则更多分类就没有意义。实现步骤是,K 不断递增,对每一个 K 计算平均距离 Dis(K),得到一条曲线 Dis(K)~K。该曲线的斜率(梯度)是逐渐减小的,当小于设定的阈值时,就认为不需要进一步细分了。也即此时的 K-1 是最佳 K值。
用层次聚类吧,这个也太麻烦了
还有现在主流的ML聚类算法,可以用dbscan算法。
自动确定没有太大意义
但可以做,你首先要把数据读完,然后分析,然后判断,设计判断依据
用哈希做比较快