数据仓库与数据挖掘——k-Means算法

一、基本介绍

        聚类就是对大量未知标注的数据集,按数据的内在相似性将数据集划分为多个类别,使类别内的数据相似度较大而类别间的数据相似度较小。由这个定义可以知道,数据集并没有目标值。因此聚类算法属于无监督算法。k-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为k个簇,同时使簇内的点尽量紧密的连在一起,簇间的距离尽量的大。

二、核心思想

        给定一个有n个对象的数据集,划分聚类技术将构造数据k个划分,每一个划分就代表一个簇,k≤n。也就是说它将数据划分为k个簇,而且这k个划分满足下列条件:

        ①每一个簇至少包含一个对象;

        ②每一个对象属于且仅属于一个簇。

        对于给定的k,算法首先给出一个初始的划分方法,以后通过反复迭代的方法改变划分,使得每一次改进之后的划分方案都较前一次更好,即同一簇中的对象越近越好,而不同簇中的对象越远越好。目标是最小化所有对象与其参照点之间的相异度之和,这里的远近或者相异度/相似度实际上是聚类的评价函数。

三、原理演示

        给出样本点和k值

         随机选出k个初始点

        标出聚类中心

        计算剩余样本点到k个聚类中心的距离,指向最近的聚类中心

         划分聚类

         重新计算聚类中心

        递归计算,直到准则函数收敛或不产生新的聚类

四、算法流程图

五、关键源码展示

1、导入数据

2、划分聚类

3、输出聚类情况,绘制散点图

六、扩展实验

         DBSCAN与k-Means的对比实验

七、完整代码与数据集

1、完整代码

import math
import random
import matplotlib.pyplot as plt


# 读取数据
def loadData():
    try:
        with open("k-Means.txt", "r") as f:
            flines = f.readlines()
            dataSet = []
            for item in flines[0:]:
                dataSet.append(item.split())
            # 获取数据维度
            dimen = len(dataSet[0])
            return dimen, dataSet
    except Exception as e:
        print(e)


# 欧氏距离
def distance(A, B):
    dist = 0
    for i in range(len(A)):
        d = float(A[i]) - float(B[i])
        dist += d ** 2
    return dist ** 0.5


# 把每一个样本点划分到距离它最近的聚类中心所在的类
def Partition_Clustering(dataSet, center):
    cluster = []
    for i in range(len(center)):
        cluster.append([])
    for item in dataSet:
        clusterID = 0
        minDist = distance(item, center[0])
        for i in range(len(center)):
            dist = distance(item, center[i])
            if dist < minDist:
                minDist = dist
                clusterID = i
        cluster[clusterID].append(item)
    return cluster


# 计算聚类中心
def getCenter(cluster, dimen):
    center = []
    for items in cluster:
        Center = []
        for i in range(dimen):
            Center.append(0.0)
        for item in items:
            for i in range(dimen):
                Center[i] += float(item[i])
        if len(items) != 0:
            for i in range(dimen):
                Center[i] /= len(items)
        center.append(Center)
    return center


# 准则函数:误差平方和
def getE(center, cluster):
    E = 0
    for index, Center in enumerate(center):
        for item in cluster[index]:
            E += distance(item, Center) ** 2
    return E


def k_Means(dataSet, center, dimen):
    eps = 0.000001  # 精度要求
    e = random.random() * 1000000  # 初始化准则函数的值
    cnt = 1
    while True:
        cluster = Partition_Clustering(dataSet, center)
        center = getCenter(cluster, dimen)
        E = getE(center, cluster)
        print('第{}次迭代...'.format(cnt))
        show(center, cluster)
        '''如果收敛,就结束,否则继续迭代'''
        if math.fabs(E - e) < eps:
            print('迭代结束')
            return center, cluster
        else:
            print('继续迭代...')
            e = E
        cnt += 1


def show(center, cluster):
    # print(cluster)
    i = 1
    for index, Center in enumerate(center):
        print('cluster[{}]:{}->{}'.format(i, Center, cluster[index]))
        i += 1


def drawDataset(data):
    x = []
    y = []
    for xx, yy in data:
        x.append(float(xx))
        y.append(float(yy))
    plt.scatter(x, y)
    plt.show()


def draw(clusters):
    # colValue = ['red', 'blue', 'gray', 'black', 'purple', 'deepskyblue', 'darkblue']
    shape = ['.', 's', 'x', 'H', 'v', '^', '<', '>', '+', 'x', 'D']
    num_cluster = len(clusters)
    for i in range(num_cluster):
        x = []
        y = []
        for j in range(len(clusters[i])):  # 第i个簇的里面的元素
            x.append(float(clusters[i][j][0]))
            y.append(float(clusters[i][j][1]))
        plt.scatter(x, y, color='red', label=i, marker=shape[i])
    # plt.legend()
    plt.show()


def main():
    k = 3
    dimen, dataSet = loadData()
    drawDataset(dataSet)

    # 随机选择k个样本点作为初始点
    for i in range(0, 3):
        print('k-Means[{}]'.format(i + 1))
        center = []
        n = []
        cnt = 0
        while cnt < k:
            num = random.randint(0, len(dataSet) - 1)
            if num not in n:
                n.append(num)
                center.append(dataSet[num][:])
                cnt += 1
        for j in range(0, len(center)):
            print('Initial Point{}={}'.format(j + 1, center[j]))

        center, cluster = k_Means(dataSet, center, dimen)
        print('聚类结果如下')
        show(center, cluster)
        print()
        draw(cluster)


if __name__ == "__main__":
    main()

2、数据集 

1 2
2 1
2 4
4 3
5 8
6 7
6 9
7 9
9 5
1 12
3 12
5 12
3 3

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有为肥宅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值