二分K-mean均值算法原理讲解和代码实战
前言
上一篇我们简单给大家介绍了一下K-mean均值的原理和详细代码实践。由于普通的K-mean均值算法很容易陷入局部最优解的情况,这一篇,给大家介绍一个在前面的基础上的优化算法,能够很好的解决陷入局部最优解的情况。
GitHub地址:二分K-mean算法实战
K-mean算法回顾:K-mean均值算法原理讲解和代码实战
文章目录
二分K-mean均值算法原理解析
K-mean局限性分析
在我们写完上一节的K-mean算法后,我们可以会惊讶于算法实现方式的简单和效果的强大,但是也同样存在这样的问题,咱们看下面一张图:
图1 该图片来自《机器学习实战》
从这个图中,我们可以看到,图中的数据分为了三类,但是这样的分类明显不是一个好的分类。好的分类应该是上面三组数据各属于一类,比如下图:
图2 该图片来自《机器学习实战》
是什么原因造成出现第图1的情况呢?
是因为K-mean是采用随机初始化K点的方法,所以极有可能由于初始化点的位置,导致出现图1的情况
目前比较好的解决办法:
- 运行多次K-mean算法,取使得损失值最小的K点。(数据量比较小的时候效果比较好)
- 二分K-mean均值 -这个方法很好的解决了这个问题,下面重点讲解
二分K-mean均值原理
- 首先我们将整个数据集当成一簇,取当前所有数据点的均值作为这个簇的点坐标
- 对该簇使用K-mean进行二分类,计算分类后损失值(也就是数据点距所属簇的欧几里得距离)的大小。选取使得误差最小的那个簇进行划分。
- 不断循环2,直到当前族的个数等于K值。
伪代码(摘抄《机器学习实战》):
将所有点看成一个簇
当簇数目小于K时
对于每一个簇
计算总误差
在给定的簇上面进行K-mean均值聚类(k=2)
计算将该簇一分为二之后的总误差
选择使得误差最小的那个簇进行划分操作
二分K-mean均值算法代码实战
一、生成数据
def CreatData():
x1 = np.random.rand(50)*3#0-3
y1 = [i+np.random.rand()*2-1 for i in x1]
with open('data.txt','w') as f:
for i in range(len(x1)):
f.write(str(x1[i])+'\t'+str(y1[i])+'\n')
二、读取数据
def loadDateSet(fileName):
dataMat=[]
fr = open(fileName)
for line in fr.readlines():
curline = line.strip().split('\t')
#map函数 对指定的序列做映射,第一个参数是function 第二个是序列
#此方法可以理解为进行字符串格式转换.这个函数可以深究
fltLine = map(float,curline)
dataMat.append(list(fltLine))
return dataMat
这里主要是说一下map这个方法
map(function,list) 此方法的作用是将第二个参数(列表或者迭代器)对前面的方法进行一一映射。
举个例子:
>>>def square(x) : # 计算平方数
... return x ** 2
...
>>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
map(float,curline) 的作用可以理解为将curline 列表中的数字格式转换成float类型的。