優(yōu)化算法應(yīng)用(四)優(yōu)化聚類算法

一. 目標(biāo)描述

聚類算法是一類無(wú)監(jiān)督機(jī)器學(xué)習(xí)算法,即在使用該算法時(shí)不需要知道數(shù)據(jù)的標(biāo)簽,而是通過數(shù)據(jù)各個(gè)維度之間的某些特征對(duì)數(shù)據(jù)集進(jìn)行劃分。
  現(xiàn)在已有的聚類算法很多,劃分方式也多種多樣。這里主要是針對(duì)使用聚類中心來(lái)直接劃分聚類的算法進(jìn)行優(yōu)化,同時(shí)對(duì)不適用聚類中心直接劃分的聚類算法優(yōu)化方式進(jìn)行一個(gè)探究。
  將使用以下兩個(gè)聚類算法來(lái)進(jìn)行說(shuō)明。
  1. k均值聚類(k-means)
  2. 密度峰值聚類(dpc)

二. 優(yōu)化k均值聚類

1. K均值聚類簡(jiǎn)介

k-means中的k表示聚類中心數(shù),確定k后,其聚類過程如下?。?br>   (1). 群體中隨機(jī)設(shè)置k個(gè)聚類中心。
  (2). 所有個(gè)體自動(dòng)歸類為距自己最近的中心。
 ?。?). 更新聚類中心為該聚類的重心。
 ?。?). 直到聚類中心不再變動(dòng),否則跳至步驟2。
 ?。?). 輸出4中得到的聚類中心所劃分的聚類。



  k-means的聚類過程比較簡(jiǎn)潔,也容易實(shí)現(xiàn),只是對(duì)初始化的中心比較敏感,初始位置較差時(shí),容易陷入局部最優(yōu)。同時(shí)還有循環(huán)中心的問題,即通過T代聚類中心劃分的聚類計(jì)算除了T+1代聚類中心,通過T+1代聚類中心劃分的聚類計(jì)算出了T+2代聚類中心,但是T代與T+1代聚類中心不同,T代與T+1代聚類中心相同。
  使用優(yōu)化算法來(lái)確定聚類中心大致是解決了上述兩個(gè)問題。
  優(yōu)化算法中的一個(gè)個(gè)體表示聚類算法中的一組聚類中心。優(yōu)化算法中的適應(yīng)度函數(shù)可以通過計(jì)算各個(gè)數(shù)據(jù)到其聚類中心的距離和來(lái)計(jì)算,并求其最小值??梢院?jiǎn)單描述為使用優(yōu)化算法找到一組聚類中心,使所有數(shù)據(jù)與其相對(duì)應(yīng)的聚類中心的距離之和最小。
  如k=3,數(shù)據(jù)維度為2,數(shù)據(jù)數(shù)量為n,為(a,b),中心為(x,y),距離使用歐式距離進(jìn)行計(jì)算,則適應(yīng)度函數(shù)計(jì)算如下:


  其中n1+n2+n3=n,表示劃分聚類后的各類數(shù)據(jù)。

2. 代碼實(shí)現(xiàn)

文件名 ..\optimization algorithm\application_kmeans\Kmeans_Model.m
  該類未實(shí)現(xiàn)原k-means算法迭代過程,如有需要可自行實(shí)現(xiàn)。

