fcm算法的MATLAB實現

fcm算法

分析:

1.算法中包含的參數:
a.模糊因子expo(expo>1)
b.最大迭代次數max_t
c.迭代終止條件ε

2.算法中包含的過程:
a.目標函數
b.歐式距離
c.隸屬矩陣
d.聚類中心
e.迭代過程

還有  不要忘記!!初始化!!

3.實現代碼過程中需要寫成子函數的部分:
a.初始化函數initfcm() (主要實現隸屬度矩陣的初始化)
b.一次聚類過程stepfcm()(包含目標函數,隸屬矩陣的計算等等)
c.距離函數distfcm()
d.畫圖函數plotfcm()


代碼實現:

· 函數定義–左邊是輸出參數,右邊是函數名以及輸入參數

主函數:

function[center, U, obj_fcn] = fcm_final(data,c,options)
% 輸入:
% data 數據集 n行m列,n爲樣本數據數,m爲數據的特徵數
% c 聚類中心的個數
%options(1): 隸屬度矩陣U的指數expo,>1(缺省值: 2.0)
%options(2): 最大迭代次數max_t(缺省值: 100)
%options(3): 隸屬度最小變化量e,迭代終止條件(缺省值: 1e-5)
%options(4): 每次迭代是否輸出信息標誌(缺省值: 1)
% 輸出:
% U 隸屬度矩陣
% center 聚類中心
% obj_fcn 目標函數

% 判斷輸入參數的個數只能是2個或者3個
if nargin ~= 2 && nargin ~= 3
    error('Too many or too few input argument! ');
end
data_n = size(data, 1);% 求數據的行,即樣本個數
data_m = size(data, 2);% 求數據的列,即特徵個數

% 默認操作參數
default_options = [2; 100; 1e-5; 1];

% 如果輸入參數個數爲2,調用默認的options參數
if nargin == 2,
    options = default_options;
else % 分析有options做參數的情況:
     % 用戶在輸入options參數時需注意,如果options參數的個數少於4個,則未輸入參數的對應位置用nan來代替,這樣可以保證未輸入參數採用的是默認值,否則可能會出現前面參數佔用後面參數的值的情況,從而影響聚類效果。
    if length(options) < 4,
        temp = default_options;
        temp(1:length(options)) = options;
        options = temp;
    end
    % 返回options中值爲NaN的索引位置
    nan_index = find(isnan(options) == 1);
    % 將default_options中對應位置的參數值付給options中值爲NaN的值
    options(nan_index) = default_options(nan_index);
    if options(1) <= 1,% 模糊因子是大於1的數
        error('The exponent should be greater than 1 !');
    end

end

% 將options中的分量分別複製給四個變量
expo = options(1);%模糊因子m
max_t = options(2);% 最大迭代次數
e = options(3);%迭代終止條件
display = options(4);%輸出信息

% 目標函數初始化
obj_fcn = zeros(max_t, 1);
U = initfcm(c, data_n);
% 初始化模糊分配矩陣,使U滿足列上相加值爲1

% 主要循環
for i = 1 : max_t
    % 在第k步循環中改變聚類中心center和隸屬矩陣U
    [U, center, obj_fcn(i)] = stepfcm(data, U, c, expo);
    if display,
        fprintf('FCM:Iteration count = %d, obj_fcn = %f\n',i,obj_fcn(i));
        plotfcm(data,center,U,obj_fcn);
    end

    %迭代終止條件的判斷
    if i > 1,
        if abs(obj_fcn(i) - obj_fcn(i-1)) < e,
            break;
        end
    end

end

% 實際迭代次數
iter_n = i;
% 清除迭代次數之後的值
obj_fcn(iter_n + 1 : max_t) = [];
end


% 初始化fcm的隸屬度函數矩陣,滿足列向量之和爲1

子函數:

1.初始化函數initfcm()

% U--> c * n(c行n列) ,c爲聚類數, n爲樣本數
%% 初始化隸屬矩陣時需要已知矩陣的行和列,因此輸入應該爲該矩陣的行和列

% 輸入: c, data_n
% data_n  數據集data所含的樣本數
% c       這組數據的聚類數
% 輸出:U(初始化之後的隸屬矩陣)

