机器学习-kmeans(实现步骤、sklearn实现、python自实现、优缺点)
机器学习-kmeans
KMeans(K均值)是典型的基于距离的排他划分方法:给定一个n个对象的数据集,它可以构建数据的k个划分,每个划分就是一个聚类,并且k<=n,同时还满足两个要求:
1.每个组至少包含一个对象
2.每个对象必须属于且仅属于一个组
优点:
擅长处理球状分布的数据,当结果聚类是密集的,而且类和类之间的区别比较明显时,K均值的效果比较好
对于处理大数据及,这个算法是相对可伸缩的和高效的,它的复杂度是O(nkt),n是对象的个数,k是簇的数目,t是迭代的次数。
缺点:
算法的初始中心点选择与算法的运行效率密切相关,而随机选取中心点有可能导致迭代次数很大或者限于某个局部最优状态;通常k<<n,且t<<n,所以算法经常以局部最优收敛
K均值的最大问题是要求用户必须事先给出k的个数,k的选择一般都基于经验值和多次实验的结果,对于不同的数据集,k的取值没有可借鉴性。
对异常偏离的数据敏感--离群点;K均值对噪声和孤立点数据是敏感的,少量的这类数据就能对平均值造成极大的影响。
步骤:
1.首先创建一个初始化分,随机的选择k个对象,每个对象初始的代表一个聚类中心。对于其他对象,根据其与各个聚类中心的距离,将它们赋给最近的聚类。
递归重定位,尝试通过对象在划分间移动来改进划分。重定位即:当有新的对象加入聚类或者已有对象离开聚类的时候,重新计算聚类的平均值,然后对对象进行重新分配。这个过程不断重复,直到聚类中的数据不再变化为止。
sklearn代码如下
from numpy import * from sklearn.cluster import KMeans import matplotlib.pyplot as plt def file2matrix(filePath, lineSplit): dataSet = [] fr = open(filePath, 'r') content = fr.read() for line in content.splitlines(): dataSet.append([line.split('\t')[0], line.split('\t')[1]]) fr.close() return dataSet def drawScatter(plt, dataMat, size, color, mrkr): X = dataMat[:,0] Y = dataMat[:,-1] plt.scatter(X.tolist(), Y.tolist(), c=color, marker=mrkr, s=size) plt.xlabel("x") plt.ylabel("y") plt.title("Kmeans") plt.legend() k = 4 dataSet = file2matrix("/Users/FengZhen/Desktop/accumulate/机器学习/推荐系统/kmeans聚类测试集.txt", "\t") dataMat = mat(dataSet) print(dataMat) # 执行kmeans算法 kmeans = KMeans(init='k-means++', n_clusters=k) kmeans.fit(dataMat) print(kmeans.cluster_centers_) #绘制计算结果 drawScatter(plt, dataMat, size=20, color='b', mrkr='.') drawScatter(plt, kmeans.cluster_centers_, size=20, color='red', mrkr='D') plt.show()
python自实现
import matplotlib.pyplot as plt
from numpy import *
import numpy as np
# 数据文件转矩阵
def file2matrix(filePath):
dataSet = []
fr = open(filePath, 'r')
content = fr.read()
for line in content.splitlines():
dataSet.append([line.split('\t')[0], line.split('\t')[1]])
fr.close()
return dataSet
# 根据聚类中心绘制散点图,以及绘制聚类中心
def color_cluster(dataindx, dataSet, plt, k=4):
# print(dataindx)
plt.scatter(dataSet[:, 0].tolist(), dataSet[:, 1].tolist(), c='blue', marker='o')
# index = 0
# datalen = len(dataindx)
# for indx in range(datalen):
# if int(dataindx[index]) == 0:
# plt.scatter(dataSet[index, 0].tolist(),dataSet[index, 1].tolist(), c='blue', marker='o')
# elif int(dataindx[index]) == 1:
# plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='green', marker='o')
# elif int(dataindx[index]) == 2:
# plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='red', marker='o')
# elif int(dataindx[index]) == 3:
# plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='cyan', marker='o')
# index += 1
# 绘制散点图
def drawScatter(plt, mydata, size=20, color='blue', mrkr='o'):
# print(mydata.T[0][0].tolist())
# print(mydata.T[1][0].tolist())
plt.scatter(mydata.T[0][0].tolist(), mydata.T[1][0].tolist(), s=size, c=color, marker=mrkr)
# 欧氏距离公式
def distEclud(vecA, vecB):
return linalg.norm(vecA.astype(float) - vecB.astype(float))
# 随机生成聚类中心
def randCenters(dataSet, k):
n = shape(dataSet)[1] # 列数
clustercents = mat(zeros((k, n))) # 初始化聚类中心矩阵:k*n
for col in range(n):
mincol = min(dataSet[:, col]).astype(float); maxcol = max(dataSet[:, col]).astype(float)
# random.rand(k,1)):产生一个0-1之间的随机数向量:k,1表示产生k行1列的随机数
clustercents[:, col] = mat(mincol + float(maxcol - mincol) * random.rand(k, 1))
return clustercents
def kMeans(dataSet, k):
m = dataSet.shape[0]
ClustDist = mat(zeros((m, 2)))
clustercents = randCenters(dataSet, k) # 随机生成聚类中心
flag = True # 迭代标记
counter = [] # 初始化计数器
while flag:
flag = False # 默认设置退出标志
# 算法停止条件:ClustDist[i, 0] == minIndex
for i in range(m):
# 遍历k个聚类中心,获取最短距离
distlist = [distEclud(clustercents[j, :], dataSet[i, :]) for j in range(k)]
minDist = min(distlist) # 获取最小距离
minIndex = distlist.index(minDist) # 获取最小距离所属的簇
if ClustDist[i, 0] != minIndex: # 找到了一个新聚类中心
flag = True # 重置标志位为True,继续迭代
# 更新聚类中心
ClustDist[i, :] = minIndex, minDist
for cent in range(k):
# 从ClustDist的第一列中筛选出等于cent值的行下标
ptsInClust = dataSet[nonzero(ClustDist[:, 0].A == cent)[0]]
# 计算ptsInClust各列的均值
clustercents[cent, :] = mean(ptsInClust.astype(float), axis=0)
return clustercents, ClustDist
dataMat = file2matrix("/Users/FengZhen/Desktop/accumulate/机器学习/推荐系统/kmeans聚类测试集.txt") # 从文件构建的数据集
dataSet = mat(dataMat) # 转换为矩阵形式
k = 4 # 外部指定的聚类中心
clustercents,ClustDist = kMeans(dataSet, k)
# print("clustercents:\n", clustercents)
# color_cluster(ClustDist[:, 0:1], dataSet, plt)
# drawScatter(plt, clustercents, size=20, color='red', mrkr='D')
# plt.show()
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库