Python机器学习算法之k均值聚类(k-means)


Posted in Python onFebruary 23, 2018

一开始的目的是学习十大挖掘算法(机器学习算法),并用编码实现一遍,但越往后学习,越往后实现编码,越发现自己的编码水平低下,学习能力低。这一个k-means算法用Python实现竟用了三天时间,可见编码水平之低,而且在编码的过程中看了别人的编码,才发现自己对numpy认识和运用的不足,在自己的代码中有很多可以优化的地方,比如求均值的地方可以用mean直接对数组求均值,再比如去最小值的下标,我用的是argsort排序再取列表第一个,但是有argmin可以直接用啊。下面的代码中这些可以优化的并没有改,这么做的原因是希望做到抛砖引玉,欢迎大家丢玉,如果能给出优化方法就更好了

一.k-means算法

人以类聚,物以群分,k-means聚类算法就是体现。数学公式不要,直接用白话描述的步骤就是:

1.随机选取k个质心(k值取决于你想聚成几类)
2.计算样本到质心的距离,距离质心距离近的归为一类,分为k类
3.求出分类后的每类的新质心
4.判断新旧质心是否相同,如果相同就代表已经聚类成功,如果没有就循环2-3直到相同

用程序的语言描述就是:

1.输入样本
2.随机去k个质心
3.重复下面过程知道算法收敛:

计算样本到质心距离(欧几里得距离)
样本距离哪个质心近,就记为那一类
计算每个类别的新质心(平均值)

二.需求分析

数据来源:从国际统计局down的数据,数据为城乡居民家庭人均收入及恩格尔系数(点击这里下载)

Python机器学习算法之k均值聚类(k-means)

数据描述:

1.横轴:城镇居民家庭人均可支配收入和农村居民家庭人均纯收入,
2.纵轴:1996-2012年。
3.数据为年度数据

需求说明:我想把这数据做个聚类分析,看人民的收入大概经历几个阶段(感觉我好高大上啊)

需求分析:

1.由于样本数据有限,就两列,用k-means聚类有很大的准确性
2.用文本的形式导入数据,结果输出聚类后的质心,这样就能看出人民的收入经历了哪几个阶段

三.Python实现

引入numpy模块,借用其中的一些方法进行数据处理,上代码:

# -*- coding=utf-8 -*-

"""
authon:xuwf
created:2017-02-07
purpose:实现k-means算法
"""

import numpy as np
import random

'''装载数据'''
def load():
 data=np.loadtxt('data\k-means.csv',delimiter=',')
 return data

'''计算距离'''
def calcDis(data,clu,k):
 clalist=[] #存放计算距离后的list
 data=data.tolist() #转化为列表
 clu=clu.tolist()
 for i in range(len(data)):
  clalist.append([])
  for j in range(k):
   dist=round(((data[i][1]-clu[j][0])**2+(data[i][2]-clu[j][1])**2)*0.05,1)
   clalist[i].append(dist)
 clalist=np.array(clalist) #转化为数组
 return clalist

'''分组'''
def group(data,clalist,k):
 grouplist=[] #存放分组后的集群
 claList=clalist.tolist()
 data=data.tolist()
 for i in range(k):
  #确定要分组的个数,以空列表的形式,方便下面进行数据的插入
  grouplist.append([])
 for j in range(len(clalist)):
  sortNum=np.argsort(clalist[j])
  grouplist[sortNum[0]].append(data[j][1:])
 grouplist=np.array(grouplist)
 return grouplist

'''计算质心'''
def calcCen(data,grouplist,k):
 clunew=[]
 data=data.tolist()
 grouplist=grouplist.tolist()
 templist=[]
 #templist=np.array(templist)
 for i in range(k):
  #计算每个组的新质心
  sumx=0
  sumy=0
  for j in range(len(grouplist[i])):
   sumx+=grouplist[i][j][0]
   sumy+=grouplist[i][j][1]
  clunew.append([round(sumx/len(grouplist[i]),1),round(sumy/len(grouplist[i]),1)])
 clunew=np.array(clunew)
 #clunew=np.mean(grouplist,axis=1)
 return clunew

'''优化质心'''
def classify(data,clu,k):
 clalist=calcDis(data,clu,k) #计算样本到质心的距离
 grouplist=group(data,clalist,k) #分组
 for i in range(k):
  #替换空值
  if grouplist[i]==[]:
   grouplist[i]=[4838.9,1926.1]
 clunew=calcCen(data,grouplist,k)
 sse=clunew-clu
 #print "the clu is :%r\nthe group is :%r\nthe clunew is :%r\nthe sse is :%r" %(clu,grouplist,clunew,sse)
 return sse,clunew,data,k 

if __name__=='__main__':
 k=3 #给出要分类的个数的k值
 data=load() #装载数据
 clu=random.sample(data[:,1:].tolist(),k) #随机取质心
 clu=np.array(clu)
 sse,clunew,data,k=classify(data,clu,k)
 while np.any(sse!=0):
  sse,clunew,data,k=classify(data,clunew,k)
 clunew=np.sort(clunew,axis=0)
 print "the best cluster is %r" %clunew

四.测试

直接运行程序就可以,k值可以自己设置,会发现k=3的时候结果数据是最稳定的,这里我就不贴图了
需要注意的是上面的代码里面主函数里的数据结构都是array,但是在每个小函数里就有可能转化成了list,主要原因是需要进行array的一下方法进行计算,而转化为list的原因是需要向数组中插入数据,但是array做不到啊(至少我没找到怎么做)。于是这里就出现了一个问题,那就是数据结构混乱,到最后我调试了半天,干脆将主函数的数据结构都转化成array,在小函数中输入的array,输出的时候也转化成了array,这样就清晰多了

