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

一开始的目的是学习十大挖掘算法(机器学习算法),并用编码实现一遍,但越往后学习,越往后实现编码,越发现自己的编码水平低下,学习能力低。这一个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的数据,数据为城乡居民家庭人均收入及恩格尔系数(点击这里下载)

数据描述:

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 kmeans聚类简单介绍和实现代码
  • Python实现k-means算法
  • python中kmeans聚类实现代码
  • python实现k-means聚类算法
  • Python机器学习之K-Means聚类实现详解
  • Python实现Kmeans聚类算法
  • python实现kMeans算法
  • 详解K-means算法在Python中的实现
  • python中学习K-Means和图片压缩
  • Python KMeans聚类问题分析
时间: 2018-02-21

Python机器学习之K-Means聚类实现详解

本文为大家分享了Python机器学习之K-Means聚类的实现代码,供大家参考,具体内容如下 1.K-Means聚类原理 K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大.其基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类.通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果.各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开. 算法大致流程为:(1)随机选取k个点作为种子点(这k个点不一定属于数据集)

Python KMeans聚类问题分析

今天用python实现了一下简单的聚类分析,顺便熟悉了numpy数组操作和绘图的一些技巧,在这里做个记录. from pylab import * from sklearn.cluster import KMeans ## 利用numpy.append()函数实现matlab多维数组合并的效果,axis 参数值为 0 时是 y 轴方向合并,参数值为 1 时是 x 轴方向合并,分别对应matlab [A ; B] 和 [A , B]的效果 #创建5个随机的数据集 x1=append(randn(5

Python实现k-means算法

本文实例为大家分享了Python实现k-means算法的具体代码,供大家参考,具体内容如下 这也是周志华<机器学习>的习题9.4. 数据集是西瓜数据集4.0,如下 编号,密度,含糖率 1,0.697,0.46 2,0.774,0.376 3,0.634,0.264 4,0.608,0.318 5,0.556,0.215 6,0.403,0.237 7,0.481,0.149 8,0.437,0.211 9,0.666,0.091 10,0.243,0.267 11,0.245,0.057 12

python中kmeans聚类实现代码

k-means算法思想较简单,说的通俗易懂点就是物以类聚,花了一点时间在python中实现k-means算法,k-means算法有本身的缺点,比如说k初始位置的选择,针对这个有不少人提出k-means++算法进行改进:另外一种是要对k大小的选择也没有很完善的理论,针对这个比较经典的理论是轮廓系数,二分聚类的算法确定k的大小,在最后还写了二分聚类算法的实现,代码主要参考机器学习实战那本书: #encoding:utf-8 ''''' Created on 2015年9月21日 @author: Z

python实现k-means聚类算法

