【machine learning】KMeans算法(Python版)

一、概述

刚开始想要学习LDA主题模型的建模方法,学习的过程中发现应用到了EM算法,所以还是打算由浅及深地进行,发现EM算法虽然简单只有E步和M步的不断迭代,但其应用却很广泛,比较有名的有GMM算法和本博文要将的KMeans算法。作为数据挖掘十大经典算法之一,EM算法定义为:在统计中被用于寻找,依赖于不可观察的隐性变量的概率模型中,参数的最大似然估计。这在之后的博客中将有所体现。

建议学习顺序如下:EM->KMeans->GMM->EM->LDA

废话少说,进入正题。聚类是一种无监督的学习,它将相似的对象归到同一个簇中。它有点像全自动分类。聚类方法几乎可以应用于所有对象,簇内的对象越相似,聚类的效果越好。之所以称之为K-均值是因为它可以发现K个不同的簇,且每个簇的中心采用簇中所含值的均值计算而成。下面会逐步介绍该算法的更多细节。本博文代码参考书本Machine Learning in Action(《机器学习实战》)

聚类分析试图将相似对象归人同一簇,将不相似对象归到不同簇。相似这一概念取决于所选择的相似度计算方法。到底使用哪种相似度计算方法取决于具体应用。

二、KMeans算法理念

  • K-均值算法的工作流程是这样的
    首先,随机确定K个初始点作为质心。然后将数据集中的每个点分配到一个簇中,具体来讲,为每个点找距其最近的质心,并将其分配给该质心所对应的簇。这一步完成之后,每个簇的质心更新为该簇所有点的平均值。迭代的停止条件由相邻两次迭代结果中与质心的距离之差小于某个精度值。

  • K-均值聚类的一般流程
    (1)收集数据:使用任意方法。
    ⑵准备数据:需要数值型数据来计算距离,也可以将标称型数据映射为二值型数据再用于距离计算。
    (3)分析数据:使用任意方法。
    (4)训练算法:不适用于无监督学习,即无监督学习没有训练过程。
    (5)测试算法:应用聚类算法、观察结果。可以使用量化的误差指标如误差平方和(后面会介绍)来评价算法的结果。
    (6)使用算法:可以用于所希望的任何应用。通常情况下,簇质心可以代表整个簇的数据来做出决策。

  • 与EM算法的对照关系
    在EM算法中有一个流程是这样的:固定θ,调整Q(z)使下界J(z,Q)上升至与L(θ)在此点θ处相等,然后固定Q(z),调整θ使下界J(z,Q)达到最大值(θt到θt+1),然后再固定θ,调整Q(z)……直到收敛到似然函数L(θ)的最大值,最终获得θ。
    每一类质心的位置对应EM算法中的初始化分布参数θ
    数据点属于的类对应EM算法中的隐藏变量Q(Z)
    每个簇的质心更新为该簇所有点的平均值对应EM算法中使L(θ)的值最大的方法,即簇中数据总体属于该簇的可能性最大的θ取值
    现在只能通俗这么说,具体的L(θ)计算需要在二维展开,求导,之后判断θ取值为平均值能是L(θ)导数为零。简单的分析如下:
    这里写图片描述
    这里参考了博文
    相比之下,GMM更有概率分布的影子,所以与EM对照关系更清晰。

  • 伪代码

创建k个点作为起始质心(经常是随机选择)
当任意一个点的簇分配结果发生改变时
    对数据集中的每个数据点
       对每个质心
          计算质心与数据点之间的距离
       将数据点分配到距其最近的簇
    对每一个簇,计算簇中所有点的均值并将均值作为质心

三、常规KMeans程序分析

程序所需按照包:numpy,matplotlib(其实依赖pylab包等)

KMeans.py

#! /usr/bin/env python
#coding=utf-8
from numpy import *
import pylab

def loadDataSet(fileName):      #general function to parse tab -delimited floats
    dataMat = []                #assume last column is target value
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = map(float,curLine) #map all elements to float()
        dataMat.append(fltLine)
    return dataMat

# 计算欧氏距离
def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA - vecB, 2))) #la.norm(vecA-vecB)

# 根据dataSet产生k行数据,列数与dataSet一样,且每一列数据介于dataSet对应列最大值和最大值之间
def randCent(dataSet, k):
    n = shape(dataSet)[1]
    centroids = mat(zeros((k,n)))#create centroid mat
    for j in range(n):#create random cluster centers, within bounds of each dimension
        minJ = min(dataSet[:,j]) 
        rangeJ = float(
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值