K-means算法实现及分析

K-means算法对data中数据进行聚类分析

1. 算法原理描述

K-means算法是一种典型的无监督学习聚类算法。
而算法的具体思想是这样的:

  1. 从数据集中选择k个样本作为初始均值向量且分别带上其簇标记
    (初始值的选择也是kmeans算法里的重要环节,但这里我首先尝试随机选择,可能在后续学习后会更新其他的方法)
  2. 计算每一个样本与k个均值向量的距离,并带上与它距离最小的均值向量的簇标记,并放入对应集合里
    (距离的计算也有很多方法,可能在后续学习后会更新其他的方法)
  3. 计算集合的新的均值向量,若与上一次均值向量不一致,跳转至第二步骤开启新的一轮迭代;若与上一轮均值向量相同,则跳出循环,并将此时的均值向量和分类好的k个簇作为结果输出;

2. 写出K-means具体功能函数

  • 载入数据:
def loadData(filename):
    infile = open(filename, 'r')
    x = []
    y = []
    for line in infile:
        trainningset = line.split(' ', 1)
        x.append(trainningset[0])
        trainningset[1] = trainningset[1].replace('\n','')
        y.append(trainningset[1])
    x = [np.double(item) for item in x]
    y = [np.double(item) for item in y]
    return x, y
  • 计算与簇中心的距离:
def distance(a,b,c,d):
    return pow(pow((a-c),2)+pow((b-d),2), 0.5)
  • 将每一个样本重新归类:
def iteration(k,meansx,meansy,x,y):
    while 1:
        Cx = [[] for i in range(k)]
        Cy = [[] for i in range(k)]
        ans = []
        finalmeansx = []
        finalmeansy = []
        for item in range(len(x)):
            mindis = 1000
            minindex = -1
            for ele in range(k):
                if distance(x[item],y[item],meansx[ele],meansy[ele]) < mindis:
                    mindis = distance(x[item],y[item],meansx[ele],meansy[ele])
                    minindex = ele
            ans.append(minindex)
            Cx[minindex].append(x[item])
            Cy[minindex].append(y[item])
        for i in range(k):
            finalmeansx.append(np.mean(Cx[i]))
            finalmeansy.append(np.mean(Cy[i]))
        if finalmeansx == meansx and finalmeansy == meansy:
            break
        else:
            meansx = finalmeansx
            meansy = finalmeansy
    return finalmeansx,finalmeansy,Cx,Cy,ans
  • kmeans主函数
def kmeans(k,x,y):
    meansx = random.sample(x, k)
    meansy = random.sample(y, k)
    print(meansx)
    print(meansy)
    finalmeansx,finalmeansy,Cx,Cy,ans = iteration(k,meansx,meansy,x,y)

3. 可视化画图,不同类数据采用不同颜色for item in range(k):

f = open("E:\query.txt",'a')
for item in range(k):
    f.write("第"+item.__str__()+"个簇:\n")
    f.write("均值中心为("+finalmeansx[item].__str__()+","+finalmeansy[item].__str__()+")\n")
    scatter(finalmeansx[item], finalmeansy[item],c=colors[item],marker='x')
    f.write("簇内元素有:"+len(Cx[item]).__str__()+"个\n")
    for i in range(len(Cx[item])):
        f.write("("+Cx[item][i].__str__()+","+Cy[item][i].__str__()+")\n")
        scatter(Cx[item][i],Cy[item][i],c=colors[item])

4. 完整代码

import matplotlib
import numpy as np
import random
from matplotlib.pyplot import plot, scatter

colors=['b','c','g','k','m','r','y']
#因为最后需要不同颜色绘图,但python不是很精通,所以最后采取了手动变色(滑稽

def loadData(filename):  #把数据导入
    infile = open(filename, 'r')
    x = []
    y = []
    for line in infile:
        trainningset = line.split(' ', 1)
        x.append(trainningset[0])
        trainningset[1] = trainningset[1].replace('\n','')
        #这里也是因为我的python技术不精,不知道为啥划分后trainningset[1]后多了换行符,只好手动切除了
        y.append(trainningset[1])
    x = [np.double(item) for item in x]
    y = [np.double(item) for item in y]
    return x, y