% k-means 模型
classdef Kmeans_Model < handle
    
    properties
        % 聚類數(shù)量,默認(rèn)2個(gè)
        k = 2;
        
        % 數(shù)據(jù)維度,默認(rèn)為2
        dim = 2;
        
        % 數(shù)據(jù)集m行*n列的矩陣,n = dim
        dataset = [];
        
        % 每一維度的取值范圍上下界
        bound_up = [];
        bound_low = [];
    end
    
    methods
        % 構(gòu)造函數(shù)
        function self = Kmeans_Model(data)
            self.dataset = data;
            self.bound_up = zeros(1,self.dim);
            self.bound_low = zeros(1,self.dim);
            for i = 1:self.dim
                self.bound_up(i) = max(self.dataset(:,i));
                self.bound_low(i) = min(self.dataset(:,i));
            end
        end
        
        % 輸入為向量,輸出為適應(yīng)度值
        function value = fit_function(self,x) 
            % 將向量x,轉(zhuǎn)化為數(shù)個(gè)點(diǎn)坐標(biāo)
            point_list = self.get_point_from_vector(x);
            value = 0;
            % 遍歷所有樣本,求其到最近的聚類中心的距離和
            for i = 1:length(self.dataset)
                [dist,id] = self.get_distance(self.dataset(i,:),point_list);
                value = value + dist;
            end
        end
        
        % 計(jì)算樣本到各中心的最小距離,默認(rèn)為歐式距離
        function [dist_min,id] = get_distance(self,pos,point_list)
            dist_min = realmax('double');
            id = 1;
            % 返回到最近的中心的距離和中心id
            for i = 1:self.k
                dist = sqrt(sum((pos-point_list(i,:)).^2));
                if dist < dist_min
                    dist_min = dist;
                    id = i;
                end
            end
        end
        
        % 從輸入的向量中獲取點(diǎn)的坐標(biāo)
        function point_list = get_point_from_vector(self,x)
            point_list = [];
            for i = 1:(length(x)/self.dim)
                % x中相鄰數(shù)個(gè)值組成一個(gè)點(diǎn)
                point = x((i-1)*self.dim+1:i*self.dim);
                % 將該點(diǎn)加入列表
                point_list = [point_list;point];
            end
        end
            
        % 繪圖,num為圖片編號(hào)
        function draw(self,input,num)    
            set(gca,'XLim',[self.bound_low(1) self.bound_up(1)]);
            set(gca,'YLim',[self.bound_low(2) self.bound_up(2)]);
            
            % 沒有數(shù)據(jù)則繪制數(shù)據(jù)點(diǎn)
            if isempty(input)
                for i = 1:length(self.dataset)
                    scatter(self.dataset(i,1),self.dataset(i,2),10,'b','filled');
                    hold on;
                end
                return;
            end
            
            % 有數(shù)據(jù)則繪制各數(shù)據(jù)點(diǎn)屬于哪個(gè)聚類中心
            point_list = self.get_point_from_vector(input);
            color_list = linspace(1,10,self.k);
            % 按照x坐標(biāo),從小到大排序
            [value,index] = sort([point_list(:,1)]);
            
            % 繪制數(shù)據(jù)點(diǎn)
            for i = 1:length(self.dataset)
                data = self.dataset(i,:);
                [dist,id] = self.get_distance(data,point_list);
                center_id = find(index==id,1);
                color = color_list(center_id);
                scatter(data(1),data(2),10,color,'filled','MarkerEdgeColor','k');
                hold on;
            end
            
            % 繪制聚類中心
            for i = 1:self.k
                center_id = find(index==i,1);
                color = color_list(center_id);
                scatter(point_list(i,1),point_list(i,2),100,color,'h','filled','MarkerEdgeColor','k');
                hold on;
            end
            
            text(self.bound_up(1)*0.9+self.bound_low(1)*0.1,self.bound_up(2)*0.9+self.bound_low(2)*0.1,num2str(num),'FontSize',20);
            axis square;
        end
        
    end
end
  1. 測(cè)試代碼
    文件名 ..\optimization algorithm\application_kmeans\Test.m
%% 清理之前的數(shù)據(jù)
% 清除所有數(shù)據(jù)
clear all;
% 清除窗口輸出
clc;

%% 隨機(jī)生成數(shù)據(jù)集

a = unifrnd(-pi,pi,100,1);
ra = unifrnd(0,10,100,1);
b = unifrnd(-pi,pi,100,1);
rb = unifrnd(0,5,100,1);

c = unifrnd(-pi,pi,100,1);
rc = unifrnd(0,6,100,1);

data = [
    sin(a(:)).*ra(:)+10,cos(a(:)).*ra(:)+10;
    sin(b(:)).*rb(:)-10,cos(b(:)).*rb(:)+5;
    sin(c(:)).*rc(:),cos(c(:)).*rc(:);
    ];


model = Kmeans_Model(data);
model.k = 3;

% 獲取每一維的取值范圍
range_max = repmat(model.bound_up,1, model.k);
range_max = reshape(range_max, 1, numel(range_max));
range_min = repmat(model.bound_low, 1,model.k);
range_min = reshape(range_min, 1, numel(range_min));

