机器学习笔记——K-Means

K-Means
K-Means算法流程:
Input:k值,data[n];
①随机选择k个对象作为初始中心点,例如c[0]=data[0],…c[k-1]=data[k-1];;
②对于data[0]….data[n], 分别与c[0]…c[k-1]比较,假定与c[i]差值最少,就标记为i;
③对于所有标记为i点,重新计算c[i]={ 所有标记为i的data[j]之和}/标记为i的个数;
④ 重复(2)(3),直到所有c[i]值的变化小于给定阈值,或达到指定的迭代次数。

例:
给定4个数据对象,每个object对应有2个features,将其分为2类:
这里写图片描述
随机选取k(此时k=2)个点作为初始的中心点。假设选A(1,1)、B(2,1)为中心点,则可得距离矩阵D0为:
这里写图片描述

——矩阵中的值d11、d12、d13、d14依次对应A与A、B、C、D的距离,d21、d22、d23、d24依次对应B与A、B、C、D的距离;
然后分别判断A、B、C、D距离A、B距离的大小;距离小置为1,距离大置为0。
得到矩阵C0:
这里写图片描述
第一类中只有A,故仍取A为中心点C1,第二类中此时有B、C、D三个,故求三者的均值作为新的中心点C2;
重复上述计算得到矩阵D1、C1:
这里写图片描述

这里写图片描述
再利用C1计算的到D2、C2;
此时可看到 C1=C2,计算结束;
即得到如下结果:

这里写图片描述

Python中实现:

#  # K Means算法
#!/usr/bin/python
# -*- coding: utf-8 -*-
import numpy as np

# #传入数据集X,
def kmeans(X, k, maxIt):
    # #获取X行数及列数
    numPoints, numDim = X.shape
    # #在X后增加1列,初始值为0
    dataSet = np.zeros((numPoints, numDim+1))
    # #除最后1列外其余列与X相同
    dataSet[:,:-1] = X
    # #随机选出k行作为初始中心点的行数,列坐标全选
    centroids = dataSet[np.random.randint(numPoints,size = k), :]
    # #初始化中心点,使中心点标签依次为1、2、3....k
    centroids[:, -1] = range(1, k + 1)
    iterations = 0
    # #旧的中心点
    oldCentroids = None
    while not shouldStop(oldCentroids, centroids, iterations, maxIt):
        print "iteration:\n", iterations
        print "dataSet:\n", dataSet
        print "centroids:\n", centroids

        oldCentroids = np.copy(centroids)
        iterations += 1

        updateLabels(dataSet, centroids)
        centroids = getCentroids(dataSet, k)

    return dataSet

# # iterations循环的次数 ; maxIt允许循环的上限
# # 当新的中心点的值与旧的中心点的值相等时,认为收敛
def shouldStop(oldCentroid, centroids, iterations, maxIt):
    if iterations > maxIt:
        return True
    return np.array_equal(oldCentroid, centroids)

# #传入一个矩阵和一个中心点,计算每一行与中心点的距离,
def updateLabels(dataSet, centroids):
    numPoints, numDim = dataSet.shape
    for i in range(0, numPoints):
        # #传入数据集中的一行,对每一列的最后一行进行归类
        dataSet[i, -1] = getLabelFromClossestCentroid(dataSet[i, :-1], centroids)


# #对比当前行与中心点的距离,返回距离最近的中心点的label
def getLabelFromClossestCentroid(dataSetRow, centroids):
    label = centroids[0,-1]
    minDist = np.linalg.norm(dataSetRow - centroids[0, :-1])
    for i in range(1,centroids.shape[0]):
        dist = np.linalg.norm(dataSetRow - centroids[i, :-1])
        # #与最小距离对比,并记录对应的label
        if dist < minDist:
            minDist = dist
            label = centroids[i, -1]
    print "minDist:", minDist
    return label

# # 输入标签和k值,计算出新的中心点
def getCentroids(dataSet, k):
    # 初始化结果,行数为k
    result = np.zeros((k, dataSet.shape[1]))
    for i in range(1, k+1):
        # #获得一个类别里的所有点
        oneCluster = dataSet[dataSet[:, -1] == i, :-1]
        # #axis=0 对行求平均值;赋值到从开始到导数第二列中
        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))

result = kmeans(testX, 2, 10)
print "final result:\n", result

打印出结果为:

iteration:
0
dataSet:
[[ 1.  1.  0.]
 [ 2.  1.  0.]
 [ 4.  3.  0.]
 [ 5.  4.  0.]]
centroids:
[[ 5.  4.  1.]
 [ 1.  1.  2.]]
minDist: 0.0
minDist: 1.0
minDist: 1.41421356237
minDist: 0.0
iteration:
1
dataSet:
[[ 1.  1.  2.]
 [ 2.  1.  2.]
 [ 4.  3.  1.]
 [ 5.  4.  1.]]
centroids:
[[ 4.5  3.5  1. ]
 [ 1.5  1.   2. ]]
minDist: 0.5
minDist: 0.5
minDist: 0.707106781187
minDist: 0.707106781187

final result:
[[ 1.  1.  2.]
 [ 2.  1.  2.]
 [ 4.  3.  1.]
 [ 5.  4.  1.]]

最终结果为CD与AB分别被分为1、2类。

直接调用kmeans()函数:

from pylab import *
from scipy.cluster.vq import *

l1 = [1., 1.]
l2 = [2., 1.]
l3 = [4., 3.]
l4 = [5., 4.]
data = vstack((l1, l2, l3, l4))
centers, _ = kmeans(data, 2)
result, _ = vq(data, centers)
print result

打印结果:

[1 1 0 0]

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值