python实现kMeans算法


Posted in Python onDecember 21, 2017

聚类是一种无监督的学习,将相似的对象放到同一簇中,有点像是全自动分类,簇内的对象越相似,簇间的对象差别越大,则聚类效果越好。

1、k均值聚类算法

k均值聚类将数据分为k个簇,每个簇通过其质心,即簇中所有点的中心来描述。首先随机确定k个初始点作为质心,然后将数据集分配到距离最近的簇中。然后将每个簇的质心更新为所有数据集的平均值。然后再进行第二次划分数据集,直到聚类结果不再变化为止。

伪代码为

随机创建k个簇质心
当任意一个点的簇分配发生改变时:
    对数据集中的每个数据点:
        对每个质心:
            计算数据集到质心的距离
        将数据集分配到最近距离质心对应的簇
    对每一个簇,计算簇中所有点的均值并将均值作为质心

python实现

import numpy as np
import matplotlib.pyplot as plt

def loadDataSet(fileName): 
 dataMat = [] 
 with open(fileName) as f:
  for line in f.readlines():
   line = line.strip().split('\t')
   dataMat.append(line)
 dataMat = np.array(dataMat).astype(np.float32)
 return dataMat


def distEclud(vecA,vecB):
 return np.sqrt(np.sum(np.power((vecA-vecB),2)))
def randCent(dataSet,k):
 m = np.shape(dataSet)[1]
 center = np.mat(np.ones((k,m)))
 for i in range(m):
  centmin = min(dataSet[:,i])
  centmax = max(dataSet[:,i])
  center[:,i] = centmin + (centmax - centmin) * np.random.rand(k,1)
 return center
def kMeans(dataSet,k,distMeans = distEclud,createCent = randCent):
 m = np.shape(dataSet)[0]
 clusterAssment = np.mat(np.zeros((m,2)))
 centroids = createCent(dataSet,k)
 clusterChanged = True
 while clusterChanged:
  clusterChanged = False
  for i in range(m):
   minDist = np.inf
   minIndex = -1
   for j in range(k):
    distJI = distMeans(dataSet[i,:],centroids[j,:])
    if distJI < minDist:
     minDist = distJI
     minIndex = j
   if clusterAssment[i,0] != minIndex:
    clusterChanged = True
   clusterAssment[i,:] = minIndex,minDist**2
  for cent in range(k):
   ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A == cent)[0]]
   centroids[cent,:] = np.mean(ptsInClust,axis = 0)
 return centroids,clusterAssment



data = loadDataSet('testSet.txt')
muCentroids, clusterAssing = kMeans(data,4)
fig = plt.figure(0)
ax = fig.add_subplot(111)
ax.scatter(data[:,0],data[:,1],c = clusterAssing[:,0].A)
plt.show()

print(clusterAssing)

2、二分k均值算法

K均值算法可能会收敛到局部最小值,而非全局最小。一种用于度量聚类效果的指标为误差平方和(SSE)。因为取了平方,更加重视原理中心的点。为了克服k均值算法可能会收敛到局部最小值的问题,有人提出来二分k均值算法。
首先将所有点作为一个簇,然后将该簇一分为二,然后选择所有簇中对其划分能够最大程度减低SSE的值的簇,直到满足指定簇数为止。

伪代码

将所有点看成一个簇
计算SSE
while 当簇数目小于k时:
    for 每一个簇:
        计算总误差
        在给定的簇上进行k均值聚类(k=2)
        计算将该簇一分为二的总误差
    选择使得误差最小的那个簇进行划分操作

python实现

import numpy as np
import matplotlib.pyplot as plt

def loadDataSet(fileName): 
 dataMat = [] 
 with open(fileName) as f:
  for line in f.readlines():
   line = line.strip().split('\t')
   dataMat.append(line)
 dataMat = np.array(dataMat).astype(np.float32)
 return dataMat


def distEclud(vecA,vecB):
 return np.sqrt(np.sum(np.power((vecA-vecB),2)))
def randCent(dataSet,k):
 m = np.shape(dataSet)[1]
 center = np.mat(np.ones((k,m)))
 for i in range(m):
  centmin = min(dataSet[:,i])
  centmax = max(dataSet[:,i])
  center[:,i] = centmin + (centmax - centmin) * np.random.rand(k,1)
 return center
def kMeans(dataSet,k,distMeans = distEclud,createCent = randCent):
 m = np.shape(dataSet)[0]
 clusterAssment = np.mat(np.zeros((m,2)))
 centroids = createCent(dataSet,k)
 clusterChanged = True
 while clusterChanged:
  clusterChanged = False
  for i in range(m):
   minDist = np.inf
   minIndex = -1
   for j in range(k):
    distJI = distMeans(dataSet[i,:],centroids[j,:])
    if distJI < minDist:
     minDist = distJI
     minIndex = j
   if clusterAssment[i,0] != minIndex:
    clusterChanged = True
   clusterAssment[i,:] = minIndex,minDist**2
  for cent in range(k):
   ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A == cent)[0]]
   centroids[cent,:] = np.mean(ptsInClust,axis = 0)
 return centroids,clusterAssment

