博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【七夕福利】k均值聚类算法告诉你到哪里找对象
阅读量:5825 次
发布时间:2019-06-18

本文共 4184 字,大约阅读时间需要 13 分钟。

一年一度的中国情人节又到了,广大单身狗们是不是又在发愁自己的终身大事呢?不要慌,今年有机器学习的各种算法来帮大家,我们在这里挑一款比较简单的叫做k均值聚类的算法给大家做一个示范。

k均值算法

如果没有接触过机器学习的话,一听这个名字k均值算法,是不是有一种很高大上的感觉呢?再看看维基百科的介绍,更蒙了:

k-平均算法源于信号处理中的一种向量量化方法,现在则更多地作为一种聚类分析方法流行于数据挖掘领域。k-平均聚类的目的是:把n个点(可以是样本的一次观察或一个实例)划分到k个聚类中,使得每个点都属于离他最近的均值(此即聚类中心)对应的聚类,以之作为聚类的标准。这个问题将归结为一个把数据空间划分为Voronoi cells的问题。

不要慌,跟着我一步一步往下走,最终我们还是只用寥寥几行代码搞定这个看上去很牛逼的东东。

获取数据

做任何算法之前,首先是要获取数据,数据来源很多种,可能是公开数据,可能是产品数据,可能是通过各种渠道收集上来的数据。在这里为了方便起见,我们还是跟一样,直接从国家统计局的第六次人口普查结果取数据,这一次我们取第《》作为我们的数据来源。同样的,在读入数据之前,你需要简单地对csv文件作一下处理,把全国这一行删掉,把几列的名称改一下,然后读入数据:

df = pd.read_csv('chnedu.csv')

clipboard.png

为了方便大家操作,我把做好的数据放在github上,。

处理数据

为了计算方便,我们对数据简单处理一下:

df['highedu'] = (df['大学本科小计'] + df['研究生小计']) / df['6岁及以上人口合计']df['gender'] = df['6岁及以上人口男'] / df['6岁及以上人口女']

假定我们只从两个维度考虑问题,第1个维度是受过高等教育的人群占总人口的百分比,第2个维度是所有人口中的男女比例,实际上k均值算法可以处理很多维度,我们这里简化一下,是为了后面作图方便。

散点图

有了两个维度,一个作X轴,一个作Y轴,我们就可以开始画图了,是不是有点迫不及待了呢?简单,寥寥数行代码而已:

fig = plt.figure(figsize = (9,7))ax1 = fig.add_subplot(111)ax1.scatter(df['gender'], df['highedu'], c = 'r', marker = 'o')plt.show()

第1行定义图片大小,第2行添加子图,第3行指定要画散点图,X轴用男女性别比,Y轴用高等教育比,第4行画图:

clipboard.png

唔,从图上看,好像是地区之间有点差异,但是我们完全不知道哪个点对应哪个省区,下面我们把省区的名字显示在图上:

for i, txt in enumerate(df['地区']):    ax1.annotate(txt, (df['gender'][i], df['highedu'][i]))

clipboard.png

这回明显看出来了,北京、上海、天津受过高等教育的人群比例远高于全国其它省份,从男女比例上来看,天津的男性要远多于女性(是这样吗?请天津的朋友告诉我),而河南是全国所有省份里男女比最接近1比1的,其它所有地方都是男多女少的局面。北京、上海男性略多于女性,但还没有达到天津这样的差异,天津似乎是个适合大龄女青年找对象的好地方,如果追求高学历的话,北京上海也不错。

但是,不要急,别忘了,我们上面的X轴是以全部人口的男女比例做的,那么如果只看高学历人群的男女比例呢?我们把X轴的计算公式换一下,其他什么都不变,再来看一下:

df['gender'] = (df['大学本科男'] + df['研究生男']) / (df['大学本科女'] + df['研究生女'])

clipboard.png

这回数据变得有点不一样了,在所有受过高等教育的人里面,北京女性的受教育程度明显较高,天津也不差,上海则是男性要多于女性。这告诉我们什么呢?如果你是一个大龄女青年,你到上海找到另一半的可能性要高于北京和天津。

k均值聚类

最后,我们再把所有这些点分一个类,以供全国朋友们参考。这时候就要用到k均值聚类算法了,代码也很简单:

from sklearn.cluster import KMeanskmeans = KMeans(n_clusters = 4)X_clustered = kmeans.fit_predict(df[['gender', 'highedu']])LABEL_COLOR_MAP = {0:'r', 1:'g', 2:'b', 3:'m'}label_color = [LABEL_COLOR_MAP[l] for l in X_clustered]ax1.scatter(df['gender'], df['highedu'], c = label_color, marker = 'o')

