机器学习笔记-K-means算法

写个python小程序复习一遍K-means算法,算法本身思想很简单,下面这篇文章介绍的很详细。http://home.deib.polimi.it/matteucc/Clustering/tutorial_html/kmeans.html

一、算法主函数

给定一个n维的向量集合points,将其划分为k个类别,采用闵氏距离作为两点之间距离的判定方法,算法参数就有三个:

1、points:向量集合

2、kcentroids:初始k个类别的质心位置的集合

3、p:闵氏距离的计算参数,1就是manhattan距离,2就是欧式距离

返回值是分好类的二维数组,行数为k,表示k个类别,每一行内的元素是int类型,表示向量数据在points中的下标,从0开始

主算法代码如下:

def alg_kmeans(points, kcentroids, p):
    assert(len(points) > 1);
    assert(len(kcentroids) > 1);
    assert(len(points[0]) == len(kcentroids[0]));

    k = len(kcentroids);
    # centroids for clusters, each centroid is a vector
    centroids = kcentroids;
    # clusters, set of point's index
    c1 = [[] for row in range(k)];
    c2 = [[] for row in range(k)];

    change = True;
    while change:
        change = False;
        # cluster once
        c2 = PointstoCluster(points, centroids, p);
        # if cluster change
        change = (cmp(c1,c2) != 0);
        # if not change, do again
        if change:
            c1 = c2;
            # recalculate cluster centroids
            centroids = RecalculateCentroids(points, centroids, c2);
    return c2;

主循环中每一轮计算,都会根据k个质心计算出分类的数据集合,将其保存在主算法中定义的二维数组c2中,c1为上一轮计算结果,c1与c2相同则表示算法结束。

二、计算函数

每一轮计算的函数参数与主函数相同,这是第二个参数质心集合是每一轮的计算结果,代码如下:

def PointstoCluster(points, kcentroids, p):
    assert(len(points) > 1);
    assert(len(kcentroids) > 1);
    assert(len(points[0]) == len(kcentroids[0]));

    k = len(kcentroids);
    clusters = [[] for i in range(k)];
    
    for i in range(len(points)):
        # cal distance to each centroid
        mindis = sys.float_info.max;
        point = points[i];
        clusteridx = -1;
        for j in range(0, k):
            dis = dis_minkowski(point, kcentroids[j], p);
            if dis < mindis:
                clusteridx = j;
                mindis = dis;
        clusters[clusteridx].append(i);

    return clusters;
函数遍历所有向量数据,每一个向量均计算与各个质心之间的距离,取最近距离质心的类别作为其归属分类。

三、质心计算函数
每一轮计算过后,都要重新计算每个分类的质心,函数需要参数参数:

1、points:同上

2、k:类别数目

3、clusters:PointstoCluster的返回值

代码如下:

def RecalculateCentroids(points, k, clusters):
    assert(len(points) > 1);
    assert(k > 1);

    dimention = len(points[0]);
    centroids = [[0 for d in range(dimention)] for row in range(k)];
    for i in range(k):
        if len(clusters[i]) == 0:
            continue;
        for d in range(0, dimention):
            centroids[i][d] = 0;
            for pidx in clusters[i]:
                centroids[i][d] += points[pidx][d];
            centroids[i][d] /= len(clusters[i]);
    return centroids;

算法较为简单,对于某一个类别内的所有数据,取其内所有向量,对每个维度取平均值。

四、效果

为验证效果,另外写了一个壳程序,维度取2(平面),p取2(欧式距离),随机生成1000个点,分为5类,结果图示如下。


代码的github地址:https://github.com/wsxwang/ML-practise.git


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值