python实现kmeans聚类不使用科学计算包_k-means聚类分析 python 代码实现(不使用现成聚类库)...

这篇博客介绍了如何在Python中不使用现成的科学计算包实现K-means聚类算法。通过8:2的比例划分训练集和测试集,尝试了多个K值,并分析了不同K值下的SSE(均方误差)以确定最佳K值。最终,博主发现K=4时数据聚类效果最佳,这个结论基于肘部法则。
摘要由CSDN通过智能技术生成

标签:RKE   show   个数   lin   rand   lib   小白   pytho   博客

一、实验目标

1、使用 K-means 模型进行聚类,尝试使用不同的类别个数 K,并分析聚类结果。

?    2、按照 8:2 的比例随机将数据划分为训练集和测试集,至少尝试 3 个不同的 K 值,并画出不同 K 下 的聚类结果,及不同模型在训练集和测试集上的损失。对结果进行讨论,发现能解释数据的最好的 K 值。

二、算法原理

首先确定k,随机选择k个初始点之后所有点根据距离质点的距离进行聚类分析,离某一个质点a相较于其他质点最近的点分配到a的类中,根据每一类mean值更新迭代聚类中心,在迭代完成后分别计算训 练集和测试集的损失函数SSE_train、SSE_test,画图进行分析。

20200601134349864201.png

伪代码如下:

num=10 #k的种类

for k in range(1,num):

随机选择k个质点for i in range(n): #迭代n次

根据点与质点间的距离对于X_train进行聚类

根据mean值迭代更新质点

计算SSE_train

计算SSE_test

画图

算法流程图:

20200601134349997019.png

三、代码实现

1、导入库

importpandas as pdimportmatplotlib.pyplot as pltimportnumpy as npfrom sklearn.model_selection import train_test_split

2、计算距离

defdistance(p1,p2):return np.sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2)

3、计算均值

defmeans(arr):return np.array([np.mean([p[0] for p in arr]),np.mean([p[1] for p in arr])])

4、二维数据处理

#数据处理

data= pd.read_table(‘cluster.dat‘,sep=‘\t‘,header=None)

data.columns=[‘x‘]

data[‘y‘]=Nonefor i in range(len(data)): #遍历每一行

column = data[‘x‘][i].split( ) #分开第i行,x列的数据。split()默认是以空格等符号来分割,返回一个列表

data[‘x‘][i]=column[0] #分割形成的列表第一个数据给x列

data[‘y‘][i]=column[1] #分割形成的列表第二个数据给y列

list=[]

list1=[]for i inrange(len(data)):

list.append(float(data[‘x‘][i]))

list.append(float(data[‘y‘][i]))

list1.append(list)

list=[]

arr=np.array(list1)print(arr)

20200601134350087842.png

5、划分数据集和训练集

#按照8:2划分数据集和训练集

X_train, X_test = train_test_split(arr,test_size=0.2,random_state=1)

6、主要聚类实现

count=10 #k的种类:1、2、3...10

SSE_train=[] #训练集的SSE

SSE_test=[] #测试集的SSE

n=20 #迭代次数

for k in range(1,count):

cla_arr=[] #聚类容器

centroid=[] #质点

for i inrange(k):

j=np.random.randint(0,len(X_train))

centroid.append(list1[j])

cla_arr.append([])

centroids=np.array(centroid)

cla_tmp=cla_arr #临时训练集聚类容器

cla_tmp1=cla_arr #临时测试集聚类容器

for i in range(n): #开始迭代

for e in X_train: #对于训练集中的点进行聚类分析

pi=0

min_d=distance(e,centroids[pi])for j inrange(k):if(distance(e,centroids[j])min_d):

min_d=distance(e,centroids[j])

pi=j

cla_tmp[pi].append(e)#添加点到相应的聚类容器中

for m inrange(k):if(n-1==i):breakcentroids[m]=means(cla_tmp[m])#迭代更新聚类中心

cla_tmp[m]=[]

dis=0for i in range(k): #计算训练集的SSE_train

for j inrange(len(cla_tmp[i])):

dis+=distance(centroids[i],cla_tmp[i][j])

SSE_train.append(dis)

col= [‘HotPink‘,‘Aqua‘,‘Chartreuse‘,‘yellow‘,‘red‘,‘blue‘,‘green‘,‘grey‘,‘orange‘] #画出对应K的散点图

for i inrange(k):

plt.scatter([e[0]for e in cla_tmp[i]],[e[1] for e in cla_tmp[i]],color=col[i])

plt.scatter(centroids[i][0],centroids[i][1],linewidth=3,s=300,marker=‘+‘,color=‘black‘)

plt.show()for e in X_test: #测试集根据训练集的质点进行聚类分析

ki=0

min_d=distance(e,centroids[ki])for j inrange(k):if(distance(e,centroids[j])min_d):

min_d=distance(e,centroids[j])

ki=j

cla_tmp1[ki].append(e)for i in range(k): #计算测试集的SSE_test

for j inrange(len(cla_tmp1[i])):

dis+=distance(centroids[i],cla_tmp1[i][j])

SSE_test.append(dis)

20200601134350147415.png

7、画图

SSE=[] #计算测试集与训练集SSE的差值

for i inrange(len(SSE_test)):

SSE.append(SSE_test[i]-SSE_train[i])

x=[1,2,3,4,5,6,7,8,9]

plt.figure()

plt.plot(x,SSE_train,marker=‘*‘)

plt.xlabel("K")

plt.ylabel("SSE_train")

plt.show()#画出SSE_train的图

plt.figure()

plt.plot(x,SSE_test,marker=‘*‘)

plt.xlabel("K")

plt.ylabel("SSE_test")

plt.show()#画出SSE_test的图

plt.figure()

plt.plot(x,SSE,marker=‘+‘)

plt.xlabel("K")

plt.ylabel("SSE_test-SSE_train")

plt.show()#画出SSE_test-SSE_train的图

20200601134350267537.png

20200601134350338829.png

四、实验结果分析

可以看出SSE随着K的增长而减小,测试集和训练集的图形趋势几乎一致,在相同的K值下,测试集的SSE大于训练集的SSE。于是我对于在相同的K值下的SSE_test和SSE_train做了减法(上图3),可知K=4时数据得出结果最好。这里我主要使用肘部原则来判断。本篇并未实现轮廓系数,由于博主是python小白,故此次代码参考了一部分CSDN的博客:https://blog.csdn.net/qq_37509235/article/details/82925781

k-means聚类分析 python 代码实现(不使用现成聚类库)

标签:RKE   show   个数   lin   rand   lib   小白   pytho   博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值