一:介绍
关于聚类分析算法,类型较多,用法也不同。先收集一些网上的相关博客,有兴趣可以看看:
1.聚类分析综述:http://blog.csdn.net/assiduousknight/article/details/16831965
2.这个博主整了个聚类分析系列,很好呀,原理介绍部分棒,部分程序是用Java语言写的,熟悉的可以看看。
贴其中一个索引:http://blog.csdn.net/zaozxueyuan/article/details/22613633
3.再收藏一个机器学习算法系列,当然里面有道关于K-均值算法。
贴其中一个索引:http://blog.csdn.net/qq415171148/article/details/25394477
二:关于聚类分析的动态聚类算法
下面的部分内容是看模式课程整理的:
2.1.思想: 一)选取K个样本作为聚类中心
二)按某种聚类准则(如:最小距离准则)使所有样本点都找到自己所 属的初始类
三)判断分类是否合理,不合理修改分类
四)反复迭代修改直至分类合理
2.常用方法:
● K-均值算法
● ISODATA算法(迭代自组织数据分析算法)(matlab实现书籍上有)
(有点复杂 --> 动态调整分类数目)
(这些算法,matlab都有自带的函数(还没用过!),当明白了算法的原理后,再去用这些函数应该很好)
2.2: K-均值算法 (--->一般使用在已知可以分成几类的情况下效果好)
思想:使聚类性能指标最小化,准则函数:每一个样本点到该类中心的 距离平方和 最小。
算法: 一)选K个聚类中心,Z(1)......Z(K)。 开始可以任意选。
(任意选,选取的准确度与先验知识等等有关,可以考虑)
二)逐个将需要分类的样本进行分类到K个初始类中的某一个 中,假设当i=j时,可以满足
, 那么x就属 于第Sj(k)个。
K:迭代次数,每个样本都得迭代K次才能判断出来那个是最近的。
Sj(k):第j个聚类,聚类中心为Z(j)
三)计算各个聚类中心的新的值,组成新的聚类中心向量。
N:该类中样本的个数
有了聚类中心向量,可以使用聚类准则函数使函数值最小:
(该步骤中要计算K个聚类的均值,所以叫K-均值)
比较: 若,则返回第二步继续迭代,所有 的模式样本重新分类。
(此时与上一回合变化的只是聚类中心点,这已经足够了)如果相等,那么很明显算法收敛了(没有改变了)。
讨论该算法:
K-均值受那些因素的影响:
● 所选的聚类数目(最直接的影响,所以说比较适合于已知类 别的分类)
● 聚类中心的初始分布
● 样本几何性质(越高维数据,计算量越大)
● 读入样本次序
进一步讨论方法:
● 试验中如果不知道分类数,那么可以试探不同的K值和不同 的聚类中心(可以随机产生初始聚类中心)。
● 模式样本本身类之间的差距大时,收敛性较好。
三:简易的matlab程序实现
根据上面的算法思路,编写matlab程序如下:
%--------------函数说明-------------
%-----简单的两类聚类分类问题
%---(模拟数据,已知类别数为2类,K-means在已知类别下使用较好)
%-----------------------------------
function mean = k_means_new
%%
%------------随机生成用于分类的10对坐标---
%--------------(必须具有一定的差异性)
for i=1:100
x1(i) = rand()*5; %人为保证差异性
y1(i) = rand()*5;
x2(i) = rand()*5 + 3; %人为保证差异性
y2(i) = rand()*5 + 3;
end
x = [x1,x2];
y = [y1,y2];
cities = [x;y];
% plot(cities(1,:),cities(2,:),'*'); %画出来
%%
%------------随机把其中两个点作为初始的聚类中心
num = size(cities,2); %样本个数
m1 = round(rand()*num); %随机选取两个当做初始聚类中心
m2 = round(rand()*num);
while m1==m2 %不能相同
m2 = round(rand()*num);
end
u1 = cities(:,m1);
u2 = cities(:,m2);
u_old = [u1,u2];
u_new = [u2,u1];
%%
while u_old ~= u_new %聚类中心没有变化时退出循环
u_old = u_new ; %更新聚类中心坐标
for j=1:num %对与每一个样本,找到对应的类
dis1 = norm(cities(:,j)-u1); %求距离,范数
dis2 = norm(cities(:,j)-u2);
if dis1>=dis2 c(j) = 2; %比较距离,划分类
else c(j) = 1;
end
end
index1 = find(c==1); %索引第一类
index2 = find(c==2); %...
sum1 = sum(cities(:,index1),2); %对第一类中的元素x,y分别求和
sum2 = sum(cities(:,index2),2); %...
u1 = sum1/length(index1); %对第一类平均,求取新的聚类中心
u2 = sum2/length(index2); %...
u_new = [u1,u2]; %新的聚类中心向量
end
%%
hold on,plot(cities(1,index1),cities(2,index1),'*'); %画出来
hold on,plot(cities(1,index2),cities(2,index2),'+');
hold on,plot(u1(1),u1(2),'o',u2(1),u2(2),'o');
mean = u_new;
直接运行函数就可以了,改变一下程序第二行的数字参数,使得初始生成的点个数不同,从而测试下效果:
初始点10个:
初始点20个:
初始点50个:
初始点100个:
实验了多次,看着都很准,基本上没有分错类的,可以看到K-均值对已知分类的问题效果确实还行。