実体と情報のはざま

何事にも囚われず。

自己組織化マップに注力

 前回は、初めて自己組織化マップ(SOM)をPythonで書いてみたが、いざやってみると自分が根本をいまいち理解できていないことがはっきりした。今も実はまだちゃんと理解できていない。ネットや本で調べてみたが様々な考え方があるようだし、根本的な部分で腑に落ちるものはなかった。ただ、平均寿命の半分を生きてきた経験から、「分からない状態をキープする」ことで自分が成長できるのも知っている。SOMについてはこの状態にしておきたい。というわけで、もうしばらくはSOMの周辺に住み込んでいたいと思う。
 理屈はともかくSOMらしいものはできた!
 前回のプログラムはいまいち納得できないことばかりだったので書き直した。一番重要な変更点はこの部分のσの関数形。
f:id:myuteru:20170519231220p:plain
これは、マップ上において着目地点の値の更新の影響をどれくらい遠くまで与えるかを表現した式。今回、関数系を変えたのは、あとで出てくる計算のゼロで割ることのエラー回避のため。減少関数ならいろんな選択肢があるが、シンプルで挙動が分かり易いのを採用した。あとは、プログラム構造のダサい感じを少しでもスマートになるように工夫した。(けど、大差なしか~。。)
プログラムはこうなった。
開発環境:Spyder(Python 3.6)

import numpy as np
import matplotlib.pyplot as plt
########################パラメータの設定
n,f=5,3#入力ベクトル数,#入力ベクトルの要素数
sgm0=10#誤差に関するパラメータ
T=50#繰り返し回数兼時定数
cx,cy=20,15#マップのx,y方向の数

###########################行列の設定
X=np.zeros((n,f))#入力ベクトル行列
X[0,:]=([1,0,0])#R
X[1,:]=([0,1,0])#G
X[2,:]=([0,0,1])#B
X[3,:]=([0,1,1])#?
X[4,:]=([1,1,0])#?
M=np.random.random((cx*cy,f))#マップ中の各サイトの値が入った行列
R=np.zeros((cx*cy,2))#マップ中のサイトの位置が入った行列
for y in range(0,cy):
    for x in range(0,cx):
        k=x+(cx*y)
        R[k,0]=x
        R[k,1]=y
Ita=np.zeros((n,cx*cy))#更新に使う係数
fig1=plt.figure(1)
for j in range(0,cx*cy):
    plt.scatter(R[j,0],R[j,1],color=(M[j,0],M[j,1],M[j,2]),s=100,marker='s')

###########################繰り返しの実行
for t in range(0,T):
    sgm=sgm0*np.exp(-t/T)#
    for i in range(0,n):
        min=1
        for j in range(0,cx*cy):
            d=np.linalg.norm(X[i,:]-M[j,:])
            if d<min:
                min=d
                cj=j
        for j in range(0,cx*cy):
            D=np.linalg.norm(R[j,:]-R[cj,:])
            Ita[i,j]=np.exp(-((D/sgm)**2)/2)
    s=np.sum(Ita,axis=0)#列方向に和をとる(axis=1なら行方向)
    for j in range(0,cx*cy):
        p=np.zeros((f))
        for i in range(0,n):
            p=p+(Ita[i,j]*X[i,:])
        M[j,:]=p/s[j]

fig2=plt.figure(2)
for j in range(0,cx*cy):
    plt.scatter(R[j,0],R[j,1],color=(M[j,0],M[j,1],M[j,2]),s=100,marker='s')

 結果は、こんな感じ。
初期はランダム。
f:id:myuteru:20170519232624p:plain
繰り返し計算で自己組織化した状態がこれ。グラデーションがきれい。
f:id:myuteru:20170519232644p:plain
入力として5色をRGBで指定した。
 プログラムがうまく動いたので調子に乗ってマップのサイズ(プログラム中の記号ではcx,cy)を大きくしてみると、急に計算時間が長くなった。ビッグデータをSOMで分類している方々は何かしらの高速化の仕組みを持っているのだろうな。
 次回は、もっと”分類”や”次元圧縮”といった側面に触れたい~。
今日はここまで!