本系列來自於我《人工智能》課程複習總結以及機器學習部分的實驗總結
Kmeans是機器學習中最經典的無監督學習聚類算法,本文複習了無監督學習定義和Kmeans算法,然後提出了一種基於Kmeans算法的圖像壓縮方案,並給出了其在Matlab中的實現
1.無監督學習
通過非標記數據樣本
無監督學習由於沒有標記,那就不存在學習誤差或獎懲函數來評估一個可行解,這是無監督學習和監督學習最大的差別
2.Kmeans聚類
2.2聚類
最常見的無監督學習的方法是聚類,聚類是把數據對象集合通過靜態分類的方法劃分成多個不相交子集並且讓這些子集中的對象都有一些相似的屬性的機器學習方法
相似的定義量化到多維座標系中就是擁有更短的空間距離
最經典也最簡單的聚類算法是Kmeans聚類
2.3Kmeans算法
Kmeans算法需要預先設定聚類個數K,然後以K個點爲中心進行迭代聚類,每輪迭代中把數據歸結到離自己最近的中心點所代表的類中,然後更新中心點繼續迭代
算法可以歸納爲:
- 選擇聚類個數K
- 選擇K個初始中心點(一般隨機產生或數據可視化後挑選較優聚類中心)
- 迭代開始,對每個數據點計算其到所有K箇中心點的距離,選取距其最近的中心點所代表的聚類作爲該數據點的聚類
- 在所有數據點確定其新聚類後,更新每個聚類的新中心點(通常聚類中所有數據點求平均值作爲該聚類新中心點)
- 重複3、4直到聚類中心點收斂(通常會定義最大迭代次數)
Kmeans算法簡潔易懂、收斂速度較快,是機器學習算法中最經典的聚類算法,但它也有以下缺點:
- K需要預先設定,在無法直接觀察數據分佈的情況下較難確定聚類個數
- 對初始聚類中心的優良性依賴較大
- 抗干擾性較弱
3.Kmeans與圖像壓縮
3.1壓縮算法設計
怎樣把聚類算法應用到圖像壓縮中呢?
我們可以從顏色空間壓縮入手:
考慮一個512x512大小的RGB圖像,若每個像素點都有3個8bit(uint8類型,0-255)的值分別對應其紅、綠、藍三種顏色的色彩強度,則這幅圖像需要512x512x3x8bit = 786432Byte = 768KB來保存圖像信息(不包括文件頭)
很容易發現一幅圖像中一般不會囊括RGB色彩空間中的每一種顏色,而其往往包含多個主色調,那麼我們可以通過Kmeans算法來減少圖片中的顏色,如降低到K=16種顏色(記該顏色空間爲K顏色空間),則每個像素點僅需要log2(16)=4bit來標識顏色
我們可以設計一種新的圖片格式,除了必要的文件頭以外,還需要記錄:
- 壓縮K顏色空間和RGB顏色空間的映射關係:即給出0-15代表的K=16種顏色,需要索引出對應的uint8類型RGB值
- 每個像素點的K顏色空間顏色值
那麼我們可以粗略計算理想壓縮比爲:
實際壓縮比應該比該值小,需要注意的是這事一種有損圖像壓縮方案並且壓縮比率也不是很高(只利用了色彩信息,沒有利用空間信息),並且人眼察覺明顯(見結果部分),這裏只是作爲基本機器學習算法的練習,實際圖像壓縮一般不會採取該壓縮方案
3.2Kmeans圖像壓縮
Kmeans可以作爲顏色空間壓縮的聚類算法,具體的做法是
- 取聚類個數K=16
- 隨機產生K個初始中心二維座標,選取出它們的顏色(1x3向量)作爲顏色聚類初始中心點
- 迭代開始,枚舉圖像中所有像素點,對每個像素點計算其顏色到所有K箇中心點的距離,這裏可以用歐式距離,選取距其最近的中心點所代表的聚類作爲該像素點顏色的聚類
- 在所有像素點確定其顏色的新聚類後,更新每個顏色聚類的新中心點(求平均值)
- 重複3、4直到最大迭代次數
如果我們直接考慮對原始圖像顏色聚類,單線程Matlab程序需要較長時間,因此我們先對其較小的壓縮過的圖像進行顏色聚類,選取出16個顏色中心後,在枚舉較大圖像所有像素點,做一次聚類然後更改顏色即可(注:此方法僅僅出於節約時間的目的,老師要求)
3.3Matlab實現
下面給出Matlab用Kmeans算法壓縮圖片的代碼:
clear all;
small = double(imread('../data/bridge_small.bmp'));
h = size(small, 1);
w = size(small, 2);
kn = 16;
key = zeros(kn, 3);
for i = 1 : kn
x = round(random('unif', 1, h));
y = round(random('unif', 1, w));
for j = 1 : 3
key(i, j) = small(x, y ,j);
end
end
iterate = 50;
for t = 1 : iterate
sum = zeros(kn, 3);
count = zeros(kn, 1);
for i = 1 : h
for j = 1 : w
mind = dis(key(1, :), small(i, j, :));
mink = 1;
for k = 2 : kn
d = dis(key(k, :), small(i, j, :));
if d < mind
mind = d;
mink = k;
end
end
count(mink) = count(mink) + 1;
for c = 1 : 3
sum(mink, c) = sum(mink, c) + small(i, j, c);
end
end
end
for k = 1 : kn
key(k, :) = round(sum(k, :) / count(k));
end
end
large = double(imread('../data/bridge_large.bmp'));
compressed = large;
h = size(large, 1);
w = size(large, 2);
for i = 1 : h
for j = 1 : w
mind = dis(key(1, :), large(i, j, :));
mink = 1;
for k = 2 : kn
d = dis(key(k, :), large(i, j, :));
if d < mind
mind = d;
mink = k;
end
end
for c = 1 : 3
compressed(i, j, c) = key(mink, c);
end
end
end
figure
subplot(1,2,1)
imshow(uint8(round(large)))
title('original')
subplot(1,2,2)
imshow(uint8(round(compressed)))
title('compressed')
imwrite(uint8(round(compressed)), 'compressed.bmp');
注:我們並沒有定義之前所構想的圖像格式,而是仍把圖像存儲爲8bitRGB的bmp格式,壓縮後圖像compressed.bmp大小是不變的(僅是結果示意)
3.4結果
壓縮前後圖像對比:
細緻觀察壓縮後圖像:
圖像還是有很多細節丟失,如所佔比例較小的紫紅色的花,被聚類到了橋的磚黃色