用Scipy实现K-means聚类算法
这是我之前写过的一篇文章,使用k-均值聚类算法给明星的身材分分类,由于技艺不精,写得着实不好。今天在stackoverflow上发现,原来scipy有聚类的相关包,还挺方便的。不过,貌似网上似乎都没有它的使用介绍。我忙了一下午,终于搞好了,我的数据如下:
身高 体重 胸围 腰围 臀围 金巧巧 164 112.5 34.0 25.0 34.0 杨幂 168 99.0 32.0 24.0 32.0 钟丽缇 168 108.0 36.0 24.0 35.0 朱茵 160 95.0 33.0 22.0 33.0 赵薇 166 105.0 33.0 23.0 33.0 李珊珊 175 115.0 36.0 24.0 36.0 佘诗曼 164 96.0 33.0 22.0 34.0 郭羡妮 166 103.0 33.0 23.0 34.0 郑秀文 165 100.0 31.0 22.0 32.0 林嘉欣 163 108.0 33.0 24.0 34.0 韩君婷 168 108.0 34.0 24.0 35.0 安雅 163 104.0 34.5 24.0 35.0 林志玲 174 117.0 34.0 24.0 36.0 萧蔷 170 108.0 34.0 23.0 35.0 林嘉绮 180 126.0 34.0 25.0 35.0 姚乐怡 163 101.0 34.0 24.0 34.0 关之琳 170 117.0 35.0 24.0 35.0 巩俐 168 126.0 38.0 30.0 36.0 彭丹 169 125.0 36.0 24.0 36.0 张柏芝 165 101.0 33.0 25.0 34.0 章子怡 164 108.0 32.0 24.0 34.0 何洁 157 104.0 32.0 20.0 45.0 蔡依林 158 92.0 32.0 24.0 32.0 阿娇 160 101.0 32.0 24.0 33.0 阿Sa 165 100.0 32.0 23.0 33.5 高圆圆 167 108.0 33.0 24.0 34.0 奥黛丽赫本 170 103.5 32.0 20.0 35.0 温碧霞 164 106.0 33.0 23.0 33.0 安吉利娜-朱丽 173 130.0 36.0 27.0 36.0 巩新亮 168 101.0 34.0 22.0 33.0 舒淇 168 115.0 34.0 24.0 35.0 范冰冰 168 112.0 33.0 22.0 32.0 阿朵 166 115.0 38.0 30.0 38.0 白歆惠 175 112.0 33.0 23.0 35.0 韩艺瑟 166 101.0 33.0 24.0 33.0 幸田来未 156 92.0 33.0 22.0 33.0 饭岛爱 161 100.0 33.5 22.0 33.5 苍井空 155 101.0 35.0 22.4 32.7 衫本彩 168 124.0 33.9 22.6 33.6 宋慧乔 161 101.0 33.0 24.0 32.0 李慧珍 160 92.0 33.0 24.0 32.0 陈怡蓉 160 101.0 32.0 25.0 34.0 张梓林 182 128.0 34.7 25.0 34.8 斯嘉丽·约翰逊 160 108.0 35.5 24.6 35.5 霍莉·威洛比 170 123.8 29.3 23.4 30.1 碧昂斯 170 126.0 35.2 23.8 34.4 蕾哈娜 173 108.0 30.0 24.0 32.0 玛丽莲 166 120.4 35.0 22.0 35.0 黛塔·范·提思 168 107.0 34.0 22.0 34.0 凯蒂·派瑞 173 130.0 34.0 27.0 33.0 碧姬·芭铎 170 128.0 35.0 23.0 35.0 金·卡戴珊 175 128.0 35.5 25.0 36.0 拉拉·斯通 173 112.5 34.0 24.0 35.0 洪欣 167 124.0 33.0 25.0 35.0 王祖贤 172 128.0 33.0 25.0 33.0 林心如 167 103.5 33.0 22.0 34.0 孟广美 178 129.0 34.0 26.0 36.0 应采儿 175 112.5 33.0 24.5 34.0 张韶涵 158 90.0 32.0 23.5 32.0 徐若瑄 161 114.0 33.0 25.0 33.0 桂纶镁 164 103.5 32.0 23.0 34.5 陈乔恩 165 90.0 33.0 22.0 33.3 杨丞琳 161 99.0 32.0 23.0 33.0 廖碧儿 171 117.0 35.0 24.0 34.0 李玟 162 105.0 35.0 22.5 35.0 Maggie 170 106.0 34.0 24.0 34.0 张曼玉 168 115.0 32.4 23.0 34.0 上述数据用csv格式存储,代码如下:
1234567891011121314151617181920import
pandas as pd
from
scipy.cluster.vq
import
vq, kmeans, whiten,kmeans2
data
=
pd.read_csv(
'/home/rickey/文档/学习/数据挖掘与数据仓库/数据挖掘作业/三围数据'
,sep
=
't'
,index_col
=
0
)
matData
=
data.as_matrix()
whitened
=
whiten(matData)
center
=
kmeans(whitened,
12
)[
0
]
result
=
vq(whitened,center)[
0
]
dicResult
=
{}
resultList
=
result.tolist()
i
=
0
for
i
in
range
(
len
(resultList)):
#print i
if
dicResult.has_key(resultList[i]):
dicResult[result[i]].append(i)
else
:
dicResult[result[i]]
=
[i]
for
i
in
dicResult:
for
j
in
dicResult[i]:
data.index[j],
'nnn'
现在的代码量相对于之前的,真的是少了很多很多呀。下面我介绍一下一些主要函数的说明:
我这里使用了scipy,pandas两个包,read_csv读取csv文件的效果我觉得比numpy和scipy都要好。data里面包含了人名,列名,所以用matData获取纯数据部分。whiten函数比较坑爹,它的文档的例子是错误的,我是看了它的源代码才知道什么意思的,实际上,它是先算出matData各列的标准差,形成一个新的数组,比如上面的数据有四列,该新的数组就有四个元素,每个元素分别是对应列的标准差。然后,用matData处于该标准差数据,就得出了whitened这个结果了。
center获得的是聚类中心所形成的数组。,这里,可以用kmeans,也可以用kmeans2。他们两个的区别我还没有去细致区分。kmeans返回的结果是一个有两个元素的元组,第一个元素是聚类中心数组,第二个元素是单个数字,我不太明白它的意思。
result则是聚类的结果。这里,vq需要两个参数,分别是whitened,center,通过vq,可以获取每个人所属的类,返回的也是如kmeans一样的元组结果,第一个元素如下:
array([ 6, 11, 7, 3, 11, 7, 3, 11, 11, 6, 7, 8, 7, 7, 10, 6, 7, 0, 2, 6, 6, 1, 5, 5, 11, 6, 11, 11, 10, 11, 7, 11, 0, 7, 6, 5, 3, 9, 2, 5, 5, 6, 10, 8, 4, 2, 4, 2, 11, 10, 2, 10, 7, 2, 2, 11, 10, 7, 5, 6, 11, 3, 5, 7, 8, 7, 11])这个数组的意思是说,第一个人属于聚类中心6,第二个人属于聚类中心11。后面的那些代码,主要是用来输出人名的,与聚类算法已经无关了,获得的结果会变,貌似即使是同样的k值,结果还是会有点不一样的,k值也比较难以确定,我分的是12个,结果如下:
巩俐 阿朵 何洁 彭丹 衫本彩 碧昂斯 玛丽莲 碧姬·芭铎 洪欣 王祖贤 朱茵 佘诗曼 饭岛爱 陈乔恩 霍莉·威洛比 蕾哈娜 蔡依林 阿娇 幸田来未 宋慧乔 李慧珍 张韶涵 杨丞琳 金巧巧 林嘉欣 姚乐怡 张柏芝 章子怡 高圆圆 韩艺瑟 陈怡蓉 徐若瑄 钟丽缇 李珊珊 韩君婷 林志玲 萧蔷 关之琳 舒淇 白歆惠 拉拉·斯通 应采儿 廖碧儿 Maggie 安雅 斯嘉丽·约翰逊 李玟 苍井空 林嘉绮 安吉利娜-朱丽 张梓林 凯蒂·派瑞 金·卡戴珊 孟广美 杨幂 赵薇 郭羡妮 郑秀文 阿Sa 奥黛丽赫本 温碧霞 巩新亮 范冰冰 黛塔·范·提思 林心如 桂纶镁 张曼玉总体来讲,感觉不然我之前的那个算法分得准确。