%% 添加目錄
% 將上級(jí)目錄中的frame文件夾加入路徑
addpath('../frame')
% 引入差分進(jìn)化算法
addpath('../algorithm_differential_evolution')
%% 算法實(shí)例
dim = model.dim*model.k;
% 種群數(shù)量
size = 50;
% 最大迭代次數(shù)
iter_max = 100;
% 取值范圍上界
range_max_list = range_max;
% 取值范圍下界
range_min_list = range_min;
% 實(shí)例化差分進(jìn)化算法類
base = DE_Impl(dim,size,iter_max,range_min_list,range_max_list);
base.is_cal_max = false;
% 確定適應(yīng)度函數(shù)
base.fitfunction = @model.fit_function;
% 運(yùn)行
base.run();
disp(['復(fù)雜度',num2str(base.cal_fit_num)]);

%% 下面繪制動(dòng)態(tài)圖
% 繪制每一代的路徑
for i = 1:length(base.position_best_history)
    model.draw(base.position_best_history(i,:),i);
    % 每0.01繪制一次
    pause = 0.01;
    %下面是保存為GIF的程序
    frame=getframe(gcf);
    % 返回單幀顏色圖像
    imind=frame2im(frame);
    % 顏色轉(zhuǎn)換
    [imind,cm] = rgb2ind(imind,256);
    filename = ['kmeans_',num2str(model.k),'.gif'];
    if i==1
         imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',1e-4);
    else
         imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',pause);
    end

    if i <length(base.position_best_history)
        % 如果不是最后一張圖就清除窗口
        clf;
    end
end

運(yùn)行效果如下:

三. 優(yōu)化密度峰值聚類

1. 密度峰值聚類簡(jiǎn)介

密度峰值聚類是通過定義和計(jì)算數(shù)據(jù)的密度來(lái)進(jìn)行聚類的。其具體實(shí)現(xiàn)步驟如下:
(1) 確定密度計(jì)算半徑dc
半徑dc(或者截距)是一個(gè)經(jīng)驗(yàn)值,需要手動(dòng)輸入,后面將使用優(yōu)化算法計(jì)算。
(2) 計(jì)算所有數(shù)據(jù)的密度
在該數(shù)據(jù)半徑dc范圍內(nèi)的數(shù)據(jù)數(shù)量稱為該數(shù)據(jù)的密度。


  如圖,當(dāng)dc=1時(shí)A的密度為2(半徑內(nèi)有B,C),當(dāng)dc=2時(shí),A的密度為3(半徑內(nèi)有B,C,D)。
  密度rho可表示為


  其中num(dist<dc)表示距離小于dc的數(shù)據(jù)個(gè)數(shù)。
  從上述公式可知,rho將會(huì)是一個(gè)正整數(shù),為了讓密度更加有區(qū)分度,我們可以在上面密度的基礎(chǔ)上加上dc范圍內(nèi)最遠(yuǎn)點(diǎn)距離與dc的比值:


  使用公式(2)計(jì)算當(dāng)dc = 1時(shí),可得出,A的密度為2,當(dāng)dc=1.5時(shí), A的密度依然為2。
  使用公式(3)時(shí),當(dāng)dc =1時(shí),A的密度=2+1/1=3,當(dāng)dc = 1.5時(shí),A的密度=2+1/1.5=8/3;當(dāng)dc = 2時(shí)A的密度=3+2/2=4,當(dāng)dc=100時(shí),A的密度=3+2/100=3.02??梢钥闯?,使用公式(3)時(shí),密度不在一定是一個(gè)整數(shù),它會(huì)隨著dc的大小有著一定變化。
(3) 計(jì)算相對(duì)距離
  密度最大的點(diǎn)的相對(duì)距離delta為它到最遠(yuǎn)點(diǎn)的距離。
  其他點(diǎn)的相對(duì)距離delta為到密度大于自己的點(diǎn)的最近距離。
(4) 確定聚類中心
  一般的,將選取密度和相對(duì)距離均較大的點(diǎn)作為聚類中心??梢酝ㄟ^計(jì)算rho*delta的值來(lái)確定,將離群較遠(yuǎn)的點(diǎn)作為聚類中心。
(5) 劃分聚類
  如果該點(diǎn)不是(4)中的聚類中心,那么它的父節(jié)點(diǎn)是密度大于自己且距離自己最近的點(diǎn)。
  如1-10個(gè)點(diǎn),1,4為聚類中心,劃分聚類的結(jié)果如下

節(jié)點(diǎn) 父節(jié)點(diǎn)
1 無(wú)
2 5
3 2
4 無(wú)
5 4
6 1
7 10
8 1
9 7
10 7

