K-means(K-均值)Python实现

实验内容

1. 实验基本原理及目的

K-means(K-均值):

K-均值算法把簇形心定义为簇内点的均值

算法的基本思想:

首先,随机的选择k个对象,每个对象初始的代表了一个簇的平均值;

对剩余的每个对象,根据其与各个簇中心的距离,将它赋给最近的簇;

然后重新计算每个簇的平均值。

 这个过程不断重复,直到准则函数收敛。

2. 数据的准备及数据预处理

将数据读入,然后将数据转化为numpy形式,进行归一化处理,这里采用的是0-1归一化。

3. 实验过程

1. 函数介绍:

read(datafile):数据预处理函数,datafile为文件所在位置,返回值为data,为一个numpy类型的数组。

distEclud(vecA, vecB):计算欧式距离的函数,vecA,vecB分别为两个向量,返回值为他们之间的距离。

CenterPoints(dataSet, k):初始点函数,在dataSet中选取K个点作为初始中心点,返回值为一个矩阵,每个行向量为选取的中心点。

K_means(dataSet,k,distMeans=distEclud,createCent=CenterPoints):K—mean聚类函数,dataSet为数据集,k为聚类的个数,distMeans表示距离,createCent表示初始点选择。返回值为最后的中心点,以及分类情况。

transfer(data,clustAssing):将data按照分类结果clustAssing分为三个组,以便于画图,返回值为三个簇的点。

plot(Point1,Point2,Point3):画图函数,输入值为三个簇的点,将聚类结果进行可视化展示。

2.源码


# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
import random
import matplotlib.pyplot as plt 

#预处理数据,做0-1规范化处理
def read(datafile):
    df=pd.read_excel(datafile)
    df.index=df['国家']
    df=df.drop(['国家'],axis=1)
    df=pd.DataFrame(df,dtype=np.float)
    for i in df.columns:
        dfmax=max(df[i])
        dfmin=min(df[i])
        for j in df.index:
            df[i][j]=(df[i][j]-dfmin)/(dfmax-dfmin)
    data=np.array(df)
    return data

#计算两个向量的欧氏距离
def distEclud(vecA, vecB):
    return np.sqrt(np.sum(np.square(vecA-vecB)))

# 构建聚簇中心,取k个(此例中为3)随机质心
def CenterPoints(dataSet, k):
    m,n=np.shape(dataSet)
    centroids = np.mat(np.zeros((k,n)))   # 每个质心有n个坐标值,总共要k个质心
    a=random.sample(list(np.arange(m)),k)
    for i in range(0,k):
        centroids[i,:]=dataSet[a[i],:]
    return centroids

def K_means(dataSet,k,distMeans=distEclud, createCent=CenterPoints):
    m=len(dataSet)
    clusterAssment=np.mat(np.zeros((m,2)))# 用于存放该样本属于哪类及质心距离
# clusterAssment第一列存放该数据所属的中心点,第二列是该数据到中心点的距离
    centroids=createCent(dataSet,k)
    clusterChanged = True #用来判断聚类是否已经收敛
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist=np.inf
            minIndex=-1
            for j in range(k):
                DistJI=distMeans(centroids[j,:],dataSet[i,:])
                if DistJI<minDist:# 如果第i个数据点到第j个中心点更近,则将i归属为j
                    minDist=DistJI
                    minIndex=j
            if clusterAssment[i,0] != minIndex:#如果分配发生变化,则需要继续迭代
                clusterChanged = True;    
            clusterAssment[i,:] = minIndex,minDist**2#并将第i个数据点的分配情况存入字典
        print(centroids)
        for cent in range(k):# 重新计算中心点
            ptsInClust=dataSet[np.nonzero(clusterAssment[:,0].A==cent)[0]]#去第一列等于cent的所有列
            centroids[cent,:]=np.mean(ptsInClust, axis = 0)#算出这些数据的中心点
    return centroids, clusterAssment
#将三类点分开
def transfer(data,clustAssing):
    Point1=[]
    Point2=[]
    Point3=[]
    m=len(data)
    for i in range(m):
        if clustAssing[i,0]==0:
            Point1.append(data[i,:])
        elif clustAssing[i,0]==1:
            Point2.append(data[i,:])
        else:
            Point3.append(data[i,:])
    return Point1,Point2,Point3

def plot(Point1,Point2,Point3):
    fig = plt.figure()
    ax= fig.add_subplot(111, projection ='3d')
    ax.scatter(Point1[:,0],Point1[:,1],Point1[:,2],c='y')
    ax.scatter(Point2[:,0],Point2[:,1],Point2[:,2],c='r')
    ax.scatter(Point3[:,0],Point3[:,1],Point3[:,2],c='g')
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    plt.show()

datafile='D:/ProgramData/file8/data.xls'
data=read(datafile)
lastCenterPoint,clustAssing=K_means(data,3)
print('最后的中心点:')
print(lastCenterPoint)
print('聚类结果:')
print(clustAssing)
Point1,Point2,Point3=transfer(data,clustAssing)
plot(np.array(Point1),np.array(Point2),np.array(Point3))

4. 实验结果分析

输出结果:

最终三个中心点以及聚类结果:

                            

输出的三维聚类图:

分析:

选取不同的初始点,聚类结果有所差别,由结果可知中国队处于三流水平。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值