def distance(a,b,c,d): #最简单的距离计算方法哈!
    return pow(pow((a-c),2)+pow((b-d),2), 0.5)

def iteration(k,meansx,meansy,x,y): 
#kmeans的核心函数,找到最终的均值向量
    while 1:
        Cx = [[] for i in range(k)]
        Cy = [[] for i in range(k)]
        ans = []
        finalmeansx = []
        finalmeansy = []
        for item in range(len(x)):
            mindis = 1000
            minindex = -1
            for ele in range(k):
                if distance(x[item],y[item],meansx[ele],meansy[ele]) < mindis:
                    mindis = distance(x[item],y[item],meansx[ele],meansy[ele])
                    minindex = ele
            ans.append(minindex)
            Cx[minindex].append(x[item])
            Cy[minindex].append(y[item])
        for i in range(k):
            finalmeansx.append(np.mean(Cx[i]))
            finalmeansy.append(np.mean(Cy[i]))
        if finalmeansx == meansx and finalmeansy == meansy:
            break
        else:
            meansx = finalmeansx
            meansy = finalmeansy
    return finalmeansx,finalmeansy,Cx,Cy,ans

def kmeans(k,x,y):
    meansx = random.sample(x, k)
    meansy = random.sample(y, k)
    print(meansx)
    print(meansy)
    finalmeansx,finalmeansy,Cx,Cy,ans = iteration(k,meansx,meansy,x,y)
    #修改后代码:
    f = open("E:\query.txt",'a')
    for item in range(k):
        f.write("第"+item.__str__()+"个簇:\n")
        f.write("均值中心为("+finalmeansx[item].__str__()+","+finalmeansy[item].__str__()+")\n")
        scatter(finalmeansx[item], finalmeansy[item],c=colors[item],marker='x')
        f.write("簇内元素有:"+len(Cx[item]).__str__()+"个\n")
        for i in range(len(Cx[item])):
            f.write("("+Cx[item][i].__str__()+","+Cy[item][i].__str__()+")\n")
            scatter(Cx[item][i],Cy[item][i],c=colors[item])
    """
    #以下就是在输出框输出分类结果
    for item in range(k):
        print("第"+item.__str__()+"个簇:\n")
        print("均值中心为("+finalmeansx[item].__str__()+","+finalmeansy[item].__str__()+")\n")
        #最终簇中心用x突显
        scatter(finalmeansx[item], finalmeansy[item],c=colors[item],marker='x')
        print("簇内元素有:"+len(Cx[item]).__str__()+"个\n")
        for i in range(len(Cx[item])):
            print("("+Cx[item][i].__str__()+","+Cy[item][i].__str__()+")\n")
            #画散点图
            scatter(Cx[item][i],Cy[item][i],c=colors[item])"""



datax,datay = loadData("E:\data.txt")
k = int(input("请问需要分为几类:"))
kmeans(k,datax,datay)
#刚开始不知道为什么不弹出画图框,后来加了这个就出来啦
matplotlib.pyplot.figure(1)
matplotlib.pyplot.show()

实验结果

在这里插入图片描述在这里插入图片描述(应该要把它导出到文件里的,再去修改修改!)
改好了!
(又学到了!开心!)
将最后的数据生成txt文件存在了E盘里:
在这里插入图片描述

感想

  • 其实之前只有在计算方法课上用过一段时间python,并没有自己主动地深入地学习过python,而对于数据处理和可视化,python有着其独特优势,希望在之后能够更多地学习了解python。
  • 这次实验其实写的python代码很冗余,希望以后了解更多后能够加以修改!
  • 先在E盘里找,找不到就自动创建
f = open("E:\query.txt",'a')

有问题的地方希望各位加以指正!

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值