Python k-均值聚类算法二维实例

k-均值聚类算法二维实例,不多解释,解释就是掩饰,复制粘贴即可运行。

import time
import numpy as np
import random
import matplotlib.pyplot as plt
import operator

def func01():    #生成二维随机点

    #random.seed(1)
    kjz1=[[random.randint(50,100),random.randint(50,100)] for j in range(0,200)]
    kjz1.extend([[random.randint(150,200),random.randint(150,200)] for j in range(0,200)])
    kjz1.extend([[random.randint(60,110),random.randint(150,200)] for j in range(0,200)])
    kjz1.extend([[random.randint(130,180),random.randint(50,100)] for j in range(0,200)])
    kjz1.extend([[random.randint(150,200),random.randint(250,300)] for j in range(0,200)])
    kjz1.extend([[random.randint(60,110),random.randint(250,300)] for j in range(0,200)])
    return kjz1

def func02(kjz2w): #绘图

    if kjz2w!=[]:
        colors=['b','g','r','c','m','y','k'];s=0;
        for j in kjz2w:
            for i in j:
                plt.plot(i[0], i[1], color=colors[s%len(colors)], marker='.')
            s=s+1;
        plt.ion();plt.show();plt.pause(5);plt.close();

def func03(kjz1,k):    #计算初始均值,并返回初始分组

    minxy=np.min(kjz1,axis=0).tolist();maxxy=np.max(kjz1,axis=0).tolist();
    xjg=(maxxy[0]-minxy[0])/k;yjg=(maxxy[1]-minxy[1])/k;
    meanxy=[];meanxy.append([minxy[0],minxy[1]]);meanxy.append([maxxy[0],maxxy[1]]);
    for j in range(1,k-1):
        meanxy.append([minxy[0]+xjg*j,minxy[1]+yjg*j])
    kjz2wxy2=[[] for j in range(0,len(meanxy))];
    for j in kjz1:
        s=0;lslb=[];
        for k in meanxy:
            lslb.append([s,(j[0]-k[0])**2+(j[1]-k[1])**2]);s=s+1; #一个坐标一组
        lslb.sort(reverse=False,key=operator.itemgetter(1))  #正序
        kjz2wxy2[lslb[0][0]].append(j)
    return kjz2wxy2

def func05(lb2): #剔除空列表

    j=0;
    while(True):
        if len(lb2[j])<=0:
            lb2.pop(j)
        else:
            j=j+1;
        if j>=len(lb2):
            break
    return lb2

def func06(kjz2wxy): #求组合中心(均值)

    meanxy=[];
    for j in kjz2wxy:
        meanxy.append(np.mean(j,axis=0).tolist())
    kjz2wxy2=[[] for j in range(0,len(meanxy))];
    for j in kjz2wxy:
        for i in j: #点
            s=0;lslb=[];
            for k in meanxy:
                lslb.append([s,(i[0]-k[0])**2+(i[1]-k[1])**2]);s=s+1;
            lslb.sort(reverse=False,key=operator.itemgetter(1))  #正序
            kjz2wxy2[lslb[0][0]].append(i)
    kjz2wxy2=func05(kjz2wxy2)
    return kjz2wxy2,meanxy

def func07(kjz2w,fz):

    kjz2wxy=func03(kjz2w,fz) #坐标列表,分组,0-按照x轴均分
    j=0;
    while(True):
        kjz2wxy,meanxy=func06(kjz2wxy)
        if j>0 and meanxy==meanxy2:
            break
        meanxy2=meanxy.copy();
        j=j+1;
    print('迭代%d次' % (j))
    func02(kjz2wxy) #绘图

if __name__=='__main__':

    start=time.time();
    for j in range(0,10):
        kjz2w=func01()
        func07(kjz2w,6) #分6组

    print('Time used:',int((time.time()-start)/60*10)/10,'分钟')

这里写图片描述
上图是初始均值选取比较好的时候的情况,还有些情况是下面这样的。
这里写图片描述
今天还写了一种画蛇添足的算法,从一维算法过度来的,就像下面这样的。

import time
import numpy as np
import random
import matplotlib.pyplot as plt
import operator


def func01():    #生成二维随机点

    random.seed(1)
    kjz1=[[random.randint(50,100),random.randint(50,100)] for j in range(0,200)]
    kjz1.extend([[random.randint(150,200),random.randint(150,200)] for j in range(0,200)])
    kjz1.extend([[random.randint(60,110),random.randint(150,200)] for j in range(0,200)])
    kjz1.extend([[random.randint(130,180),random.randint(50,100)] for j in range(0,200)])
    kjz1.extend([[random.randint(150,200),random.randint(250,300)] for j in range(0,200)])
    kjz1.extend([[random.randint(60,110),random.randint(250,300)] for j in range(0,200)])
    #绘图
    plt.xlabel('x-axis')
    plt.ylabel('y-axis')  
    for j in kjz1:
        plt.plot(j[0], j[1], color='b', marker='.', label='y1 data')
    plt.ion();plt.show();plt.pause(1);plt.close();

    return kjz1

