简单聚类算法 K-means实现

K-means算法中K指分成多少类,为数据挖掘十大算法之一。

  • 基本原理:在非监督学习(Unsupervised Learning)中,没有标签用来分类,此时应如何分类?

K-means算法是一种解决方案,此实例较为简单,提前声明数据集要分类的数目,即K值。以空间中K个点为中心进行聚类,对最靠近他们的对象归类,逐次更新各聚类中心的值,直到最后的聚类结果。

  • 算法描述:
    1. 适当选择k个类的初始中心,记为 c 
    2. 在第k次迭代中,对任意一个样本,计算到c中各个中心点的距离,将该样本归到距离最短的中心x所在的类。即 data[i,-1]=x
    3. 利用均值等方法更新该类的中心值
    4. 对于所有的聚类中心,进行2、3迭代更新后,若c值保持不变,则迭代结束
  • 示例:分类四个药物,特征值简单,只有2个

ObjectFeature 1:Weight IndexFeature 2: pH
Medicine A11

Medicine B

21
Medicine C43
Medicine D54

 

#!/usr/bin/env python
#coding:utf-8
#Author:Fabian
import numpy as np
def Kmeans(X, k, maxIt):
    """
    kmeans聚类算法
    :param X: 数据集
    :param k: 分多少类
    :param maxIt: 最大迭代次数
    :return:
    """
    numPoints, numDim = X.shape
    print numPoints,numDim
    #加一列
    dataSet = np.zeros((numPoints, numDim + 1))
    dataSet[:, :-1] = X

    #Initialize centroids randomly
    centroids = dataSet[np.random.randint(numPoints, size=k),:]
    #centroids = dataSet[0:2, :]
    #Randomly assign labels to initial centroid
    centroids[:,-1] = range(1, k+1)

    #Initialize book keeping vars
    iterations = 0
    oldCentroids = None

    #Run the main k-means algorithm
    while not shouldStop(oldCentroids, centroids, iterations, maxIt):
        print "iteration: \n", iterations
        print "dataSet: \n", dataSet
        print "centroids: \n", centroids
        #Save old centroids for convergence test.
        oldCentroids = np.copy(centroids)
        iterations += 1

        #assign labels to each datapoint based on centroids
        updateLabels(dataSet, centroids)
        #assign centroids based on datapoint labels
        centroids = getCentroids(dataSet, k)
    return dataSet

def shouldStop(oldCentroids, centroids, iterations, maxIt):
    """
    判断是否停止更新,超过返回True,否则判断是否相等,相等返回True
    :param oldCentroids:上一次循环的中心点
    :param centroids: 本次的中心点
    :param iterations: 迭代次数
    :param maxIt: 最大迭代数
    :return: True or False
    """
    if iterations > maxIt:
        return True
    return np.array_equal(oldCentroids, centroids)

def updateLabels(dataSet, centroids):
    #For each element in the dataset, chose the closest centroid
    """
    数据集中每个数据与中心点比较 选择最近的聚类
    :param dataSet: 数据集
    :param centroids: 中心
    :return: No return
    """
    numPoints, numDim = dataSet.shape
    for i in range(0,numPoints):
        dataSet[i, -1] = getLabelFromClosestCentroid(dataSet[i, :-1], centroids)

def getLabelFromClosestCentroid(dataSetRow, centroids):
    #初始化label为中心点第一点的label
    label = centroids[0, -1]
    #初始化最小值为当前行到中心点第一点的距离值
    #np.linalg.norm计算两个向量的距离
    minDist = np.linalg.norm(dataSetRow - centroids[0, : -1])
    #对每个中心点开始循环
    for i in range(0, centroids.shape[0]):
        dist = np.linalg.norm(dataSetRow - centroids[i, : -1])
        if dist < minDist:
            minDist = dist
            label = centroids[i, -1]
    print "minDist:",minDist
    return label

def getCentroids(dataSet, k):
    """
    更新中心点
    :param dataSet: 数据集 + 标签
    :param k: 分类数
    :return: centroids
    """
    result = np.zeros((k, dataSet.shape[1]))
    for i in range(1, k+1):
        #找出最后一列类别都为i的行集
        oneCluster = dataSet[dataSet[:,-1] == i,:-1]
        #学习这种判定模式
        result[i-1, :-1] = np.mean(oneCluster, axis= 0)
        result[i-1, -1] = i
    return result

x1 = np.array([1,1])
x2 = np.array([2,1])
x3 = np.array([4,3])
x4 = np.array([5,4])
testX = np.vstack((x1, x2, x3, x4))
print testX
result = Kmeans(testX,2,10)
print "final result:"
print result

  • 优缺点:

通过以上代码,我们可以发现,必须要提前确定K值,而在实际操作中是不可能确定的。

但是,优点也较为明显:速度快,简单

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值