用户:四九圣尊查看:0 回复:4 评论:0 创建时间:2018-10-03T20:56:44
那么当我们不知道每个数据点的类型时就无法使用中心聚类了。一开始数据集就是这样的:
那么我们就无法选择聚类中心了(没有类别)。这时我们如何把数据分为两类呢?这时就要采用无监督学习算法了:Kmeans均值聚类法。
这里引用一下csdn上kmeans的流程:
上图a表达了初始的数据集,假设k=2。在图b中,我们随机选择了两个k类所对应的类别质心,即图中的红色质心和蓝色质心,然后分别求样本中所有点到这两个质心的距离,并标记每个样本的类别为和该样本距离最小的质心的类别,如图c所示,经过计算样本和红色质心和蓝色质心的距离,我们得到了所有样本点的第一轮迭代后的类别。此时我们对我们当前标记为红色和蓝色的点分别求其新的质心,如图4所示,新的红色质心和蓝色质心的位置已经发生了变动。图e和图f重复了我们在图c和图d的过程,即将所有点的类别标记为距离最近的质心的类别并求新的质心。最终我们得到的两个类别如图f。
(比较长,但是不要害怕,你能看懂的!)注:k就是有几类,质心就跟之前的中心聚类的中心一样。
这里初始质心的选取我们一会儿再探讨。(这是个极其复杂的问题。初始质心的选择对训练结果的影响很大。)
这里我们初始质心选择:d1 = [4.5,2.5],d2 = [6.5,4]:(蓝点和橙点)按照刚才的聚类算法一步一步的对质心进行调整:
def distance(x,y,x1,y1):
one = abs(x-x1) ** 2
two = abs(y-y1) ** 2
return (one+two) ** 0.5
label = []
for i in range(len(data)):
a = distance(d1[0],d1[1],data[i][0],data[i][1])
b = distance(d2[0],d2[1],data[i][0],data[i][1])
if a>b:
label.append(1)
else:
label.append(-1)
d1 = [0,0]
d2 = [0,0]
d1_num = 0
d2_num = 0
for i in range(len(data)):
if label[i] == -1:
d1[0] += data[i][0]
d1[1] += data[i][1]
d1_num += 1
else:
d2[0] += data[i][0]
d2[1] += data[i][1]
d2_num += 1
d1[0] = d1[0]/d1_num
d1[1] = d1[1] / d1_num
d2[0] = d2[0] / d2_num
d2[1] = d2[1] / d2_num
Normal_x = []
Normal_y = []
color_x = []
color_y = []
for i in range(len(data)):
if label[i] == -1:
Normal_x.append(data[i][0])
Normal_y.append(data[i][1])
else:
color_x.append(data[i][0])
color_y.append(data[i][1])
第二次迭代:第三次迭代:
第四次迭代:可以看出kmeans已经能较好的分出类别了,但还是有个别分错的地方。因为数据集x,y平均值的点已经跟质心。重合,
这时优化便停止了。
所以我们需要选取更好的初始质心才能100%正确分类。至于怎么选取,一会儿再讲!
质心的灵活选择,kmeans++原理介绍:
kmeans很简单喵,它的最终目标就是让各个质心分布的尽可能远。这是它的操作流程:(这张图片少有的简单易懂。)
距离已选择质心最长的那个便是下一个质心所在,代码实现:
pick = random.randint(0,90)
d1 = data[pick]
biggest = 0
biggest_index = 0
for i in range(len(data)):
if distance(d1[0],d1[1],data[i][0],data[i][1])>biggest:
biggest = distance(d1[0],d1[1],data[i][0],data[i][1])
biggest_index = i
d2 = data[biggest_index]
这样就可以让电脑自动选择质心,不仅高效,而且更加准确!
点赞0
评论
那么如何评估kmeans分类结果的好坏呢?
计算一类数据的方差便是一种方法。方差是各个数据与平均数之差的平方的平均数 比如1.2.3.4.5 这五个数的平均数是3 ,所以这五个数的方差就是 1/5[(1-3)²+(2-3)²+(3-3)²+(4-3)²+(5-3)²]=2
即数据离散程度越低,分类程度就越高。代码实现:
N_x_ra = 0#平均值
N_y_ra = 0#平均值
for i in range(len(Normal_x)):
N_x_ra += Normal_x[i]#一类样本的x轴
N_y_ra += Normal_y[i]#一类样本的x轴
N_x_ra = N_x_ra/len(Normal_x)#平均值
N_y_ra = N_y_ra/len(Normal_y)#平均值
Var_nx = 0#方差
Var_ny = 0#方差
for i in range(len(Normal_x)):
Var_nx += (Normal_x[i]-N_x_ra) ** 2
Var_ny += (Normal_y[i]-N_y_ra) ** 2
Var_nx = Var_nx/len(Normal_x)#方差
Var_ny = Var_ny/len(Normal_y)#方差
Var_b1 = (Var_nx+Var_ny)/2#方差平均值
print("SSE:" + str(Var_b1))
训练完成后的kmeans各个类别的方差是一样的。
通过计算方差还可以找出K的最佳取值,这里大家可以自己去尝试。
点赞0
评论