def func02(kjz1,k,axis):    #k个均值分k份

    kjz1.sort(reverse=False,key=operator.itemgetter(1-axis))  #正序
    kjz1.sort(reverse=False,key=operator.itemgetter(axis))  #正序
    wb2=kjz1.copy();
    #初始均匀分组
    xlb=[];a=round(len(wb2)/k);b=len(wb2)%k;
    for j in range(1,k+1):
        xlb.append(j*a)
        if j==k:
            xlb[j-1]=xlb[j-1]+b;
    j=0;wb1=[];
    for j in range(0,k):
        wb1.append([])
    i=0;j=0;
    while(i<=len(wb2)-1):
        wb1[j].append(wb2[i]);
        if i>=xlb[j]-1:
            j=j+1;
        i=i+1;
    kj1=means(wb1,axis);#初始分组均值

    bj=1;
    while(True):
        wb2=kjz1.copy();
        if bj!=1:
            kj1=kj2.copy();
        wb3=[];
        for j in range(0,k-1):
            wb3.append([])
        for j in range(0,k-1):
            i=0;
            while(True):
                if wb2[i][axis]<=kj1[j]:
                    wb3[j].append(wb2.pop(i));
                else:
                    i=i+1;
                if i>=len(wb2):
                    break
        wb3.append(wb2)
        for j in wb3:
            if len(j)<=0:
                print('分组出现空组,返回[]');return []
        kj2=means(wb3,axis);#过程均值
        if bj==2:
            if kj1==kj2:
                break
        bj=2;
    return wb3

def means(lb1,axis):    #计算均值

    mean1=[];mean2=[];std1=[];
    for j in lb1:
        mean1.append(np.mean(j,axis=0).tolist())
    for j in range(1,len(mean1)):
        mean2.append(np.mean([mean1[j-1][axis],mean1[j][axis]])) #分组均值使用各组的均值
    return mean2

def func03(kjz2w): #绘图

    if kjz2w!=[]:
        colors=['b','g','r','c','m','y','k'];s=0;
        for j in kjz2w:
            for i in j:
                plt.plot(i[0], i[1], color=colors[s%len(colors)], marker='.', label='y1 data')
            s=s+1;
        plt.ion();plt.show();plt.pause(3);plt.close();

def func04(kjz2wx,kjz2wy): #x,y 组整合

    kjz2wxy=[[] for j in range(0,len(kjz2wx)*len(kjz2wy))];k=0;
    for j in kjz2wx:
        for i in kjz2wy:
            for a in j:
                if a in i:
                    kjz2wxy[k].append(a);
            k=k+1;
    kjz2wxy=func05(kjz2wxy)
    return kjz2wxy


def func05(lb2): #组合迭代

    j=0;
    while(True):
        if len(lb2[j])<=0:
            lb2.pop(j)
        else:
            j=j+1;
        if j>=len(lb2):
            break
    return lb2


def func06(kjz2wxy): #组合迭代

    #求组合中心(均值)
    meanxy=[];
    for j in kjz2wxy:
        meanxy.append(np.mean(j,axis=0).tolist())
    kjz2wxy2=[[] for j in range(0,len(meanxy))];
    for j in kjz2wxy:
        for i in j: #点
            s=0;lslb=[];
            for k in meanxy:
                lslb.append([s,(i[0]-k[0])**2+(i[1]-k[1])**2]);s=s+1;
            lslb.sort(reverse=False,key=operator.itemgetter(1))  #正序
            kjz2wxy2[lslb[0][0]].append(i)
    kjz2wxy2=func05(kjz2wxy2)
    return kjz2wxy2,meanxy

def func07(kjz2w):

    kjz2wx=func02(kjz2w,2,0) #列表,分组数,x轴0,y轴1
    func03(kjz2wx) #绘图

    kjz2wy=func02(kjz2w,3,1)
    func03(kjz2wy) #绘图

    kjz2wxy=func04(kjz2wx,kjz2wy)
    func03(kjz2wxy) #绘图

    #kjz2wxy=func06(kjz2wxy)
    j=0;
    while(True):
        kjz2wxy,meanxy=func06(kjz2wxy)
        if j>0 and meanxy==meanxy2:
            break
        meanxy2=meanxy.copy();
        j=j+1;
    print('迭代%d次' % (j))
    func03(kjz2wxy) #绘图

if __name__=='__main__':

    start=time.time();
    kjz2w=func01()

    func07(kjz2w)

    print('Time used:',int((time.time()-start)/60*10)/10,'分钟')
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值