機器學習練習之k均值

       k-means屬於聚類分析的其中一種算法,聚類分析在機器學習、數據挖掘、模式識別、決策支持和圖像分割中有廣泛的應用。聚類是無監督的分類方法,所謂無監督就是沒有給定訓練數據的標籤信息,所以聚類出來的結果的類別是未定義的,而分類的目標是把數據分到已知的類別中。聚類是在給定的數據集合中尋找數據子集合,每個子集合形成一個類簇,簇內間的相似性高,而簇間的相似性低。通俗地說,k-means算法就是“物以類聚人以羣分”,把相似性較大的事物聚在一起,相似性較低的事物分開來,從而得到一個個羣組。比如在市場營銷中,我們通過對市場上的顧客信息進行k-means劃分成不同的顧客羣體,因而可以分析不同羣體性質從而制定不同的營銷策略。

      k-means的k是指聚類結果把數據劃分成k個簇,mean表示簇的質心或中心是簇內數據的均值,當數據無法求得均值時,k-means算法就不適用。


算法過程如下:


      算法首先初始化k個簇的中心點或質心。根據樣本集中的每一樣本與k個簇中心的距離,把它賦給最近的簇,然後重新計算簇中心,重複這個過程直到收斂。k個質心可以從樣本集中隨機挑選k個樣本來代表。

      下圖表示k-means的收斂過程:


       如果k個簇中心的初始值選取得不好,k-means會達到局部最優而不是全局最優,局部最優時的結果可能跟預料的結果大相徑庭,所以k-means對初始值選取敏感。k-means還對“噪聲”和異常值敏感,因爲這些點對均值的計算結果影響很大。

       k-means算法是一定能夠收斂的,我們可以定義如下的損失函數:


       函數J衡量的是每個訓練樣本到它被劃分到的簇的中心點的平方距離的和,J不是關於c和u的凸函數,但是函數J可以通過座標下降的方法來求出局部最小值,通過固定u來更新c即固定了中心點,把每個樣本賦給離它最近的簇中心來減少J,然後通過固定c來更新u,因爲使用的是平方距離損失函數,所以求出簇的均值就可以使得J最小,對於這兩個步驟,J都是減少的,因此J得到收斂,但由於J不是凸函數,不一定收斂到全局最優解。


       k-means算法也是EM思想的體現,EM是最大期望算法,也是機器學習和數據挖掘常用的一種方法。E步可對應把每個樣本點劃分到離它最近的簇中,M步可對應到求出簇的均值作爲簇的中心點。但是,k-means的E步是硬的指定,把樣本點劃分到最近的簇中,而不像混合高斯模型中的E步是軟的指定,樣本點可以以概率分到不同的高斯分佈中。


       該練習是要在圖片中把像素分爲16個顏色,k-means的算法過程如下:


       Matlab代碼如下:

%% Exercise: k-means
% k-means算法對鳥圖像素聚類
% 先在小鳥圖上k-means得出k箇中心點顏色,然後在大鳥圖上把各個像素的顏色賦值爲最近中心點的顏色

% 載入小鳥圖像
% A是一個三維數組,A(y,x,1)、A(y,x,2)、A(y,x,3)分別是位置(i,j)的r、g、b像素
A = double(imread('bird_small.tiff'));

dim = size(A,1); %圖片寬度或高度
k = 16; %顯示的顏色種類

%隨機選擇k個初始中心點
means = zeros(k,3); %mean存儲中心點(r,g,b)顏色
x_rand = ceil(dim*rand(k,1));
y_rand = ceil(dim*rand(k,1));
for i=1:k
    means(i,:) = A(y_rand(i), x_rand(i), :);
end

%k-means算法過程
MAX_ITR = 100;
for itr=1:MAX_ITR
    %這一輪新的中心點
    new_means = zeros(size(means));
    %分到每個中心點的像素個數
    num_assigned = zeros(k,1);
    
    for i=1:dim
        for j=1:dim
            %計算像素點到每個中心的距離
            r = A(j,i,1); g = A(j,i,2); b = A(j,i,3);
            diff = ones(k,1)*[r,g,b] - means;
            distance = sum(diff.^2, 2);
            %選擇最近的中心點
            [val ind] = min(distance);
            %該像素點加到最近的中心點
            new_means(ind,1) = new_means(ind,1) + r;
            new_means(ind,2) = new_means(ind,2) + g;
            new_means(ind,3) = new_means(ind,3) + b;
            
            num_assigned(ind) = num_assigned(ind)+1;
        end
    end
    
    %計算新的中心點
    for i=1:k
        if (num_assigned(i) > 0)
            means(i,:) = new_means(i,:) ./ num_assigned(i);
        end
    end
    
    %檢測是否收斂
    d = sum(sqrt(sum((means - new_means).^2, 2)));
    if d < 1e-5
        break
    end
end

disp(itr);

means = round(means);

large_image = double(imread('bird_large.tiff'));
large_dim = size(large_image,1);

for i=1:large_dim
    for j=1:large_dim
        r = large_image(j,i,1); g = large_image(j,i,2); b = large_image(j,i,3);
        diff = ones(k,1)*[r,g,b] - means;
        distance = sum(diff.^2, 2);
        [val ind] = min(distance);
        large_image(j,i,:) = means(ind,:);
    end
end

%顯示
imshow(uint8(round(large_image))); hold off

%保存圖像
imwrite(uint8(round(large_image)), 'bird_kmeans.tiff');

figure; hold on
for i=1:k
    col = (1/255).*means(i,:);
    rectangle('Position', [i,0,1,1], 'FaceColor', col, 'EdgeColor', col);
end
axis off
            

原始大鳥圖:

       通過小鳥圖聚類後把大鳥圖分成16種顏色:


      聚類後的16種顏色:




參考:

http://openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=MachineLearning&doc=exercises/ex9/ex9.html

Andrew NG, 機器學習教程


關於kmeans和EM的一些理解和數學推導可參考jerrylead的博客:

http://www.cnblogs.com/jerrylead/tag/Machine%20Learning/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章