(6) 遞歸合并
  遍歷各個(gè)節(jié)點(diǎn)將其賦給其父節(jié)點(diǎn),直至父節(jié)點(diǎn)為聚類中心

節(jié)點(diǎn) 父節(jié)點(diǎn) 聚類鏈 聚類中心
1 無(wú) 無(wú) 1
2 5 2-5-4 4
3 2 3-2-5-4 4
4 無(wú) 無(wú) 4
5 4 5-4 4
6 1 6-1 1
7 10 7-10-1 1
8 1 8-1 1
9 7 9-7-10-1 1
10 1 10-1 1

2. 適應(yīng)度函數(shù)設(shè)計(jì)

個(gè)人的思考,無(wú)嚴(yán)格證明,僅供參考。
  從密度峰值聚類流程可以看出,過程中有兩個(gè)需要手動(dòng)確定的步驟:dc的值,聚類中心的數(shù)量。只要確定了這兩個(gè)值,就能確定聚類的劃分情況,所以適應(yīng)度函數(shù)的輸入定為dc和聚類數(shù)量。
  輸入已經(jīng)確定,下面就要思考適應(yīng)度輸出的計(jì)算了。
思路1:輸出為各類之間最近距離,使該值最大化,即各類之間的最近距離越大越好。
  這是一個(gè)不錯(cuò)的值,當(dāng)聚類中心數(shù)為2時(shí),效果很好,但是使用該值時(shí),計(jì)算得出的聚類中心數(shù)也必定是2。


  如圖,A,B,C表示三個(gè)聚類中距離其他類最近的點(diǎn)(A類中距B類最近的點(diǎn)和距C類最近的點(diǎn)不一定重合,假設(shè)重合,方便說(shuō)明)。當(dāng)分3類(正解)時(shí),可知最近距離的分別為0.5,1,1.2。故最近距離的最小值為0.5。此時(shí)分2類時(shí)會(huì)出現(xiàn)將AB劃分為一類的情況,該情況下,最近距離變?yōu)榱?。

思路2:計(jì)算各類到其他類的最近距離之和,使其最大化,同樣是希望各類之間的距離越大越好。


  此時(shí)會(huì)出現(xiàn)另一種情況,會(huì)產(chǎn)生無(wú)數(shù)距離很接近的聚類劃分。如上圖,按照3類劃分為A,B,C,在此規(guī)則下C類分裂為了 CDEF。
  劃分3類時(shí),計(jì)算適應(yīng)度函數(shù)為AB+AB+AC=2。分裂后適應(yīng)度函數(shù)為 AB+AB+ CD+CD+CF+EF=2.2。此時(shí)聚類中心的數(shù)量會(huì)非常的多,聚類過度劃分。

思路3:在思路2的基礎(chǔ)上,計(jì)算最近距離時(shí)減去半徑作為結(jié)果。
  上圖中,假設(shè)半徑dc為0.1,那么聚類中心數(shù)為3時(shí),適應(yīng)度函數(shù)AB+BC+AC-dc3=1.7,劃分為6類時(shí)AB+AB+ CD+CD+CF+EF-60.1=1.6。
  計(jì)算距離時(shí)減去dc的主要目的是防止聚類過于集中,當(dāng)聚類很集中時(shí),其計(jì)算的最近距離可能為負(fù)數(shù),同時(shí)也會(huì)讓dc取較小值。
  為了保證dc的值不會(huì)過大或者過小,并使所有個(gè)體的密度不為0(極端dc=0的情況),同時(shí)所有個(gè)體的密度不全為數(shù)據(jù)總數(shù)(極端為dc=正無(wú)窮),dc的取值范圍將設(shè)置為:數(shù)據(jù)點(diǎn)距其他點(diǎn)最近距離的最大值——數(shù)據(jù)點(diǎn)距其他店最遠(yuǎn)距離的最小值

3.代碼實(shí)現(xiàn)

文件名:..\optimization algorithm\application_dpc\DPC_Model.m

