XMeans聚类算法

参考博客:

https://blog.csdn.net/quiet_girl/article/details/79553898

https://blog.csdn.net/luman1991/article/details/79340381

K-means的缺点

  • 每一轮迭代的计算花费大
  • 需要用户指定K
  • 易于收敛到局部最优解

X-means的改进

  • 使用kd-tree加速原K-means的每一轮迭代
  • 用户指定K所属的范围,根据BIC score选到最优K
  • 每一轮迭代只进行2-means(2-means对局部最优解不敏感)

X-means算法步骤

算法


用户输入 kminkmin, kmaxkmax,数据集 DD 
1、运行Kmin−meansKmin−means。 
2、在每个聚类上,运行2-means。 
3、根据BIC score(只在该聚类上计算,即只计算本聚类数据只分成1类和两类时的BIC score)决定是否二分聚类。 
4、如果K


样例 
1、首先将DD分成3个聚类 
2、再将每个子聚类分成2个聚类 
3、计算BIC score决定是否二分 
XMeans聚类算法_第1张图片

BIC score(Bayesian Information Criterion)

  • BIC(ϕ)=lϕ^(D)−pϕ2⋅logRBIC(ϕ)=lϕ^(D)−pϕ2⋅logR 
    其中ϕϕ表示模型,lϕ^(D)lϕ^(D)为likelihood,pϕpϕ为模型的复杂度(自由参数个数)
  • X-means的假设:identical spherical assumption 
    数据由XX个高斯函数产生,每个高斯函数有一样的方差σσ(每个维度上的变量不相关,协方差矩阵为diag(σ))、不同的μiμi; 
    数据生成时,根据概率pipi选择一个高斯函数gigi,然后生成一个点。 
    所以似然函数为: 
    lϕ(D)=∑Ri=1[logp(g(i))+logp(xi)]lϕ(D)=∑i=1R[logp(g(i))+logp(xi)] 
    其中p(g(i))p(g(i))为生成点xixi的高斯函数被选到的概率。
  • 计算BIC,需要计算最大化的lϕ^(D)lϕ^(D),所以需要对参数进行估计 
    p(gk)=RkRp(gk)=RkR 
    σ2=1MR∑Kk=1∑xi∈Dk∥xi−μk∥∥2σ2=1MR∑k=1K∑xi∈Dk∥xi−μk∥2 
    文中使用无偏估计,即σ2=1M(R−K)∑Kk=1∑xi∈Dk∥xi−μk∥∥2σ2=1M(R−K)∑k=1K∑xi∈Dk∥xi−μk∥2
  • pϕpϕ自由参数个数 
    K-1个高斯函数选择到的概率,MK 个每个高斯函数每个维度上的mean,1个方差 
    所以pϕ=(M+1)Kpϕ=(M+1)K

Python代码:能力有限,如有不足请批评指正

#coding=utf-8
from sklearn.cluster import KMeans
from sklearn import datasets 
import numpy as np
import math


def mykmeans(data,target,k,iteration,):
	'''
	Parameters
	----------
	data: array or sparse matrix, shape (n_samples, n_features)
	target: 样本标签,shape(1,n_samples)
	k: cludter number
	iteration: 聚类最大循环次数

	return
	----------
	result: 聚类结果和集群的失真
	'''
	model = KMeans(n_clusters = k, n_jobs = 4, max_iter = iteration) #分为k类, 并发数4
	model.fit(data) #开始聚类
	#聚类结果
	labels=model.labels_
	centers=model.cluster_centers_
	distortion=model.inertia_
	clusters={}
	for i in range(k):
		clusters[i]={}
		clusters[i]['target']=[]
		clusters[i]['data']=[]
		clusters[i]['cluster_centers']=centers[i]
	for i in range(len(labels)):
		clusters[labels[i]]['target'].append(target[i])
		clusters[labels[i]]['data'].append(data[i])
	result={}
	result['clusters']=clusters
	result['distortion']=distortion
	return result

def oldbic(n,d,distortion):
	'''
	Parameters
	----------
	n: 样本总数量
	d: 样本维度
	distortion: 集群失真

	return
	----------
	L: BIC 分数
	'''
	variance = distortion / (n - 1)
	p1=-n*math.log(math.pi*2)
	p2=-n*d*math.log(variance)
	p3=-(n - 1)
	L=(p1 + p2 + p3) / 2
	numParameters = d + 1
	return L - 0.5 * numParameters * math.log(n)

def newbic(k,n,d,distortion,clustersSize):
	'''
	Parameters
	----------
	k: 聚类数量
	n: 样本总数量
	d: 样本维度
	distortion: 集群失真
	clustersSize: 每个聚类的样本数量 shape(1,k)

	return
	----------
	L: BIC 分数
	'''
	variance = distortion / (n - k);
	L = 0.0;
	for i in range(k):
		L += logLikelihood(k, n, clustersSize[i], d, variance)
	numParameters = k + k * d;
	return L - 0.5 * numParameters * math.log(n);

def logLikelihood(k,n,ni,d,variance):
	'''
	Parameters
	----------
	k: 聚类数量
	n: 样本总数量
	ni: 属于此聚类的样本数
	d: 样本维度
	variance: 集群的估计方差

	return
	----------
	loglike: 后验概率估计值
	'''
	p1 = -ni *math.log(math.pi*2);
	p2 = -ni * d * math.log(variance);
	p3 = -(ni - k);
	p4 = ni * math.log(ni);
	p5 = -ni * math.log(n);
	loglike = (p1 + p2 + p3) / 2 + p4 + p5;
	return loglike;

def myxmeans(data,target,kmin,kmax):
	'''
	Parameters
	----------
	data: array or sparse matrix, shape (n_samples, n_features)
	target: 样本标签,shape(1,n_samples)
	k: cludter number
	iteration: 聚类最大循环次数

	return
	----------
	result: 聚类结果和集群的失真
	'''
	d=len(data[0])
	k=kmin
	iteration=400
	init_clusters=mykmeans(data, target, k, iteration)
	while koldbicscore:
				split2cluster[i]=my2means
		for key in split2cluster.keys():
			init_clusters['clusters'][key]=split2cluster[key]['clusters'][0]
			init_clusters['clusters'][k]=split2cluster[key]['clusters'][1]
			k+=1
		if split2cluster=={}:
			break
	return init_clusters

if __name__=='__main__':
	iris=datasets.load_iris()
	data=iris.data
	target=list(range(len(data)))
	# data=np.random.random((100,50))
	# target=list(range(0,100))
	xmeans_result=myxmeans(data, target, 10, 20)
	for key in xmeans_result['clusters'].keys():
		print('----------------',key,'------------------')
		print(xmeans_result['clusters'][key]['target'],'\n')













 

你可能感兴趣的:(机器学习)