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使用dis模块把Python反编译为字节码的用法详解
Jun 14 Python
Python+PIL实现支付宝AR红包
Feb 09 Python
Python实现读取SQLServer数据并插入到MongoDB数据库的方法示例
Jun 09 Python
python爱心表白 每天都是浪漫七夕!
Aug 18 Python
pycharm重置设置,恢复默认设置的方法
Oct 22 Python
Python线程池模块ThreadPoolExecutor用法分析
Dec 28 Python
Django实现单用户登录的方法示例
Mar 28 Python
将Pytorch模型从CPU转换成GPU的实现方法
Aug 19 Python
如何用Anaconda搭建虚拟环境并创建Django项目
Aug 02 Python
vscode配置anaconda3的方法步骤
Aug 08 Python
python Selenium 库的使用技巧
Oct 16 Python
python Zmail模块简介与使用示例
Dec 19 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获取淘宝分类id示例
2014/01/16 PHP
smarty模板引擎从配置文件中获取数据的方法
2015/01/22 PHP
PHP程序中的文件锁、互斥锁、读写锁使用技巧解析
2016/03/21 PHP
PHP实现一个多功能购物网站的案例
2017/09/13 PHP
PHP实现正则匹配所有括号中的内容
2018/06/22 PHP
php实现获取近几日、月时间示例
2019/07/06 PHP
js读取本地excel文档数据的代码
2010/11/11 Javascript
Javascript之this关键字深入解析
2013/11/12 Javascript
jQuery Ajax中的事件详细介绍
2015/04/16 Javascript
完美兼容多浏览器的js判断图片路径代码汇总
2015/04/17 Javascript
JS实现滑动菜单效果代码(包括Tab,选项卡,横向等效果)
2015/09/24 Javascript
JavaScript的Backbone.js框架环境搭建及Hellow world示例
2016/05/07 Javascript
JavaScript使用键盘输入控制实现数字验证功能
2016/08/19 Javascript
bootstrap中模态框、模态框的属性实例详解
2017/02/17 Javascript
js中DOM三级列表(代码分享)
2017/03/20 Javascript
ES6字符串模板,剩余参数,默认参数功能与用法示例
2017/04/06 Javascript
js实现简易聊天对话框
2017/08/17 Javascript
Vue的土著指令和自定义指令实例详解
2018/02/04 Javascript
JavaScript数组及常见操作方法小结
2019/11/13 Javascript
详解Vue.js3.0 组件是如何渲染为DOM的
2020/11/10 Javascript
Vue 列表页带参数进详情页的操作(router-link)
2020/11/13 Javascript
python嵌套函数使用外部函数变量的方法(Python2和Python3)
2016/01/31 Python
Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例
2017/12/12 Python
朴素贝叶斯分类算法原理与Python实现与使用方法案例
2018/06/26 Python
Linux下python制作名片示例
2018/07/20 Python
Python使用MyQR制作专属动态彩色二维码功能
2019/06/04 Python
通过selenium抓取某东的TT购买记录并分析趋势过程解析
2019/08/15 Python
Mac PyCharm中的.gitignore 安装设置教程
2020/04/16 Python
Python使用pickle进行序列化和反序列化的示例代码
2020/09/22 Python
HTML5在线预览PDF的示例代码
2017/09/14 HTML / CSS
嘻哈珠宝品牌:KRKC&CO
2020/10/19 全球购物
元旦获奖感言
2014/03/08 职场文书
三分钟英语演讲稿
2014/04/24 职场文书
2014年十八届四中全会思想汇报范文
2014/10/17 职场文书
2014年为民办实事工作总结
2014/12/20 职场文书
证婚人婚礼致辞
2015/07/28 职场文书