% dpc 模型
classdef DPC_Model < handle
    
    properties
        % 數(shù)據(jù)維度
        dim = 2;
        
        % 數(shù)據(jù)集m行*n列的矩陣,n = dim
        dataset = [];
        
        % 距離矩陣,為n*n的方陣,n = dataset的長(zhǎng)度
        dist_mat=[];
        
        % 局部密度矩陣,為(1行*n列)的矩陣,n = dataset的長(zhǎng)度
        rho_mat=[];
        
        % 相對(duì)距離矩陣,為(1行*n列)的矩陣,n = dataset的長(zhǎng)度
        delta_mat=[];
        
        % 記錄各個(gè)數(shù)據(jù)的父類id,為(1行*n列)的矩陣,n = dataset的長(zhǎng)度
        members_parent_id=[];
        
        % 記錄各個(gè)數(shù)據(jù)的聚類中心id,為(1行*n列)的矩陣,n = dataset的長(zhǎng)度
        members_center_index=[];
        
        center_num = 2;
        
        dc = 1;
        
        % 各聚類中心的id
        center_ids = [];
        
        % 每一維度的取值范圍上下界
        bound_up = [];
        bound_low = [];
    end
    
    methods
        % 構(gòu)造函數(shù)
        function self = DPC_Model(data)
            self.dataset = data;
            self.bound_up = zeros(1,self.dim);
            self.bound_low = zeros(1,self.dim);
            for i = 1:self.dim
                self.bound_up(i) = max(self.dataset(:,i));
                self.bound_low(i) = min(self.dataset(:,i));
            end
            % 初始化距離方陣
            self.dist_mat = zeros(length(self.dataset));
            % 計(jì)算距離矩陣
            self.cal_dist_mat();
            self.init();
        end
        
        % 初始化數(shù)據(jù)
        function init(self)
            self.delta_mat = zeros(1,length(self.dataset));
            % 取出聚類中心在樣本中的id
            self.center_ids = ones(1,self.center_num);
            self.members_parent_id = zeros(1,length(self.dataset));
            self.members_center_index = zeros(1,length(self.dataset));

        end
        
        % 計(jì)算dc的取值范圍:最近距離的最大值--最遠(yuǎn)距離的最小值
        function [min_dc,max_dc]=get_dc_range(self)
            % 求距離矩陣中每一行的最小值
            % 將對(duì)角線設(shè)置為最大,方便求最小值
            self.dist_mat(logical(eye(size(self.dist_mat)))) = realmax('double');
            % 計(jì)算每一行的最小值
            [dist_min,index_min] = min(self.dist_mat,[],2);
            % 計(jì)算最小值中的最大值
            min_dc = max(dist_min);
            % 將對(duì)角線設(shè)置為0,方便求最大值
            self.dist_mat(logical(eye(size(self.dist_mat)))) = 0;
            % 計(jì)算每一行的最大值
            [dist_max,index_max] = max(self.dist_mat,[],2);
            % 計(jì)算最大值中的最小值
            max_dc = min(dist_max);
        end
        
        % 輸入為向量,輸出為適應(yīng)度值
        function value = fit_function(self,x) 
            % 第一維作為截距
            self.dc = x(1);
            % 第二維向下取整作為聚類數(shù)
            self.center_num = floor(x(2));
            % 初始化數(shù)據(jù)
            self.init();

            % 計(jì)算密度矩陣
            self.cal_rho_mat();
            % 計(jì)算相對(duì)距離矩陣
            self.cal_delta_mat();
            % 聚類
            self.cluster();
            % 計(jì)算適應(yīng)度值
            dist_min = self.get_dist_min();
            value = dist_min-self.dc*self.center_num;
        end
        
        % 繪圖
        function draw(self)    
            set(gca,'XLim',[self.bound_low(1) self.bound_up(1)]);
            set(gca,'YLim',[self.bound_low(2) self.bound_up(2)]);
            color_list = linspace(1,10,self.center_num);
            
            % 繪制數(shù)據(jù)點(diǎn)
            for i = 1:length(self.dataset)
                data = self.dataset(i,:);
                center_index = self.members_center_index(i);

                color = color_list(center_index);
                scatter(data(1),data(2),10,color,'filled','MarkerEdgeColor','k');
                hold on;
            end
            for i = 1:self.center_num
                scatter(self.dataset(self.center_ids(i),1),self.dataset(self.center_ids(i),2),40,'r','filled','MarkerEdgeColor','k');
                hold on;
            end
            
            axis square;
        end
    end
    
    % 受保護(hù)的方法,繼承用
    methods (Access = protected)
        % 計(jì)算樣本到之間距離,默認(rèn)為歐式距離
        function cal_dist_mat(self)
            
            for i = 1:length(self.dataset)
                for j = i+1:length(self.dataset)
                    % 計(jì)算各個(gè)數(shù)據(jù)之間的歐式距離
                    dist = sqrt(sum((self.dataset(i,:)-self.dataset(j,:)).^2));
                    self.dist_mat(i,j) = dist;
                    self.dist_mat(j,i) = dist;
                end
            end
        end
        
        % 計(jì)算局部密度矩陣
        function cal_rho_mat(self)
            % 計(jì)算距離小于截距的點(diǎn)的數(shù)量
            a = self.dist_mat < self.dc;
            self.rho_mat = sum(a);
            max_dist = zeros(1,length(self.dataset));
            for i = 1:length(self.dataset)
                max_dist(i) = max(self.dist_mat(i,a(i,:)));
            end
            self.rho_mat = self.rho_mat+max_dist/self.dc;
        end
        
        % 計(jì)算相對(duì)距離矩陣
        function cal_delta_mat(self)
            
            % 將密度矩陣從大到小排序
            [value,index] = sort([self.rho_mat],'descend');
            % 局部密度最大的數(shù)據(jù)id
            id_max = index(1);
            self.delta_mat(id_max) = max(self.dist_mat(id_max,:));
            for i = 2:length(self.dataset)
                self.delta_mat(index(i)) = min(self.dist_mat(index(i),index(1:i-1)));
            end
        end
        
        % 對(duì)數(shù)據(jù)進(jìn)行聚類
        function cluster(self)
            % 將rho與delta相乘,取值最大的數(shù)個(gè)為聚類中心
            [value,index] = sort([self.rho_mat.*self.delta_mat],'descend');
            
            for i = 1:self.center_num
                self.center_ids(i) = index(i);
            end;
            
            % 遍歷樣本,將其分類給最近的且密度大于自己的數(shù)據(jù)
            for i = 1:length(self.dataset)
                dist = realmax('double');
                % 取出大于該個(gè)體密度的數(shù)據(jù)id
                better_ids = self.rho_mat > self.rho_mat(i);
                for id = 1:length(self.dataset)
                    if better_ids(id) == 0 
                        % 密度小于當(dāng)前數(shù)據(jù),跳過
                        continue
                    end
                    % 如果該數(shù)據(jù)是聚類中心則跳過
                    if ismember(i,self.center_ids)
                        continue
                    end
                    % 記錄密度大于自己的最近數(shù)據(jù)id
                    if self.dist_mat(i,id) < dist
                        dist = self.dist_mat(i,id);
                        self.members_parent_id(i) = id;
                    end
                end   
                
                if self.members_parent_id(i)==0
                    for id = 1:self.center_num
                        % 如果自己是聚類中心,則賦值自己
                        if self.center_ids(id) == i
                            self.members_parent_id(i) = i;
                        else
                            % 否則賦值最近的聚類中心
                            % 記錄密度大于自己的最近數(shù)據(jù)id
                        if self.dist_mat(i,self.center_ids(id)) < dist
                            dist = self.dist_mat(i,self.center_ids(id));
                            self.members_parent_id(i) = self.center_ids(id);
                        end
                        end
                    end
                end
                self.members_parent_id(index(1)) = index(1);
            end
            
            % 遍歷樣本,將其分類給最近的且密度大于自己的數(shù)據(jù)
            for i = 1:length(self.dataset)
                self.members_center_index(i) = self.get_center_id(i);
            end
        end 
        
        % 遞歸查找聚類中心
        function center_index=get_center_id(self,data_id)
            for i = 1:self.center_num
                % 如果自己是聚類中心直接返回
                if data_id == self.center_ids(i)
                    center_index = i;
                    return 
                end
                if self.center_ids(i) == self.members_parent_id(data_id) 
                    center_index = i;
                    return;
                end
            end
            
            center_index = self.get_center_id(self.members_parent_id(data_id));
            return ;
        end
        
        % 計(jì)算各類到其他類的最小距離之和
        function dist_min = get_dist_min(self)
            % 創(chuàng)建一個(gè)臨時(shí)矩陣,1*center_num,記錄各聚類與其他類的最小距離
            dist_min_mat = ones(1,self.center_num)*realmax('double');
            for i = 1:length(self.dataset)
                % 獲取該數(shù)據(jù)的聚類中心
                center_index = self.members_center_index(i);
                % 獲取與該數(shù)據(jù)不是一個(gè)中心的數(shù)據(jù)
                other_ids = center_index~=self.members_center_index;
                dist = min(self.dist_mat(i,other_ids));
                if dist < dist_min_mat(center_index)
                    dist_min_mat(center_index) = dist;
                end
            end
            dist_min = sum(dist_min_mat);
        end
        
    end
   
