十分种算法小故事之Kmeans聚类算法
Posted AI小迷妹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了十分种算法小故事之Kmeans聚类算法相关的知识,希望对你有一定的参考价值。
编辑:AI小迷妹
学校要举办一场篮球比赛,想参加的同学可以到组委会报名,并由组委会统一安排分队。学校一共有20人报名参赛,篮球比赛每一队有五人,可以组成四队。但是,如何合理的对这20名选手进行分组呢?
篮球比赛中有组织后卫,得分后卫,小前锋,大前锋,中锋五个位置,一只五人的篮球队最合理的配置是在每一个位置有对应的一个队员。但是报名参赛的20名选手对自己的位置并没有一个清晰的定义,或者即使在报名时要求报名者提供一个自己想打的位置,他的实际能力与自己的期望也有一定的差异。例如有的同学其实更加适合打中锋的位置,但是他却选择了后卫,因为他对后卫更感兴趣。
【表1: 各位置球员特征】
因此,有必要在组队环节就根据每个选手各自的特点来合理分队。比如身高越高弹跳越好的选手更适合打内线中锋,身高较矮但速度较快的选手更适合打得分后卫,擅长传球的选手更适合打组织后卫等。这种问题可以利用智能聚类的算法来解决。
聚类是指根据一些输入的特征来将这些特征所代表的样本进行分类。在《战国策.齐策三》中有一句话叫“方以类聚,物以群分”,后来这句话演变成了“物以类聚,人以群分”,用来比喻同类的东西经常聚在一起,志同道合的人相聚成群,反之就分开。也就是说我们会根据自己对他人的了解,凭借自己的意志来决定我们所结交的朋友,但是在上述所提的组队问题中,各选手对彼此的身体特征、技术特点都不是很熟的情况下如何能够实现智能组队呢?
这里可以用聚类算法来实现。组委会可以要求每个队员提供自身各方面的数据,组合成为可以代表该队员的特征,例如身高、体重、臂展、弹跳、速度等身体上的特征,以及球场视野、传球能力、无球跑动等技战术特征。聚类算法将根据这些特征数据完成智能聚类,将特点、风格相似的球员聚合在一起形成一个类型。然后在不同的类型当中分别取出一个球员组成一个队伍,这个队伍的配置将是合理的。
【图1:典型的聚类算法示意图】
在之前的小故事中我们已经介绍了什么是特征和如何获取特征。在这个例子里,我们需要先得到队员的身高、体重、臂展、弹跳、速度等身体上的特征,以及球场视野、传球能力、无球跑动等技战术特征。然后我们要用这些特征来衡量选手之间差异性,因此我们引入“距离”的概念。
“距离”是针对两个特征之间的距离,我们设一个选手的特征是X=(X1,X2,...Xd),另一个选手的特征是 Y=(Y1,Y2,...Yd)。由前面的分析可以看出,当特征的维度2时,也就是当d=2时,X和Y之间的距离可以通过以下公式计算:
因此,我们可以将计算距离的方式推广到d维的情况下:
这个公式就是在各个领域都广泛使用的欧式距离。
K-means聚类算法,也被称为K-均值算法或K-平均算法,是一种被广泛使用的聚类算法。该算法的主要功能就是将所有输入的数据划分成为K个子集合,并且要求每个子集合内各个元素之间的差异性尽可能的小,而不同子集合的元素差异性尽可能的大。在篮球对组队的例子中,我们可以将K设定为5,那么算法最后会将所有报名参赛的选手分成5组,每一组内选手的打球风格、身体素质等差异性不大,而各组之间球员的差异性较大。而这5组球员可以看作分别对应着比赛中的5个位置。
首先我需要有5个位置上标准球员的特征,标准球员的特征就是指最适合打这一位置的球员的特征,例如最适合打组织后卫的球员身高不需要太高,但是希望他的速度能够更快,视野能够更开阔,传球能力能够更好;而中锋位置上的球员则希望他的身高能够更高,抢篮板的意识能够更好,协防的意识能够更好。然后利用距离来衡量所有选手与标准球员的差异,某一选手与某一位置标准球员的差异最小,那么说明在所有5个位置中,该选手更加适合球场上的这一位置。
但是标准球员的特征并不能够那么容易的得到,这是因为标准球员应该是所有报名参赛的20位选手中的“标准球员”,而不能来自于外界。也就是说我们需要先知道20名选手当中各个位置的“标准球员”才能更好的将20名选手分到各个位置,但是另一方面我们又需要先知道20名选手当中各个位置选手的情况才能得到各个位置的“标准球员”。那么如何来解决这样一个看似矛盾的问题呢?
既然球员的分组需要标准球员的确定,而标准球员的确定又需要球员的分组,而这两项总是不能同时进行的,那么我们可以选择固定其中一项去得到另一项,并且不断交替固定。例如,初始我们可以先从20名选手当中随机挑选出5个选手,将这5个选手作为5个位置暂时的“标准球员”。然后以这5个暂时的标准球员为准进行分组聚类,也就是计算每个选手与这5个标准球员的欧式距离来表征每个选手与5个标准球员的差异性,并且将每个球员划分到与之差异最小的那个标准球员所代表的类别下。
到此,我们得到了每个球员的初步聚类结果,但是这个结果并不准确,因为我们一开始所用的“标准球员”是随机初始化而来。接下来我们可以利用初步聚类的结果来更新“标准球员”,现在所有球员已经初步聚合成了5类,分别代表适合5个位置的球员集合,那么我们认为每个集合当中所有球员的平均水平就代表了当前状态下能得到的“标准球员”,因此可以简单的将集合当中每个球员的特征求取其平均值,得到更新后的“标准球员”的特征。进一步我们又可以利用更新后的“标准球员”来重新对选手进行聚类得到新的聚类结果,然后根据新的聚类结果更新“标准球员”。总之上述过程是一个可以不断重复的过程,直到新一次的聚类结果与上一次的聚类结果相同时,表示多次重复的聚类已经收敛到了一个稳定的状态,对参赛选手的聚类已经完成,得到了一个比较理想的聚类结果。
创建K个点作为K个类别的初始化质心。K是最终要聚类的类别数量。在上述的篮球组队问题中,目标是要将5个不同位置的球员全部聚类出来,因此K=5。每个选手的特征可以看作是一个点,而每次聚类过程中的“标准球员”就是质心,指当前类别所有点的中心。初始化时质心的选择通常是随机确定,即从所有20个选手当中随机挑选5个作为“标准球员”。
对于所有剩下的每个元素,计算其到K个质心的距离(差异性),并且将这些元素划分到差异性最低的类别下。这一步骤就对应了上述问题中根据“标准球员”聚类的步骤。利用剩余球员与当前每个“标准球员”的差异性,将每个球员都划归到一个类别当中,得到当前的聚类结果。
根据聚类结果,更新K个类别的质心,更新的方法是取每个类别中所有元素各自维度的算数平均值。这一步骤就对应上述问题中的根据聚类结果更新“标准球员”。更新每一类别的“标准球员”时应该考虑这一类别中的所有球员,将所有球员特征的平均值作为这一类别新的“标准球员”。
将所有元素按照新的质心重新聚类。即按照更新的“标准球员”重新对所有球员聚类。
重复步骤3和步骤4,直到聚类结果不再发生变化。
【问题定义】
某高中要选出三名选手代表学校参加市里举办的数学建模大赛,经过学校的初赛,共有6位同学经过初赛的选拨,可以说这6位同学能力都很强,因此如何从这六位同学当中最中挑选出三位去参加市里的建模大赛就成了学校要考虑的一个问题。建模大赛要求选手具有综合性的素质,为了使得代表学校的三人小组分工更加合理,每个人都能在比赛当中独挡一面,学校决定让计算机智能系统对所有同学按照每个同学的特点进行分组,将具有相同特长对同学聚合成为一组,并在组内进行复赛,取小组内的最强者进入到最终的三人名单代表学校参加比赛。学校中的老师已经根据这六位同学平时学习中以及初赛中的表现进行了打分,计算机将根据这些分数来进行分组。每一项总分10分,分数越高则表示老师对该同学的该项能力评价越高。
【解题思路】
我们拟采用K-means聚类算法来求解该问题。表格中所有同学的综合特征可以用一个数值表X来表示。该数值表共6行6列,每一行对应于一个同学的特征(共6名同学);六个数值分别对应每个同学的六个特征属性。
数据准备好后,需要对这些数据进行聚类。基于Python的机器学习工具scikit-learn中的K-means代码进行建模求解,求解步骤如下:
1)首先从sklearn中导入K-means模块:
from sklearn.cluster import KMeans
2)然后准备数据,也就是六名同学的特征数值表:
x=[[5,3,4,3,1,8],[9,3,7,9,6,6],[2,1,5,4,4,8],[4,9,6,7,2,4],[8,6,7,3,8,4],[8,3,8,6,2,9]]
3)创建一个K-means聚类模板,调用Scikit-Learn中的相关函数:
clf=KMeans(n_clusters=3) #这里n_clusters是KMeans函数中的一个参数,代表了聚类的类别数为3。
4)上面创建的模版clf是一个空模板,向模板中喂数据它才能够将数据进行聚类,其中fit就是用来喂数据的函数。这样KMeans模板已经根据喂好的数据自动完成了聚类。
clf.fit(x)
5)获取聚类后的标签:
labels=clf.labels_
printlabels
得到结果[0,1,0,2,1,0],表示A、C、F同学聚合成为了一类,B、E同学聚合成了一类,D同学单独是一类。到此,利用KMeans对6位同学进行聚类的工作就完成了。将6位同学聚合成了三类,每类中分别有3位、2位、1位同学。
【代码实现】
--------------------------------
%%从Scikit-Learn软件包中加载K-Means相关模块
from sklearn import KMeans
%%准备训练的样本
x=[[5,3,4,3,1,8],[9,3,7,9,6,6],[2,1,5,4,4,8],[4,9,6,7,2,4],[8,6,7,3,8,4],[8,3,8,6,2,9]]
%%构建并初始化K-means
clf=KMeans(n_clusters=3)
%%利用K-Means算法对数据x进行聚类
clf.fit(x)
%%获取聚类后的标签
labels=clf.labels_
%%打印出聚类后的结果
printlabels
--------------------------------
想学习了解人工智能知识的小伙伴们,请关注:
以上是关于十分种算法小故事之Kmeans聚类算法的主要内容,如果未能解决你的问题,请参考以下文章