K-means算法实现

1.实验数据构建
首先构建实验所用的数据,这里我才用的是随机数生成的形式,生成1000个二
维空间的点,存储到特定文件与集合中,并在函数结束时将集合返回。代码如下:
在这里插入图片描述
2.K-means算法实现
有了数据之后,接下来要做的就是K-means算法本身的实现了,首先,先初始化
k个点作为初始中心点,这里的k值我设置为3。为了使得生成的初始中心点与实际的数据点分布相符,我采用了x_rand = min + (max-min)*random(1)的形式,其中min与max分别为当前维度取值的最大值与最小值,x_rand为当前维度的初始值。代码如下:
在这里插入图片描述
有了初始中心点后,便开始进行聚类。遍历所有的数据点,针对每一个数据点,找出距离该数据点距离最近的中心点,然后将该数据点与对应中心点归为一类。完成一次遍历后,针对每一个类别,计算类别中所有数据的每个维度的平均值,将所有维度平均值组合起来形成新的中心点,然后重复上述过程,直至所有数据点的类别不再变化为止。代码如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.聚类结果写入文件
聚类完成后,将聚类所得信息写入相应文件中。代码如下:
在这里插入图片描述
4.聚类结果可视化
将聚类结果以散点图的形式输出,代码和效果如下:
在这里插入图片描述在这里插入图片描述
注:其中红色的点为各类别的中心点。

完整代码如下:
#用户聚类
from numpy import *
import matplotlib.pyplot as plt

#生成随即数据并写文件
def rand_data(filename):
    fw = open(filename,'w')
    dataSet = random.rand(1000,2)
    #print(dataSet)
    for data in dataSet:
        #print(data)
        data = str(data).split()
        fw.write(','.join(data) + "\n")
    fw.close()
    return dataSet

# #读数据
# def loadData(filename):
#     data=[]
#     fo=open(filename)
#     for line in fo:
#         line=line.replace('\n','')
#         l1=line.split(',')
#         ls=[]
#         for i in range(1,2):
#             ls.append(float(l1[i]))
#         #print(ls)
#         data.append(ls)
#     fo.close()
#     return data

#计算两个点之间的距离
def dist(va,vb):
    return sqrt(nansum(power((va-vb),2)))


#生成随机中心,k为聚类个数,dataset为原始用于聚类的数据集
def randCents(dataSet,k):
    #获取数据的列数,即每条数据有几个属性
    n=shape(dataSet)[1]
    #生成一个k行n列的全零矩阵
    cents=mat(zeros((k,n)))
    for i in range(n):
        mini=min(dataSet[:,i])
        maxi=max(dataSet[:,i])
        rangei=float(maxi-mini)
        #random.rand(k,1)生成一个k行一列的随机数组,
        # 每个元素分布在(0,1)之间
        cents[:,i]=mini+rangei*random.rand(k,1)
    return cents

#k-means的主体方法
def kMeans(dataSet,k,getDist=dist,getCents=randCents):
    #shape[0],数据的行数     shape[1],数据的列数
    m=shape(dataSet)[0]
    #print(m)
    #生成一个m行两列的全零数组,并转化为矩阵
    cluster=mat(zeros((m,2)))
    #初始化K个聚类中心
    cents=getCents(dataSet,k)
    flag=True
    while flag:
        flag=False
        #对每一个数据点,计算他与每个分类的中心点的距离中
        # 最近的那一个中心点x,然后将它的类别设为x
        for i in range(m):
            minDist=10000000000000
            minIdx=-1
            for j in range(k):
                dist=getDist(cents[j,:],dataSet[i,:])
                if dist<minDist:
                    minDist=dist
                    minIdx=j
            #只要有一个点的类别发生变化,就继续循环下去
            if cluster[i,0]!=minIdx:
                flag=True
            #cluster中的数据为类别以及该点距离这一类中心点的距离
            cluster[i,:]=minIdx,minDist**2
        #print(cents)
        #将所有的数据根据上面所分的类别进行处理,
        # 计算每类数据当中的新的中心点,然后重新迭代k-means算法
        for cent in range(k):
            pts=[]
            for data in range(m):
                if cluster[data,0]==cent:
                    pts.append(dataSet[data,:])
            #pts=mat(pts)
            if(len(pts)!=0):
                cents[cent,:]=nanmean(pts,axis=0)
    classification = []
    for line in range(len(cluster)):
        classification.append(int(cluster[line,0]))
    #cents 为最终的聚类中心点,
    # cluster为每个点的类别以及该点距离他所属类别中心的距离 ,
    # classification表示该点所属类别
    return cents,cluster,classification

#将结果i而文件输出
def writeMat(m,filename):
    fw=open(filename,'w')
    for i in range(shape(m)[0]):
        row=[]
        for j in range(shape(m)[1]):
            row.append(str(m[i,j]))
        fw.write(','.join(row)+'\n')
    fw.close()

def draw_scatter(dataSet,classification,cents):
    #所有的数据
    x = []
    y = []
    type = []
    #print(dataSet)
    for line in range(len(dataSet)):
        x.append(dataSet[line,0])
        y.append(dataSet[line,1])
        type.append(classification[line])

    #中心点
    cent_x = []
    cent_y = []
    for line in range(len(cents)):
        cent_x.append(cents[line,0])
        cent_y.append(cents[line,1])

    plt.scatter(x, y, c=type, marker="o")
    plt.colorbar()
    plt.scatter(cent_x,cent_y,c='r')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title('K-Means')
    plt.show()

def main(filename,k):
    data = rand_data(filename)
    #data=loadData(filename)
    #通过mat操作将data转化成矩阵
    dataSet=mat(data)
    cents,cluster,classification=kMeans(dataSet,k)
    #print(cents0)
    writeMat(cents,str(k)+'cents__'+filename)
    writeMat(cluster,str(k)+'cluster__'+filename)
    print(classification)
    draw_scatter(dataSet,classification,cents)
main('K-means.csv',3)
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值