def biKmeans(dataSet,k,distMeans = distEclud):
 m = np.shape(dataSet)[0]
 clusterAssment = np.mat(np.zeros((m,2)))
 centroid0 = np.mean(dataSet,axis=0).tolist()
 centList = [centroid0]
 for j in range(m):
  clusterAssment[j,1] = distMeans(dataSet[j,:],np.mat(centroid0))**2
 while (len(centList)<k):
  lowestSSE = np.inf
  for i in range(len(centList)):
   ptsInCurrCluster = dataSet[np.nonzero(clusterAssment[:,0].A == i)[0],:]
   centroidMat,splitClustAss = kMeans(ptsInCurrCluster,2,distMeans)
   sseSplit = np.sum(splitClustAss[:,1])
   sseNotSplit = np.sum(clusterAssment[np.nonzero(clusterAssment[:,0].A != i)[0],1])
   if (sseSplit + sseNotSplit) < lowestSSE:
    bestCentToSplit = i
    bestNewCents = centroidMat.copy()
    bestClustAss = splitClustAss.copy()
    lowestSSE = sseSplit + sseNotSplit
  print('the best cent to split is ',bestCentToSplit)
#  print('the len of the bestClust')
  bestClustAss[np.nonzero(bestClustAss[:,0].A == 1)[0],0] = len(centList)
  bestClustAss[np.nonzero(bestClustAss[:,0].A == 0)[0],0] = bestCentToSplit

  clusterAssment[np.nonzero(clusterAssment[:,0].A == bestCentToSplit)[0],:] = bestClustAss.copy()
  centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0]
  centList.append(bestNewCents[1,:].tolist()[0])
 return np.mat(centList),clusterAssment

data = loadDataSet('testSet2.txt')
muCentroids, clusterAssing = biKmeans(data,3)
fig = plt.figure(0)
ax = fig.add_subplot(111)
ax.scatter(data[:,0],data[:,1],c = clusterAssing[:,0].A,cmap=plt.cm.Paired)
ax.scatter(muCentroids[:,0],muCentroids[:,1])
plt.show()

print(clusterAssing)
print(muCentroids)

代码及数据集下载:K-means

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现电子词典
Apr 23 Python
win7 下搭建sublime的python开发环境的配置方法
Jun 18 Python
Python过滤函数filter()使用自定义函数过滤序列实例
Aug 26 Python
Python map和reduce函数用法示例
Feb 26 Python
python搭建微信公众平台
Feb 09 Python
关于Python中异常(Exception)的汇总
Jan 18 Python
Python简直是万能的,这5大主要用途你一定要知道!(推荐)
Apr 03 Python
Django中ORM外键和表的关系详解
May 20 Python
python3.x+pyqt5实现主窗口状态栏里(嵌入)显示进度条功能
Jul 04 Python
Python3如何判断三角形的类型
Apr 12 Python
使用python+poco+夜神模拟器进行自动化测试实例
Apr 23 Python
Python matplotlib可视化之绘制韦恩图
Feb 24 Python
利用Tkinter(python3.6)实现一个简单计算器
Dec 21 #Python
python编写朴素贝叶斯用于文本分类
Dec 21 #Python
python并发2之使用asyncio处理并发
Dec 21 #Python
利用Python暴力破解zip文件口令的方法详解
Dec 21 #Python
Python人脸识别初探
Dec 21 #Python
python中判断文件编码的chardet(实例讲解)
Dec 21 #Python
python 设置文件编码格式的实现方法
Dec 21 #Python
You might like
老生常谈PHP面向对象之标识映射
2017/06/21 PHP
php 替换文章中的图片路径,下载图片到本地服务器的方法
2018/02/06 PHP
laravel admin实现分类树/模型树的示例代码
2020/06/10 PHP
JavaScript 的继承
2011/10/01 Javascript
javascript学习笔记(十六) 系统对话框(alert、confirm、prompt)
2012/06/20 Javascript
jQuery动画效果-slideUp slideDown上下滑动示例代码
2013/08/28 Javascript
jQuery中的val()示例应用
2014/02/26 Javascript
jquery实现显示已选用户
2014/07/21 Javascript
node.js超时timeout详解
2014/11/26 Javascript
node.js中的fs.linkSync方法使用说明
2014/12/15 Javascript
使用javascript实现监控视频播放并打印日志
2015/01/05 Javascript
js的toUpperCase方法用法实例
2015/01/27 Javascript
JavaScript中函数(Function)的apply与call理解
2015/07/08 Javascript
详解jQuery中的元素的属性和相关操作
2015/08/14 Javascript
解决js图片加载时出现404的问题
2020/11/30 Javascript
jQuery多条件筛选如何实现
2015/11/04 Javascript
整理Javascript函数学习笔记
2015/12/01 Javascript
js注册时输入合法性验证方法
2017/10/21 Javascript
详解如何解决Vue和vue-template-compiler版本之间的问题
2018/09/17 Javascript
layUI的验证码功能及校验实例
2019/10/25 Javascript
Angular8引入百度Echarts进行图表分析的实现代码
2019/11/27 Javascript
Python兔子毒药问题实例分析
2015/03/05 Python
Python编程中使用Pillow来处理图像的基础教程
2015/11/20 Python
Python 处理数据的实例详解
2017/08/10 Python
Python基础学习之基本数据结构详解【数字、字符串、列表、元组、集合、字典】
2019/06/18 Python
python3.6使用SMTP协议发送邮件
2020/05/20 Python
pycharm实现print输出保存到txt文件
2020/06/01 Python
Python 实现3种回归模型(Linear Regression,Lasso,Ridge)的示例
2020/10/15 Python
python 基于PYMYSQL使用MYSQL数据库
2020/12/24 Python
探究 canvas 绘图中撤销(undo)功能的实现方式详解
2018/05/17 HTML / CSS
2015年幼儿园毕业感言
2014/02/12 职场文书
高一新生军训感言
2014/03/02 职场文书
品质主管岗位职责
2014/03/16 职场文书
施工安全责任书
2014/04/14 职场文书
村党支部对照检查材料思想汇报
2014/09/28 职场文书
国际残疾人日广播稿范文
2014/10/09 职场文书