MeanShift算法可以称作均值飘移聚类,是基于聚类中心的聚类算法,但和k-means聚类有所不同的是,不必须提早原作类别的个数k。在MeanShift算法中聚类中心是通过一定范围内样本密度来确认的,通过不断更新聚类中心,直到最后的聚类中心超过中止条件。
整个过程可以看右图,我实在还是较为形象的。MeanShift向量MeanShift向量是指对于样本X1,在以样本点X1为中心,半径为h的高维球区域内的所有样本点X的加权平均值,如下右图,同时也是样本点X1改版后的座标。
而中止条件则是指|Mh(X)-X|<ε,满足条件则样本点X1暂停改版,否则将以Mh(X)为新的样本中心反复上述步骤。核函数核函数在机器学习(SVM,LR)中经常出现的频率是十分低的,你可以把它看作是一种同构,是计算出来同构到低维空间之后的内积的一种简单方法。在这个算法中将用于高斯核,其函数形式如下。
h回应比特率,当比特率h一定时,两个样本点距离越近,其核函数值越大;当两个样本点距离一定时,h越大,核函数值就越小。核函数代码如下,gaosi_value为以样本点X1为中心,半径为h的高维球范围内所有样本点与X1的高斯核函数值,是一个(m,1)的矩阵。defgaussian_kernel(self,distant):m=shape(distant)[1]#样本数gaosi=mat(zeros((m,1)))foriinrange(m):gaosi[i][0]=(distant.tolist()[0][i]*distant.tolist()[0][i]*(-0.5)/(self.bandwidth*self.bandwidth))gaosi[i][0]=exp(gaosi[i][0])q=1/(sqrt(2*pi)*self.bandwidth)gaosi_value=q*gaosireturngaosi_valueMeanShift向量与核函数在01中有提及MeanShift向量是指对于样本X1,在以样本点X1为中心,半径为h的高维球区域内的所有样本点X的加权平均值。
但事实上是不同点对于样本X1的贡献程度是不一样的,因此将权值(1/k)更加改回每个样本与样本点X1的核函数值。改良后的MeanShift向量如下右图。
其中就是指高斯核函数,Sh回应在半径h内的所有样本点子集。MeanShift算法原理在MeanShift算法中实质上利用了概率密度,求出概率密度的局部拟合解法。对于一个概率密度函数f(x),未知一个概率密度函数f(X),其核密度估计为其中K(X)是单位核,概率密度函数f(X)的梯度估算为其中G(X)=-K'(X)。
第一个中括号是以G(X)为核函数对概率密度的估算,第二个中括号是MeanShift向量。因此MeanShift向量是与概率密度函数的梯度成正比的,总是指向概率密度减少的方向。而对于MeanShift向量,可以将其变形为下列形式,其中mh(x)为样本点X改版后的方位。
MeanShift算法流程在并未被标记的数据零点随机自由选择一个点作为接续中心点X;找到以X为中心半径为radius的区域中经常出现的所有数据点,指出这些点同归属于一个聚类C。同时在该聚类中记录数据点经常出现的次数特1。以X为中心点,计算出来从X开始到子集M中每个元素的向量,将这些向量相乘,获得向量Mh(X)。
mh(x)=Mh(X)+X。即X沿着Mh(X)的方向移动,移动距离是||Mh(X)||。
反复步骤2、3、4,直到Mh(X)的较小(就是递归到发散),忘记此时的X。留意,这个递归过程中遇上顶点都应当归类到簇C。
如果发散时当前簇C的center与其它早已不存在的簇C2中心的距离大于阈值,那么把C2和C拆分,数据点经常出现次数也对应拆分。否则,把C作为新的聚类。反复1、2、3、4、5直到所有顶点都被标记为已采访。分类:根据每个类,对每个点的采访频率,所取采访频率仅次于的那个类,作为当前点集的所属类。
TIPS:每一个样本点都必须计算出来其飘移均值,并根据计算出来出有的飘移均值展开移动,以后符合中止条件,最后获得的均值飘移点为该点的聚类中心点。MeanShift算法代码fromnumpyimport*frommatplotlibimportpyplotaspltclassmean_shift():def__init__(self):#比特率self.bandwidth=2#飘移点发散条件self.mindistance=0.001#簇心距离,大于该值则两簇心拆分self.cudistance=2.5defgaussian_kernel(self,distant):m=shape(distant)[1]#样本数gaosi=mat(zeros((m,1)))foriinrange(m):gaosi[i][0]=(distant.tolist()[0][i]*distant.tolist()[0][i]*(-0.5)/(self.bandwidth*self.bandwidth))gaosi[i][0]=exp(gaosi[i][0])q=1/(sqrt(2*pi)*self.bandwidth)gaosi_value=q*gaosireturngaosi_valuedefload_data(self):X=array([[-4,-3.5],[-3.5,-5],[-2.7,-4.5],[-2,-4.5],[-2.9,-2.9],[-0.4,-4.5],[-1.4,-2.5],[-1.6,-2],[-1.5,-1.3],[-0.5,-2.1],[-0.6,-1],[0,-1.6],[-2.8,-1],[-2.4,-0.6],[-3.5,0],[-0.2,4],[0.9,1.8],[1,2.2],[1.1,2.8],[1.1,3.4],[1,4.5],[1.8,0.3],[2.2,1.3],[2.9,0],[2.7,1.2],[3,3],[3.4,2.8],[3,5],[5.4,1.2],[6.3,2],[0,0],[0.2,0.2],[0.1,0.1],[-4,-3.5]])x,y=[],[]foriinrange(shape(X)[0]):x.append(X[i][0])y.append(X[i][1])plt.scatter(x,y,c='r')#plt.plot(x,y)plt.show()classlable=mat(zeros((shape(X)[0],1)))returnX,classlabledefdistance(self,a,b):v=a-breturnsqrt(v*mat(v).T).tolist()[0][0]defshift_point(self,point,data,clusterfrequency):sum=0n=shape(data)[0]ou=mat(zeros((n,1)))t=mat(zeros((n,1)))newdata=[]foriinrange(n):#print(self.distance(point,data[i]))d=self.distance(point,data[i])ifd<self.bandwidth:ou[i][0]=dt[i][0]=1newdata.append(data[i])clusterfrequency[i]=clusterfrequency[i]+1gaosi=self.gaussian_kernel(ou[t==1])meanshift=gaosi.T*mat(newdata)returnmeanshift/gaosi.sum(),clusterfrequencydefgroup2(self,dataset,clusters,m):data=[]fre=[]foriinclusters:i['data']=[]fre.append(i['frequnecy'])forjinrange(m):n=where(array(fre)[:,j]==max(array(fre)[:,j]))[0][0]data.append(n)clusters[n]['data'].append(dataset[j])print("一共有%d个簇心"%len(set(data)))#print(clusters)#print(data)returnclustersdefplot(self,dataset,clust):colors=10*['r','g','b','k','y','orange','purple']plt.figure(figsize=(5,5))plt.xlim((-8,8))plt.ylim((-8,8))plt.scatter(dataset[:,0],dataset[:,1],s=20)theta=linspace(0,2*pi,800)foriinrange(len(clust)):cluster=clust[i]data=array(cluster['data'])iflen(data):plt.scatter(data[:,0],data[:,1],color=colors[i],s=20)centroid=cluster['centroid'].tolist()[0]plt.scatter(centroid[0],centroid[1],color=colors[i],marker='x',s=30)x,y=cos(theta)*self.bandwidth+centroid[0],sin(theta)*self.bandwidth+centroid[1]plt.plot(x,y,linewidth=1,color=colors[i])plt.show()defmean_shift_train(self):dataset,classlable=self.load_data()m=shape(dataset)[0]clusters=[]foriinrange(m):max_distance=infcluster_centroid=dataset[i]#print(cluster_centroid)cluster_frequency=zeros((m,1))whilemax_distance>self.mindistance:w,cluster_frequency=self.shift_point(cluster_centroid,dataset,cluster_frequency)dis=self.distance(cluster_centroid,w)ifdis<max_distance:max_distance=dis#print(max_distance)cluster_centroid=whas_same_cluster=Falseforclusterinclusters:ifself.distance(cluster['centroid'],cluster_centroid)<self.cudistance:cluster['frequnecy']=cluster['frequnecy']+cluster_frequencyhas_same_cluster=Truebreakifnothas_same_cluster:clusters.append({'frequnecy':cluster_frequency,'centroid':cluster_centroid})clusters=self.group2(dataset,clusters,m)print(clusters)self.plot(dataset,clusters)if__name__=="__main__":shift=mean_shift()shift.mean_shift_train()获得的结果图如下。
之后还不会详尽讲解K-means聚类以及DBSCAN聚类,若无注目。
本文来源:凯发一触即发(中国区)官方网站-www.0739web.com