end

4.測(cè)試代碼
文件名:..\optimization algorithm\application_dpc\Test.m
  隨機(jī)生成了5個(gè)簇,優(yōu)化算法中,聚類中心數(shù)的取值范圍設(shè)置為了2-10

%% 清理之前的數(shù)據(jù)
% 清除所有數(shù)據(jù)
clear all;
% 清除窗口輸出
clc;

a = unifrnd(-pi,pi,100,1);
ra = unifrnd(0,5,100,1);
b = unifrnd(-pi,pi,100,1);
rb = unifrnd(0,5,100,1);

c = unifrnd(-pi,pi,100,1);
rc = unifrnd(0,6,100,1);

data = [
    sin(a(:)).*ra(:)+10,cos(a(:)).*ra(:)+10;
    sin(b(:)).*rb(:)-10,cos(b(:)).*rb(:)-10;
    sin(c(:)).*rc(:),cos(c(:)).*rc(:);
    sin(c(:)).*rc(:)-10,cos(c(:)).*rc(:)+10;
    sin(b(:)).*rb(:)+10,cos(b(:)).*rb(:)-10;
    ];

model = DPC_Model(data);
model.get_dc_range();
[min_dc,max_dc] = model.get_dc_range();
range_max = [max_dc,10];
range_min = [min_dc,2];
%% 添加目錄
% 將上級(jí)目錄中的frame文件夾加入路徑
addpath('../frame')
% 引入差分進(jìn)化算法
addpath('../algorithm_differential_evolution')
%% 算法實(shí)例
dim = 2;
% 種群數(shù)量
size = 10;
% 最大迭代次數(shù)
iter_max = 20;
% 取值范圍上界
range_max_list = range_max;
% 取值范圍下界
range_min_list = range_min;
% 實(shí)例化差分進(jìn)化算法類
base = DE_Impl(dim,size,iter_max,range_min_list,range_max_list);
base.is_cal_max = true;
% 確定適應(yīng)度函數(shù)
base.fitfunction = @model.fit_function;
% 運(yùn)行
base.run();
disp(['復(fù)雜度',num2str(base.cal_fit_num)]);

