【2】机器学习之兄弟连:K近邻和K-means

16 篇文章 1 订阅

利用Java实现的K-means聚类:k-means cluster

关键词:从K近邻到最近邻,监督学习,数据带lable,效率优化(从线性搜索到kd树搜索),缺点是需要存储所有数据,空间复杂度大。可以利用kd数来优化k-means算法。

学习了kNN和K-means算法后,仔细分析比较了他们之间的异同以及应用场景总结成此文供读者参阅。

首先,kNN是分类算法,其主要任务是将实例数据划分到合适的分类中,属于监督学习,什么叫监督学习?就是这类算法必须知道需要预测什么(即目标变量的分类信息),线性回归、朴素贝叶斯、支持向量机、决策树等常用算法均属于监督学习的范畴。K-means是聚类算法,将一个数据集合中的类似对象分成多个类即可,属于无监督学习。什么是无监督的学习?就是训练结果是未知的,也许能发现一些数据之间的规律与联系。

在说这两类算法之前我先明确一个距离的概念,如何评判两个点之间的距离与相似性?介绍两种最简单也是最广泛的方法--欧几里得距离和皮尔逊系数。两点的欧几里得距离就是两点的实际距离这两点的欧氏距离越小说明两点越相关,比较简单,不再赘述。皮尔逊相关系数是根据这个式子来计算两个向量之间的相关性的,它的好处是在数据不是很规范的时候(个别数据和平均数据相差很大的时候)结果往往趋向更好的结果,它是一种宏观上的相似。还有其他的距离与相似性的衡量算法可以参考博文:

http://www.cnblogs.com/ronny/p/4080442.html?utm_source=tuicool&utm_medium=referral

接下来我们来说kNN算法,kNN又叫k-近邻算法,顾名思义就是找出k个距离最近的数据。给定一个分类集合,我们将目标变量的和这个分类集合中的每个元素求距离(距离用上面讨论的任意一种距离都可以,为了计算方便后面我们用欧氏距离来计算),然后将距离进行排序得到最小的那个元素分类就是我们的目标变量分类了。kNN算法代码如下:

def classify0(inX,dataSet,labels,k):
    dataSetSize=dataSet.shape[0]
    diffMat=tile(inX,(dataSetSize,1))-dataSet
    sqDiffMat=diffMat**2
    #这里用numpy里面的矩阵计算提高了运算效率
    sqDistances=sqDiffMat.sum(axis=1)
    distances=sqDistances**0.5 
    sortedDistIndicies=distances.argsort()
    classCount={}
    for i in range(k):
        voteIlabel=labels[sortedDistIndicies[i]]
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
    sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

但是要注意的一点是,为了避免数据本身大小影响欧氏距离的大小,所以用欧氏距离必须先对数据进行归一化处理

def autoNorm(dataSet):
    minVals=dataSet.min(0)
    maxVals=dataSet.max(0)
    ranges=maxVals-minVals
    normDataSet=zeros(shape(dataSet))
    m=dataSet.shape[0]
    normDataSet=dataSet-tile(minVals,(m,1))
    normDataSet=normDataSet/tile(ranges,(m,1))
    return normDataSet

kNN是分类算法中最简单有效的方法,而且效果也是很好的(我测试了几个分类数据集,错误率不超过2%)但是kNN必须保存全部数据集,如果训练数据集很大,必须大量占用存储空间,而且必须对每个数据计算次距离,非常耗时.

再来说K-means聚类算法,K-means又叫-k均值聚类算法,算法思想就是首先会随机确定k个中心点作为聚类中心,然后把各个数据点分配给最邻近的中心点,分配完成后将中心点移动到所表示的聚类的平均中心位置处,然后重复迭代上述步骤直到分配过程不再产生变化位置。

K-means算法代码如下:(这里用的皮尔逊相关系数作距离衡量)

def kcluster(rows,distance=pearson,k=4):
ranges=[(min([row[i] for row in rows]),max([row[i] for row in rows])) for i in range(len(rows[0]))]
clusters=[[random.random()*(ranges[i][1]-ranges[i][0])+ranges[i][0] for i in range(len(rows[0]))] for j in range(k)] 
lastmatches=None
for t in range(100):
  print 'Iteration %d' %t
  bestmatches=[[] for i in range(k)]
  for j in range(len(rows)):
    row=rows[j]
    bestmatch=0
    for i in range(k):
      d=distance(clusters[i],row)
      if d<distance(clusters[bestmatch],row):
        bestmatch=i
    bestmatches[bestmatch].append(j)
  if bestmatches==lastmatches:break
  lastmatches=bestmatches
  for i in range(k):
    avgs=[0.0]*len(rows[0])
    if len(bestmatches[i])>0:
      for rowid in bestmatches[i]:
        for m in range(len(rows[rowid])):
          avgs[m]+=rows[rowid][m]
      for j in range(len(avgs)):
        avgs[j]/=len(bestmatches[i])
      clusters[i]=avgs
return bestmatches

最后总结一下这两种算法的异同:

  1. kNN是监督的分类算法,K-means是无监督的聚类方法。

  2. 给kNN的数据是带label的,给K-means的数据是不带label的、杂乱无章的

  3. 相似点:均包含一个给定一个点找寻离它最近的点的过程,均会用距离相似度来衡量。即都用到了NN,一般会用k-d树来实现。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值