No science, No life.

もっと科学を身近に

自己組織化マップ (self-organizing map) を書いてみた

情報を自動で分類するアルゴリズムとして、自己組織化マップ (self-organizing map) というものが知られています。自己組織化マップは教師無し学習の一種で、おおざっぱな学習則はつぎの通りです。

1. ランダムな重みベクトルからなるマップを用意する。
2. 入力ベクトルを1つ用意する。
3. 入力にもっとも近いノードをみつける。
4. そのノードと、近傍のノードとを、入力ベクトルに近づける。
5. ステップ2-4をたくさん繰り返す。

ちゃんとした学習則は、Wikipediaなどを参考に。提唱者Kohonen自身による下の著作もあります。

自己組織化マップ

自己組織化マップ

これをMatlabで書いてみました。色 (赤・緑・青の3要素からなるベクトル) を自動で分類します。最初のランダムなマップはたとえば下のような状態。

f:id:neocortex:20170212233639p:plain:w300

ここから、ステップ2-4を繰り返していきます。100回目が終わるとこんな感じ↓ まだあまり変化が分かりません。

f:id:neocortex:20170212233815p:plain:w300

200回目↓

f:id:neocortex:20170212234355p:plain:w300

500回目↓ マップがすこし滑らかになってきました。

f:id:neocortex:20170212234045p:plain:w300

1000回目↓

f:id:neocortex:20170212234129p:plain:w300

2000回目↓

f:id:neocortex:20170212235255p:plain:w300

5000回目↓ 似た色が自動的に近くのノードに配置されています。

f:id:neocortex:20170212234201p:plain:w300

アニメーションでみるとこんな感じ↓

f:id:neocortex:20170202004023g:plain

シンプルな学習則なのに、情報を自動で分類できるところが面白いですね。「色」は構造のよく分かったデータですが、全体像の見えにくい高次元のデータにも適用することができます (というより自己組織化マップが真価を発揮するのはそういう場面のはず)。

今回のコードは下の通りです (ステップ4の部分はもっとスッキリ書けると思いますが、ひとまずこのままで)。

function SOMtest

figure(1);
clf
N = 20;      % map size
a = 0.1;     % learning coefficient

% random weight vector (step 1)
W = rand(N,N,3);
image(W)
title('0')
axis image off
drawnow
saveas(h,'0','png')

for t=1:5000
    % input vector (step 2)
    V = rand(1,1,3);
    
    % find the nearest node (step 3)
    D = sum((W-repmat(V,N,N,1)).^2,3);
    [~,I] = min(D(:));
    [Irow,Icol] = ind2sub(size(D),I);

    % update the weight vector (step 4)
    for ii=-1:1
        for jj=-1:1
            if 0<Irow+ii && Irow+ii<=N && 0<Icol+jj && Icol+jj<=N
                W(Irow+ii,Icol+jj,:) = ...
                    W(Irow+ii,Icol+jj,:) + a*(V-W(Irow+ii,Icol+jj,:));
            end
        end
    end
    image(W)
    title(t)
    axis image off
    drawnow
    
    % save image
    if mod(t,100)==0
        saveas(h,num2str(t),'png')
    end
end