disp(model.fit_function(base.position_best));
model.draw();

結(jié)果如下:

四. 總結(jié)

本文介紹了使用優(yōu)化算法優(yōu)化k均值聚類和密度峰值聚類這兩個(gè)聚類算法。
  其中k均值聚類的核心在于聚類中心的確定,對(duì)于由迭代計(jì)算聚類中心來(lái)完成聚類的算法我們可以直接使用優(yōu)化算法確定其聚類中心。
  密度峰值聚類中聚類的結(jié)果有密度半徑dc以及聚類數(shù)確定,但它沒有直接可用的值作為適應(yīng)度函數(shù),因此需要根據(jù)實(shí)際情況構(gòu)造適應(yīng)度函數(shù),文中的適應(yīng)度函數(shù)僅供參考,實(shí)際應(yīng)用需要自行構(gòu)造。
  文中使用的差分進(jìn)化算法實(shí)現(xiàn)可以看優(yōu)化算法matlab實(shí)現(xiàn)(七)差分進(jìn)化算法matlab實(shí)現(xiàn)。如果想使用其他優(yōu)化算法,則引入相關(guān)的優(yōu)化算法路徑后,實(shí)例化即可。

文件目錄如下:

..\optimization algorithm\application_kmeans\Kmeans_Model.m
..\optimization algorithm\application_kmeans\Test.m
..\optimization algorithm\application_dpc\DPC_Model.m
..\optimization algorithm\application_dpc\Test.m
..\optimization_algorithm\frame\Unit.py
..\optimization_algorithm\frame\Algorithm_Impl.py
..\optimization_algorithm\algorithm_differential_evolution\DE_Unit.py
..\optimization_algorithm\algorithm_differential_evolution\DE_Base.py
..\optimization_algorithm\algorithm_differential_evolution\DE_Impl.py
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容