function[U] = initfcm(c, data_n)

% 初始化隸屬矩陣U:rand函數可產生在(0, 1)之間均勻分佈的隨機數組成的數組。
U = rand(c, data_n);    

%% 注意:隸屬矩陣在初始化時需滿足某數據j對各個聚類中心i(1<i<c)的隸屬度之和爲1.
%%% sum(U)是指對矩陣U進行縱向相加,即求每一列的和,結果是一個1行n列的矩陣。(sum函數後面參數不指定或指定爲1時均表示列相加)。

col_sum = sum(U);

U = U./col_sum(ones(c,1), : );

% col_sum(ones(cluster_n, 1),:)等效於ones(clusters_n,1)*col_sum
% 上述目的是將col_sum擴展成與U(c,data_n)大小相同的矩陣,然後進行對應元素的點除,使隸屬矩陣列項和爲1%% 這裏必須要多說一句,因爲我一開始死活不理解這一句怎麼能使得隸屬矩陣列項和爲1。建議可以用一組簡單的數據做嘗試,之後你會發現,它就是一道簡單的數學題!!

end

2.一次聚類過程stepfcm()

% 一次聚類包含的過程:
% % (1)計算聚類中心,(2)目標函數,(3)距離函數,(4)計算新的隸屬矩陣

% 輸入:data,U,c,expo(模糊因子)
% 輸出:U_new(新的隸屬矩陣),center(聚類中心),obj_fcn(目標函數)

function[U_new, center, obj_fcn] = stepfcm(data, U, c, expo)

% 對隸屬矩陣進行指數運算(加上模糊因子)
mf = U.^expo; % 隸屬矩陣模糊化
% 相當於一次性將所有聚類中心作爲一個矩陣計算出來
center = mf*data./((ones(size(data,2),1)*sum(mf'))');
dist = distfcm(center, data); % 計算距離矩陣
obj_fcn = sum(sum(dist.^2 * mf)); % 計算目標函數
temp = dist.^(-2/(expo-1));
U_new = temp./(ones(c,1)*sum(temp)); % 計算新的隸屬矩陣
end

3.距離函數distfcm()

% 輸入:data, center
% 輸出:out

function out = disfcm(center,data)
out = zeros(size(center, 1), size(data, 1)); % 對c行n列的距離輸出矩陣進行置零
% 循環,每循環一次計算所有樣本點到該聚類中心的距離
for k = 1:size(center, 1)
    out(k,:) = sqrt(sum(((data - ones(size(data,1),1)*center(k,:)).^2)',1));
end
end

4.畫圖函數plotfcm()


% 輸入:data, center, U, obj_fcn
% 對fcmdata.dat(MATLAB自帶的聚類數據集,有兩個類)進行聚類

function plotfcm(data,center,U,obj_fcn)

figure(1)
subplot(2,1,1);
plot(U(1,:),'-b');
title('隸屬度矩陣值')
ylabel('第一類')
subplot(2,1,2);
plot(U(2,:),'-r');
ylabel('第二類')
xlabel('樣本數')

figure(2)
grid on
plot(obj_fcn);
title('目標函數變化值');
xlabel('迭代次數')
ylabel('目標函數值')

figure(3)
title('聚類圖像');
plot(data(:,1),data(:,2),'*r');
maxU = max(U);
index1 = find(U(1,:)==maxU);
index2 = find(U(2,:)==maxU);
plot(data(index1,1),data(index1,2),'*g');
hold on
plot(data(index2,1),data(index2,2),'*r');
plot(center(1,1),center(1,2),'oy','Markersize',5,'linewidth',3)
plot(center(2,1),center(2,2),'ob','Markersize',5,'linewidth',3)
hold off;
end

聚類結果

這裏寫圖片描述

收穫心得

%% 由於具有4個特徵值的鳶尾花數據集是四維的,無法在圖像中展示,可採用兩兩比對的方式展現。
%% 代碼中的隸屬度矩陣啊聚類中心啊目標函數啊等等這些表示實際上都是將算法中的數學計算式轉化成矩陣問題,要注意理解。

發佈了31 篇原創文章 · 獲贊 222 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章