第1行引入算法,第2行创建算法,这里我们指定分成4类,当然你也可以指定3类或5类,第3行机器会自动运行算法把数据分开,接下来的2行是给分开的类每一类一个不同的颜色,最后我们把点画在图上:

clipboard.png

最后的分类结果其实满有意思,我们并没有告诉机器任何事实,而机器根据数据自动把东北、华北和西北(大致)分在了第一集团里面。以上就是k均值聚类的用法,主要作用就是机器自动分类,但最终对于分类的解读还是需要由人的大脑来完成,也许在这里的意义是说,如果你要在全国开设婚姻介绍所的话,也许可以根据这样的分类建立分部。同时我们看到,选择不同的座标轴参数对于分类算法的最终结果影响是巨大的,如果你要得到更加真实准确的结果,还应该把人口年龄分布、婚姻状况以及其它更多因素考虑进来,这里只是一个简单的演示,只是想告诉大家使用Python进行机器学习有多么的简单。

美化

为了让我们的图形更漂亮一些,我们只需要在代码的最开始处添加2行代码:

import seaborn as snssns.set()

引入seaborn这个库,它本身是对matplotlib的一个扩充,新增了很多图形,但即使什么都不做,它也能自动让图形比原生的matplotlib漂亮一些:

clipboard.png

最后,附上完整代码:

import pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsfrom sklearn.cluster import KMeanssns.set()df = pd.read_csv('chnedu.csv')df['highedu'] = (df['大学本科小计'] + df['研究生小计']) / df['6岁及以上人口合计']df['gender'] = (df['大学本科男'] + df['研究生男']) / (df['大学本科女'] + df['研究生女'])plt.rcParams['font.sans-serif']=['SimHei']fig = plt.figure(figsize = (9,7))ax1 = fig.add_subplot(111)kmeans = KMeans(n_clusters = 5)X_clustered = kmeans.fit_predict(df[['gender', 'highedu']])LABEL_COLOR_MAP = {0:'r', 1:'g', 2:'b', 3:'m', 4:'k'}label_color = [LABEL_COLOR_MAP[l] for l in X_clustered]ax1.scatter(df['gender'], df['highedu'], c = label_color, marker = 'o')for i, txt in enumerate(df['地区']):    ax1.annotate(txt, (df['gender'][i], df['highedu'][i]))plt.show()

交互

用matplotlib做的图是静态的,没有交互效果,如果我们希望鼠标移上去时有相应的动作,那么应该怎么做呢?这时候我们可以放弃matplotlib,而改用plotly,可以做出既漂亮又有交互效果的图,使用方式也很简单:

import pandas as pdfrom sklearn.cluster import KMeansfrom plotly.offline import init_notebook_mode, iplotimport plotly.graph_objs as goinit_notebook_mode(connected=True)df = pd.read_csv('chnedu.csv')df['highedu'] = (df['大学本科小计'] + df['研究生小计']) / df['6岁及以上人口合计']df['gender'] = (df['大学本科男'] + df['研究生男']) / (df['大学本科女'] + df['研究生女'])# Set a 3 KMeans clusteringkmeans = KMeans(n_clusters = 4)# Compute cluster centers and predict cluster indicesdf['cluster'] = kmeans.fit_predict(df[['gender', 'highedu']])data = []for i in range(0, 4):    trace = go.Scatter(        x = df.loc[df.cluster==i].gender,        y = df.loc[df.cluster==i].highedu,        text = df.loc[df.cluster==i].地区,        mode = 'markers'    )    data.append(trace)iplot(data, filename='basic-scatter')

做出来的图形却很漂亮并且带有交互效果:

clipboard.png

转载地址:http://clsdx.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
redis geo 地理位置系应用战案例
查看>>
<备份>10.5yum
查看>>
IPv6单播、组播、泛播地址详解(四)
查看>>
Office 365之OneDrive for Business开启匿名共享
查看>>
系统集成项目管理工程师---教授讲解
查看>>
Python自动化开发学习8
查看>>
Python自动化开发学习-Scrapy
查看>>
XenServer安装Linux虚拟机系统如何显示图形界面
查看>>
十分详细的DHCP服务工作原理剖析
查看>>
解决WINDOWS7远程桌面到WINDOWS SERVER2003太慢的故障
查看>>
nginx加ssl模块及添加ssl功能
查看>>
学大联姻360:一场盛宴两种可能
查看>>
linux-who
查看>>
Linux下使用CUPS提供打印服务
查看>>
Linux简介及基本操作V1.0
查看>>
KVM脚本批量添加删除虚拟机
查看>>
oracle学习笔记-第三篇
查看>>
我的友情链接
查看>>
centos 6.8 安装 pure-ftpd-1.0.43,采用MariaDB作为用户数据库
查看>>