k-means聚类算法 k-means是发现给定数据集的k个簇的算法,也就是将数据集聚合为k类的算法. 算法过程如下: 1)从N个文档随机选取K个文档作为质心 2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类,我们一般取欧几里得距离 3)重新计算已经得到的各个类的质心 4)迭代步骤(2).(3)直至新的质心与原质心相等或迭代次数大于指定阈值,算法结束 算法实现 随机初始化k个质心,用dict保存质心的值以及被聚类到该簇中的所有data. def initCent(dataSe

Python实现Kmeans聚类算法

本节内容:本节内容是根据上学期所上的模式识别课程的作业整理而来,第一道题目是Kmeans聚类算法,数据集是Iris(鸢尾花的数据集),分类数k是3,数据维数是4. 关于聚类 聚类算法是这样的一种算法:给定样本数据Sample,要求将样本Sample中相似的数据聚到一类.有了这个认识之后,就应该了解了聚类算法要干什么了吧.说白了,就是归类.     首先,我们需要考虑的是,如何衡量数据之间的相似程度?比如说,有一群说不同语言的人,我们一般是根据他们的方言来聚类的(当然,你也可以指定以身高来聚类).

详解K-means算法在Python中的实现

K-means算法简介 K-means是机器学习中一个比较常用的算法,属于无监督学习算法,其常被用于数据的聚类,只需为它指定簇的数量即可自动将数据聚合到多类中,相同簇中的数据相似度较高,不同簇中数据相似度较低. K-MEANS算法是输入聚类个数k,以及包含 n个数据对象的数据库,输出满足方差最小标准k个聚类的一种算法.k-means 算法接受输入量 k :然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高:而不同聚类中的对象相似度较小. 核心思想 通过迭代寻找

python实现kMeans算法

聚类是一种无监督的学习,将相似的对象放到同一簇中,有点像是全自动分类,簇内的对象越相似,簇间的对象差别越大,则聚类效果越好. 1.k均值聚类算法 k均值聚类将数据分为k个簇,每个簇通过其质心,即簇中所有点的中心来描述.首先随机确定k个初始点作为质心,然后将数据集分配到距离最近的簇中.然后将每个簇的质心更新为所有数据集的平均值.然后再进行第二次划分数据集,直到聚类结果不再变化为止. 伪代码为 随机创建k个簇质心 当任意一个点的簇分配发生改变时:     对数据集中的每个数据点:         对

python中学习K-Means和图片压缩

大家在学习python中,经常会使用到K-Means和图片压缩的,我们在此给大家分享一下K-Means和图片压缩的方法和原理,喜欢的朋友收藏一下吧. 通俗的介绍这种压缩方式,就是将原来很多的颜色用少量的颜色去表示,这样就可以减小图片大小了.下面首先我先介绍下K-Means,当你了解了K-Means那么你也很容易的可以去理解图片压缩了,最后附上图片压缩的核心代码. K-Means的核心思想 k-means的核心算法也就上面寥寥几句,下面将分三个部分来讲解:初始化簇中心.簇分配.簇中心移动. 初始化

python kmeans聚类简单介绍和实现代码

一.k均值聚类的简单介绍 假设样本分为c类,每个类均存在一个中心点,通过随机生成c个中心点进行迭代,计算每个样本点到类中心的距离(可以自定义.常用的是欧式距离) 将该样本点归入到最短距离所在的类,重新计算聚类中心,进行下次的重新划分样本,最终类中心不改变时,聚类完成 二.伪代码   三.python代码实现   #!/usr/bin/env python # coding=utf-8 import numpy as np import random import matplotlib.pyplo

K-means聚类算法介绍与利用python实现的代码示例

聚类 今天说K-means聚类算法,但是必须要先理解聚类和分类的区别,很多业务人员在日常分析时候不是很严谨,混为一谈,其实二者有本质的区别. 分类其实是从特定的数据中挖掘模式,作出判断的过程.比如Gmail邮箱里有垃圾邮件分类器,一开始的时候可能什么都不过滤,在日常使用过程中,我人工对于每一封邮件点选"垃圾"或"不是垃圾",过一段时间,Gmail就体现出一定的智能,能够自动过滤掉一些垃圾邮件了.这是因为在点选的过程中,其实是给每一条邮件打了一个"标签&qu

Python Pandas数据结构简单介绍

Series Series 类似一维数组,由一组数据及一组相关数据标签组成.使用pandas的Series类即可创建. import pandas as pd s1 = pd.Series(['a', 'b', 'c,', 'd']) print(s1) #输出: 0 a # 1 b # 2 c # 3 d # dtype: object 上面是传入一个列表实现,上面的0,1,2,3就是数据的默认标签.另外可以通过index属性自定义标签. s2 = pd.Series(['1', '2', '

Python多线程编程简单介绍

创建线程 格式如下 复制代码 代码如下: threading.Thread(group=None, target=None, name=None, args=(), kwargs={}) 这个构造器必须用关键字传参调用 - group 线程组 - target 执行方法 - name 线程名字 - args target执行的元组参数 - kwargs target执行的字典参数 Thread对象函数 函数 描述 start() 开始线程的执行 run() 定义线程的功能的函数(一般会被子类重写

Python实现生成简单的Makefile文件代码示例

在linux下写几个测试程序,还要一行行的输入g++命令进行编译,当经常改测试代码的时候,那一次次的敲(或者一次次的上线箭头选)也感觉不爽,不如make来的快.用Makefile的好处就不用多说了,这里我写了个脚本,其功能是自动搜索当前目录(不包括子目录)下的".c"文件生成Makefile文件. 代码在这里,功能有限(适用于单个文件是一个独立的测试代码的情况),需要的朋友可以稍作修改以满足需求. 复制代码 代码如下: #! /usr/bin/python '''  File     

asp下tag的实现,简单介绍与部分代码

标签(Tag)是什么? 标签是一种更为自由.灵活,完全由用户决定的分类方式,而非传统的由网站定义的分类.您可以根据自己的理解,对发表的文章.上传的图片.音乐.视频等各种文件添加一个或多个标签,进行灵活的描述.  添加标签(Tag)有什么作用? 标签体现了群体的力量,使得用户之间可以通过相近的内容产生更多的关联和互动.您在发表日志或上传文件时添加了Tag ,就可以看到woku.com所有和您使用了相同Tag 的日志和文件.  标签频道中不同大小.粗细的文字代表什么? 使用不同大小.粗细字体的标签,

python命名空间(namespace)简单介绍

命名空间: 每一个作用域变量存储的位置,或者解释为 存储作用域中变量的字典. 作用: 获取想查看某个作用域中的变量名.变量值. 使用方法: locals() #当前命名空间 1. 效果图: 2. 代码 a=10 b=20 # 定义一个变量接收全局命名空间里的变量名.变量值 global_namespace=locals() print(global_namespace) print('\n\n\n') def one(): c=30 d=40 # 定义一个变量接收局部命名空间里的变量名.变量值