机器学习-周志华-个人练习9.4
2017-05-07 18:10
387 查看
9.4 试编程实现k均值算法,设置3组不同的k值,3组不同初始中心点,在西瓜数据集4.0上进行实验比较,并讨论什么样的初始中心有利于取得好结果。
根据k均值算法的迭代公式,可以知道在二维平面上,这些中心点直接由其几何位置的两点间垂直平分线作为聚类边界,因此在数据不多的情况下,很容易陷入局部最优,从而使迭代过程很快结束。实际执行代码发现,所谓取得好结果,应该是使各点离聚类边界尽量远,且最终的中心点相互远离。个人推测,由于在更新中心向量的时候使用了平均,因而所有中心会尽量向点分布密度较大的区域移动,因此,初始中心应该尽量分散到不同的高点密度分布区域上去,可取得较好结果。本题的算法十分简单,不过如果直接采用与书上相同的初始中心,则马上就会收敛而不会像书上所说训练5轮才达到收敛。也就是说,书上给的示例是错的。
另外,通过这个题,我才发现,原来用matplotlib可以画动图,利用animation里面的ArtistAnimation或者FuncAnimation即可。然而,我发现不能理想地导出gif图,这就比较尴尬了。。。网上搜了一下发现,需要装ImageMagick这个软件,然而装了还是各种错,后来找到matplotlib的配置文件,在最后一行更改convert_path为convert.exe的安装路径也仍然不行,还报错:winError
5,后来找到一篇帖子一篇帖子,讲到了这个问题,就是直接找到matplotlib的__init__.py,
# this is the instance used by the matplotlib classes rcParams = rc_params()找到上面这一行,在后面加上一行:
rcParams['animation.convert_path'] = 'D:\...\convert.exe' # 你的convert.exe的安装路径这样就可以完美运行啦,生成的gif占用空闲小而且非常清晰,比用录屏软件截出来的好很多。好了,废话不多说了,上代码和图。
# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation def kmeans(data, center_ids, max_err=0.0001, max_round=30): init_centers = [] n = len(center_ids) for id in center_ids: init_centers.append(data[id,:]) error, rounds = 1.0, 0 while error > max_err and rounds < max_round: rounds += 1 clusters = [] for _ in range(n): clusters.append([]) for j in range(len(data)): dist = [] for i in range(n): vector = data[j,:] - init_centers[i] d_ji = np.dot(vector, vector) ** 0.5 dist.append(d_ji) near_id = sorted(enumerate(dist), key=lambda x: x[1])[0][0] clusters[near_id].append(j) new_center = [0]* n error = 0 for i in range(n): new_center[i] = np.sum(data[clusters[i],:], axis=0) new_center[i] /= len(clusters[i]) vec = new_center[i] - init_centers[i] err = np.dot(vec,vec) ** 0.5 if err: init_centers[i] = new_center[i] error += err yield clusters, new_center,rounds # 用yield可以得到每一轮训练后的聚类情况,最终返回的是一个生成器 data = np.array([ [0.697, 0.460],[0.774, 0.376],[0.634, 0.264],[0.608, 0.318],[0.556, 0.215], [0.403, 0.237],[0.481, 0.149],[0.437, 0.211],[0.666, 0.091],[0.243, 0.267], [0.245, 0.057],[0.343, 0.099],[0.639, 0.161],[0.657, 0.198],[0.360, 0.370], [0.593, 0.042],[0.719, 0.103],[0.359, 0.188],[0.339, 0.241],[0.282, 0.257], [0.748, 0.232],[0.714, 0.346],[0.483, 0.312],[0.478, 0.437],[0.525, 0.369], [0.751, 0.489],[0.532, 0.472],[0.473, 0.376],[0.725, 0.445],[0.446, 0.459]]) init_centers = [12,22] # 对应的是选择的初始中心样本的id,这也同时代表了选择的聚类数目 fig,ax = plt.subplots(1,1,figsize=(5,5)) ax.set_xlim(0, 1) ax.set_ylim(0, 0.6) ax.set_ylabel('sugar') ax.set_xlabel('density') imgs = [] for cluster, center, rounds in kmeans(data, init_centers): # 对各轮聚类的结果进行保存,存入imgs pics,dye = [], ['red', 'orange', 'green', 'blue', 'pink'] ax.set_title('clusters in %s rounds' % rounds) for i, li in enumerate(cluster): pics.append(ax.scatter(data[li, 0], data[li, 1], c=dye[i])) pics.append(ax.scatter(center[i][0], center[i][1], s=45,c='gray', marker='s',)) imgs.append(pics) imgs.insert(0, [ax.scatter(data[:,0],data[:,1], c='k')]) A = animation.ArtistAnimation(fig, imgs, interval=1000, blit=True, repeat_delay=500) plt.show() A.save('3point.gif',fps=2, writer='imagemagick') # 设置保存路径,gif图每秒帧数2类聚类:
3类聚类:
4类聚类:
相关文章推荐
- 机器学习-周志华-个人练习10.6
- 机器学习-周志华-个人练习12.4
- 机器学习(周志华) 个人练习答案7.6
- 机器学习-周志华-个人练习13.1
- 机器学习-周志华-个人练习11.1
- 机器学习-周志华-个人练习13.2
- 机器学习-周志华-个人练习13.10
- 机器学习-周志华-个人练习4.4
- 机器学习-周志华-个人练习9.6
- 机器学习-周志华-个人练习4.3
- 机器学习-周志华-个人练习10.1
- 机器学习-周志华-个人练习8.3和8.5
- 机器学习-周志华-个人练习13.4
- 机器学习-周志华-个人练习11.3
- 《机器学习(周志华)》 习题9.4参考答案
- 机器学习(周志华) 习题7.3 个人笔记
- 《机器学习》周志华 习题答案9.4
- 周志华《机器学习》课后习题解答系列(四):Ch3.4 - 交叉验证法练习
- 机器学习(周志华版) 第一章习题1.1个人解答
- C++ primer 第五版 中文版 练习 9.3 & 练习 9.4 个人 code