python实现k-means算法使用Iris数据集

最近正在学习python,尝试用python做一些经典的算法,本文是用python实现k-means算法,没有用现成的库,只是简单的用代码实现算法,在Iris数据集上进行聚类(3类),根据结果来看,聚类效果还是不错的。

Iris数据集

Iris也称鸢尾花卉数据集,包含150个数据,每个数据包含4个属性花 萼长度、花萼宽度、花瓣长度、花瓣宽度 (sepal_length,sepal_width,petal_length,petal_width),可通过这4个 属性预测鸢尾花卉属(Setosa,Versicolour,Virginica)三个种类中 的哪一类。加载数据集的方式为

from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data   # 特征向量,并且是按顺序排列的
lable = iris.target

算法伪代码如下


不多说,直接上代码。

代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
import numpy as np
#支持坐标轴中文
plt.rcParams['font.sans-serif']=['SimHei']
iris = load_iris()
X = iris.data   # 特征向量,并且是按顺序排列的
lable = iris.target  # 标签
#数据集预处理,以花萼面积为横坐标,以花瓣面积做纵坐标
arr = np.array(X)
hua_e = arr[:,0]*arr[:,1]
hua_ban = arr[:,2]*arr[:,3]
############################################
#定义需要的函数
def shuju(k):
    b =set()
    while(len(b)<k):
        b.add(np.random.randint(0,150))
    return(b)
#每个点到中心点距离距离
def  getDistance(point_x,point_y,cent_x,cent_y,k):
    x = point_x
    y = point_y
    x0 = cent_x
    y0 = cent_y
    i = 0
    j = 0
    ds = [[]for i in range(len(x))]

    while i < len(x):
        while j < k:
            M = np.sqrt((x[i]-x0[j])  * (x[i]-x0[j]) + (y[i]-y0[j]) * (y[i]-y0[j]))
            M = round(M,1)
            j = j + 1
            ds[i].append(M)
        j = 0
        i = i + 1
    return(ds)

#计算距离误差
def  EDistance(point_x,point_y,cent_x,cent_y,k):
    x = point_x
    y = point_y
    x0 = cent_x
    y0 = cent_y
    i = 0
    j = 0
    sum = 0
    while i < k:
        while j < len(x):
            M = (x[j]-x0[i])  * (x[j]-x0[i]) + (y[j]-y0[i]) * (y[j]-y0[i])
            M = round(M,1)
            sum += M
            j = j + 1
            #ds[i].append(M)
        j = 0
        i = i + 1
    return(sum)

#计算中心点
def cent(lable):
    temp = lable
    mean_x = []
    mean_y = []
    i = 0
    j = 0
    while i < 3:
        cent_x = 0
        cent_y = 0
        count = 0
        while j < len(x):
            if i == temp[j]:
                count = count + 1
                cent_x = cent_x + x[j]
                cent_y = cent_y + y[j]
            j = j + 1
        cent_x = cent_x / count
        cent_y = cent_y / count
        #更新中心点
        mean_x.append(cent_x)
        mean_y.append(cent_y)
        j = 0
        i = i + 1
    return[mean_x,mean_y]

#按照k值聚类
def julei(ds,x):
    x = x
    x = len(x)
    i = 0
    temp = []
    while i < x:
        temp.append(ds[i].index(min(ds[i])))
        i = i + 1
    return(temp)
##############################################
#主程序部分
#这里聚3类,k取3
k = 3

b = shuju(k)
ceshi_hua_e = [hua_e[i] for i in range(len(hua_e)) if (i in b)]
ceshi_hua_ban = [hua_ban[i] for i in range(len(hua_ban)) if (i in b)]
ceshi_lable = [lable[i] for i in range(len(lable)) if (i in b)]
x = hua_e
y = hua_ban
x0 = ceshi_hua_e
y0 = ceshi_hua_ban
#第一次根据随机种子聚类
n = 0
ds = getDistance(x,y,x0,y0,k)
temp = julei(ds,x)
temp1 = EDistance(x,y,x0,y0,k)
n = n + 1
center = cent(temp)
x0 = center[0]
y0 = center[1]
ds = getDistance(x,y,x0,y0,k)
temp = julei(ds,x)
temp2 = EDistance(x,y,x0,y0,k)
n = n + 1
#比较两次平方误差 判断是否相等,不相等继续迭代
while np.abs(temp2 - temp1) != 0:
    temp1 = temp2
    center = cent(temp)
    x0 = center[0]
    y0 = center[1]
    ds = getDistance(x,y,x0,y0,k)
    temp = julei(ds,x)
    temp2 = EDistance(x,y,x0,y0,k)
    n = n + 1
    print(n,temp2)
#结果可视化
print("迭代次数: ", n) # 统计出迭代次数
print('质心位置:',x0,y0)
plt.scatter(x0,y0,color='r',s=50,marker='s')
plt.scatter(x,y,c=temp,s=25,marker='o')
plt.xlabel('花萼面积')
plt.ylabel('花瓣面积')
plt.title("聚3类")
plt.show()
 

运行结果

聚类结果
从运行结果可以看出,聚类效果还是很理想的,算法在迭代21次就收敛了,图中红色的方块代表聚类中心。具体的结果每次运行都会有所不同,迭代次数也不一样,与最初的随机种子有关。
第一次写博客,写的不好,请多指教。
k-means算法的c语言版可以参考这个

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值