FCM算法的matlab实现(Fuzzy C-means 算法)
FCM算法是一种基于模糊聚类的划分式聚类方法,用于将数据集划分为多个模糊类。其核心思想是通过模糊隶属度矩阵来表示样本对各类的归属程度,而非严格属于某一类别。算法通过迭代优化隶属度矩阵和聚类中心,使得目标函数(样本到聚类中心的加权距离平方和)逐步减小,最终收敛到最优解。
FCM算法的实现主要包括以下几个步骤:
初始化模糊隶属度矩阵,通常采用随机生成的方法,并进行归一化处理。
计算聚类中心,通过模糊隶属度矩阵和样本数据更新聚类中心。
计算样本到聚类中心的距离,并更新模糊隶属度矩阵。
重复上述步骤,直到目标函数值收敛或达到最大迭代次数。
Matlab实现中,主函数FCMCluster负责调用初始化函数、距离计算函数和逐步聚类函数,完成整个聚类过程。通过设置不同的参数(如指数幂、最大迭代次数和收敛阈值),可以控制聚类的详细过程。运行结果表明,该算法能够有效划分数据集,并生成清晰的聚类图。
FCM算法
- FCM算法简介
- FCM算法原理
- FCM算法实现(matlab)
FCM算法简介
FCM算法归类于划分式聚类算法,通过模糊数学方法处理聚类问题。基于一个初始划分,算法需要预先设定聚类数目,并定义一个最优化聚类标准,即目标函数,作为衡量各类样本分布代价的函数。FCM算法将N个数据向量划分为C个模糊类,每个类的聚类中心代表该类。通过反复迭代计算,算法逐步减小目标函数的误差值,当目标函数收敛时,最终获得所需的聚类结果。
FCM算法原理
符号定义:
x_i代表第i个样本
N表示样本总数
l为样本的维度数
C代表样本的类别划分
V表示聚类中心
u_{ik}表示第i个数据点属于第k类的隶属度
d(x_i, v_k)表示第i个样本与第k个聚类中心的欧氏距离,即d(x_i, v_k) = \sqrt{\sum_{p=1}^{L} (x_{ip} - v_{kp})^2}。
FCM算法的目标函数定义为:
J_{FCM}(u,v)=\sum_{k=1}^C\sum_{i=1}^Nu_{ik}^md^2(x_i,v_k)
其中,隶属度的约束条件为:
\sum_{k=1}^Cu_{ik}=1 \quad (i=1,2,\dots,N)
将欧氏距离代入目标函数公式:
J_{FCM}(u,v)=\sum_{i=1}^N\sum_{k=1}^C(u_{ik}^2)\sum_{p=1}^L(x_{ip}-v_{kp})^2\quad (k\in\{1,2,\dots,C\})\quad (p\in\{1,2,\dots,L\})
对v_{kp}求偏导数,令其等于零,得:
\frac{\partial{J_{FCM}}}{\partial v_{kp}} =2\sum_{i=1}^N (u_{ik})^2(x_{ip}-v_{kp})=0
解得:
v_{kp}=\frac{\sum_{i=1}^N(u_{ik})^2x_{ip}}{\sum_{i=1}^N(u_{ik})^2}
构建拉格朗日函数:
J_{FCM}(u,v,\lambda)=\sum_{i=1}^N\sum_{k=1}^C(u_{ik})^{d^2(x_{i}-v_{k})}-\sum_{i=1}^N\lambda_i\left(\sum_{k=1}^Cu_{ik}-1\right)\quad (r\in\{1,2,\dots,N\},\ s\in\{1,2,\dots,C\})
对u_{rs}求偏导数,令其等于零,得:
\frac{\partial {J_{FCM}(u,v)}}{\partial u_{rs}}=2(u_{us}d^2(x_r-\lambda_r))=0
u_{rs}=\frac{\lambda_r}{2d^2{(x_r,v_s)}}
在约束条件下,我们有\sum_{k=1}^Cu_{rk}=1,由此可得:\sum_{k=1}^C\frac{\lambda_r}{2d^2(x_r,v_k)}=1,即:
\lambda_r=\frac{1}{\sum_{k=1}^C\frac{1}{2d^2(x_r,v_k)}}
将\lambda_r代入后可得:
v_k=\frac{\sum_{i=1}^N(u_{ik})^m x_i}{\sum_{i=1}^N(u_{ik})^m}
通过隶属度更新公式,我们得到:
u_{ik}=\frac{ \frac{1} {d^2(x_i,v_k)} }{{\sum_{r=1}^C }\frac{1} {d^2(x_i,v_r)}}
FCM算法实现(matlab)
该系统包含四个核心函数:
核心函数 FCM聚类算法.m
初始化模糊关系矩阵:initfcm.m
基于欧氏距离的相似度计算:distfcm.m
基于逐次优化的聚类方法:stepfcm.m
function [center,U,obj_fun]=FCMCluster(data,n,options)
% 采用模糊c均值聚类,将数据集分为n类
% data 数据集 n 类别数
% options 4*1 矩阵
% option(1):隶属度函数矩阵的加权指数,默认为2
% option(2):最大迭代次数,默认100次
% option(3):隶属度最小变化量,默认为1e-5
% option(4):每次迭代是否输出信息标志,默认输出,值为1
% center 聚类中心
% U 隶属度矩阵
% obj_fun 目标函数值
%确定或给定参数
if nargin~=2 && nargin ~=3
error('Too many ot too few input agruments');
end
%默认参数
default_options=[2;100;1e-5;1];
% 参数配置
if nargin==2
options=default_options;
else
if length(options)<4
tmp=default_options;
tmp(1:length(options))=options;
options=tmp;
end
nan_index=find(isnan(options)==1);
options(nan_index)=default_options(nan_index);
if options(1)<=1
error('The exponent should be greater than 1!');
end
end
%参量初始化
expo=options(1); %指数的次幂
max_iter=options(2); %最大迭代次数
min_impro=options(3); %精度
display=options(4); %是否显示最终函数值
obj_fun=zeros(max_iter,1); %储存聚类函数在每次迭代中的值
data_n=size(data,1); %行数,即样本个数
in_n=size(data,2); %样本的维数
U=initfcm(n,data_n); % 初始化模糊分配矩阵
% 主程序
for i=1:max_iter
[U,center,obj_fun(i)]=stepfcm(data,U,n,expo);
%显示聚类最终的函数值
if display
fprintf('FCM:Iteration count=%d,obj_fun=%f\n',i,obj_fun(i));
end
% 终止条件判断
if i>1
if abs(obj_fun(i)-obj_fun(i-1))<min_impro
break;
end
end
end
iter_n=i;
obj_fun(iter_n+1:max_iter)=[];
end
function U=initfcm(n,data_n)
%子函数 模糊矩阵初始化
% data_n 样本个数
% n 分类个数
% U(i,j) 第j个数据点属于第i个类的隶属度
%取随机矩阵,且进行归一化(即,列和为1)
U=rand(n,data_n);
col_sum=sum(U);
U=U./col_sum(ones(n,1),:);
end
function [U_new,center,obj_fun]=stepfcm(data,U,n,expo)
% 逐步聚类
%聚类中心
mf=(U.^expo);
center=mf*data./((ones(size(data,2),1)* sum(mf'))');
%聚类函数对应函数值
dist=distfcm(center,data);
obj_fun=sum( sum( (dist.^2).* mf) );
%更新隶属度矩阵
tmp=dist.^(-2/(expo-1));
U_new=tmp./(ones(n,1)*sum(tmp));
end
function out=distfcm(center,data)
% 计算样本到聚类中的距离,欧几里得距离
out = zeros(size(center,1),size(data,1));
for k=1:size(center,1)
out(k,:)=sqrt( sum(((data-ones(size(data,1),1) * center(k,:)).^2)',1));
end
end
下面利用随机生成的100个二维数据来对算法进行验证:
function fmean
clear,clc
close all
data=rand(100,2);
N=10;
[center,U,obj_fcn]=FCMCluster(data,N);
plot(data(:,1),data(:,2),'ro');
hold on
U_max=max(U);
for j=1:100
row(:,j)=find(U(:,j)==U_max(j)); %列数对应相应的数据位置,矩阵元素对应其类别
end
for i=1:N
col=find(row==i); %max(U)返回隶属度列最大值所在行一致的分为一类
plot(data(col,1),data(col,2),'*');
hold on
end
grid on
%画出聚类中心
plot(center(:,1),center(:,2),'p','color','m','MarkerSize',8);
end
运行的结果:

聚类图:

PS:如果有问题或疑问可以联系我。