五.算法分析

单看这个算法还是较好理解的,但是算法的目的是聚类,那就要考虑到聚类的准确性,这里聚类的准确性取决于k值、初始质心和距离的计算方式。

  • k值就要看个人经验和多次试验了,算法结果在哪个k值的时候更稳定就证明这个分类更加具有可信度,其中算法结果的稳定也取决于初始质心的选择
  • 初始质心一般都是随机选取的,怎么更准确的选择初始质心呢?有种较难实现的方法是将样本中所有点组合起来都取一遍,然后计算算法收敛后的所有质心到样本的距离之和,哪个距离最小,哪个的聚类就最为成功,相对应的初始质心就选取的最为准确。但是这种方法有很大的计算量,如果样本很大,维度很多,那就是让电脑干到死的节奏
  • 距离的计算方式取决于样本的特征,有很多的选择,入欧式距离,夹角余弦距离,曼哈顿距离等,具体的数据特性用具体的距离计算方式

六.项目评测

1.项目总结数据源的数据很干净,不需要进行过多的数据清洗和数据降噪,数据预处理的工作成本接近为0。需求基本实现
2.还能做什么:可以用计算最小距离之和的方法求出最佳k值,这样就可以得到稳定的收入阶梯;可以引入画图模块,将数据结果进行数据可视化,显得更加直观;如果可能应该引入更多的维度或更多的数据,这样得到的聚类才更有说服力。

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

Python 相关文章推荐
python绘图库Matplotlib的安装
Jul 03 Python
Python标准库之多进程(multiprocessing包)介绍
Nov 25 Python
tf.truncated_normal与tf.random_normal的详细用法
Mar 05 Python
详谈Python中列表list,元祖tuple和numpy中的array区别
Apr 18 Python
Python实现聊天机器人的示例代码
Jul 09 Python
python字典嵌套字典的情况下找到某个key的value详解
Jul 10 Python
Win10下python 2.7与python 3.7双环境安装教程图解
Oct 12 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
Dec 04 Python
快速查找Python安装路径方法
Feb 06 Python
python 实现人和电脑猜拳的示例代码
Mar 02 Python
Java爬虫技术框架之Heritrix框架详解
Jul 22 Python
Anaconda使用IDLE的实现示例
Sep 23 Python
python3调用R的示例代码
Feb 23 #Python
python中kmeans聚类实现代码
Feb 23 #Python
python实现SOM算法
Feb 23 #Python
python实现k-means聚类算法
Feb 23 #Python
python写一个md5解密器示例
Feb 23 #Python
Python机器学习之K-Means聚类实现详解
Feb 22 #Python
python实现远程通过网络邮件控制计算机重启或关机
Feb 22 #Python
You might like
全国FM电台频率大全 - 5 内蒙古自治区
2020/03/11 无线电
Zend studio for eclipse中使php可以调用mysql相关函数的设置方法
2008/10/13 PHP
PHP小技巧之函数重载
2014/06/02 PHP
php计算函数执行时间的方法
2015/03/20 PHP
WordPress中缩略图的使用以及相关技巧
2015/11/24 PHP
PHP中quotemeta()函数的用法讲解
2019/04/04 PHP
php生成微信红包数组的方法
2019/09/05 PHP
PHP上传图片到数据库并显示的实例代码
2019/12/20 PHP
js 颜色选择器(兼容firefox)
2009/03/05 Javascript
js 键盘记录实现(兼容FireFox和IE)
2010/02/07 Javascript
jQuery dialog 异步调用ashx,webservice数据的代码
2010/08/03 Javascript
利用jquery动画特效和css打造的侧边弹出垂直导航
2014/04/04 Javascript
Javascript基础教程之数据类型 (布尔型 Boolean)
2015/01/18 Javascript
详谈javascript中DOM的基本属性
2015/02/26 Javascript
jquery表单验证需要做些什么
2015/11/17 Javascript
Markdown与Bootstrap相结合实现图片自适应属性
2016/05/04 Javascript
AngularJS表单详解及示例代码
2016/08/17 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(同步显示图像位置信息)
2016/12/02 Javascript
LayUI动态设置checkbox不显示的解决方法
2019/09/02 Javascript
python Django模板的使用方法(图文)
2013/11/04 Python
Python 基础之字符串string详解及实例
2017/04/01 Python
Python常用模块sys,os,time,random功能与用法实例分析
2020/01/07 Python
pyautogui自动化控制鼠标和键盘操作的步骤
2020/04/01 Python
tensorflow转换ckpt为savermodel模型的实现
2020/05/25 Python
Tensorflow中批量读取数据的案列分析及TFRecord文件的打包与读取
2020/06/30 Python
如何基于python把文字图片写入word文档
2020/07/31 Python
scrapy实践之翻页爬取的实现
2021/01/05 Python
NEW LOOK官网:英国时装零售巨头之一,快时尚品牌
2017/01/11 全球购物
美国最大的袜子制造商和零售商:Renfro Socks
2017/09/03 全球购物
物理专业大学生职业生涯规划书
2014/02/07 职场文书
高校教师岗位职责
2014/03/18 职场文书
工作总结与自我评价
2014/09/18 职场文书
党员教师群众路线思想汇报范文
2014/10/28 职场文书
医学生自荐信范文(2016精选篇)
2016/01/28 职场文书
springBoot基于webSocket实现扫码登录
2021/06/22 Java/Android
Windows server 2022创建创建林、域树、子域的步骤
2022/06/25 Servers