【自己組織化写像:SOM】読ませる気のないアルゴリズムシリーズ【第二弾】
自己組織化写像とは
自律的に秩序を持つ構造を作り出す現象
ニューラルネットワークの一種で、教師なし学習が行える。応用としてNNはもちろん、クラスタリング手法としても用いられる。
色彩の分類に応用した例 http://www.sist.ac.jp/~kanakubo/research/neuro/neuro16.png
お、これは前回の記事のようにUIのグラデーション遷移などに応用できそうだ。早速やってみよう。
ソースコード
#include <iostream> #include <cmath> using namespace std; typedef struct { int r; int g; int b; }RGB; typedef struct { int x; int y; }POS; const double PI = 3.1415926535; //マップサイズ const unsigned int SIZE = 20; //試行回数 const unsigned int NUM = 10000; //単調減少関数 double dec(int n){ return 1.0 - (static_cast<double>(n) / NUM); } //結果 void disp(RGB col[SIZE][SIZE]){ int max, sel; for(int i=0; i<SIZE; i++){ for(int j=0; j<SIZE; j++){ max=col[i][j].r; sel=0; if(max<=col[i][j].b && col[i][j].b>=col[i][j].g)sel=2; if(max<=col[i][j].g && col[i][j].b<=col[i][j].g)sel=1; switch(sel){ case 0: std::cout<<"● "; break; case 1: std::cout<<"× "; break; case 2: std::cout<<"□ "; break; } } cout<<endl; } } //最大相関値の色の位置を取得 POS getMaxCor(RGB col[SIZE][SIZE],RGB value){ POS pos; pos.x = pos.y=0; RGB min; min.r = min.g = min.b = INT_MAX; RGB tmp; for(int y=0; y<SIZE; y++){ for(int x=0; x<SIZE; x++){ tmp.r=abs(col[y][x].r - value.r); tmp.g=abs(col[y][x].g - value.g); tmp.b=abs(col[y][x].b - value.b); if(min.r+min.g+min.b >= tmp.r+tmp.g+tmp.b){ min=tmp; pos.x=x; pos.y=y; } } } return pos; } //勝者ノードの値に近づける void divideValue(RGB& col,RGB type){ col.r = (col.r + type.r) / 2; col.g = (col.g + type.g) / 2; col.b = (col.b + type.b) / 2; } //8近傍関数 void fillMap(RGB col[SIZE][SIZE],RGB type,POS &index){ int x,y; x=index.x; y=index.y; divideValue(col[y][x], type); if(y+1<SIZE && x+1<SIZE) divideValue(col[y+1][x+1], type); if(y-1>=0 && x-1>=0) divideValue(col[y-1][x-1], type); if(y+1<SIZE && x-1>=0) divideValue(col[y+1][x-1], type); if(y-1>=0 && x+1<SIZE) divideValue(col[y-1][x+1], type); if(y+1<SIZE) divideValue(col[y+1][x], type); if(y-1>=0) divideValue(col[y-1][x], type); if(x+1<SIZE) divideValue(col[y][x+1], type); if(x-1>=0) divideValue(col[y][x-1], type); } int main(int argc, const char * argv[]) { RGB rgb[SIZE][SIZE] = {0} , rtmp; POS p; //マップをランダムに初期化 for(int y=0; y<SIZE; y++){ for(int x=0;x<SIZE;x++){ rgb[y][x].r=arc4random()%256; rgb[y][x].g=arc4random()%256; rgb[y][x].b=arc4random()%256; } } //自己組織化 for(int i=0;i<NUM;i++){ rtmp.r=(arc4random()%256); rtmp.g=(arc4random()%256); rtmp.b=(arc4random()%256); p=getMaxCor(rgb,rtmp); fillMap(rgb,rtmp,p); } //結果 disp(rgb); return 0; }
実行結果
[1]
× ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● □ □ □ × ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● □ □ □ × × ● ● ● ● ● ● ● ● ● ● ● ● ● ● □ □ □ □ × × ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● □ □ × × × × × × ● ● ● ● ● ● ● ● ● ● ● ● □ □ □ □ □ □ × × × ● ● ● ● ● ● ● ● ● ● ● ● □ □ □ □ □ × × × × ● ● ● ● ● ● ● ● ● ● ● ● □ □ □ × × × × × ● ● ● ● ● ● ● ● ● ● ● ● □ □ □ × × × × × ● ● ● ● ● ● ● ● ● ● ● ● □ □ × × × × × × × × ● ● ● ● ● ● ● ● □ □ ● × × × × × × × × × × × × × ● ● ● □ □ □ ● × × × × × × × × × × × × × ● ● □ □ □ □ × × × × × × × × × × × × × × □ □ □ □ □ □ × × × × × × × × × × × × × × □ □ □ □ □ □ × × × × × × × × × □ □ □ □ □ □ □ □ □ □ □ × × × × × × × × × □ □ □ □ □ □ □ □ □ □ □ × × × × × × × × × □ □ □ □ □ □ □ □ □ □ □ × × × × × × × × □ □ □ □ □ □ □ □ □ □ □ □ × × × × × × × × □ □ □ □ □ □ □ □ □ □ □ □ × × × × × × × × □ □ □ □ □ □ □ □ □ □ □ □
[2]
● ● ● ● ● ● × × × × × × × × ● ● ● □ □ × ● ● ● ● ● ● × × × × × × × × ● ● ● □ □ × ● ● ● ● ● ● × × × × × × × × ● ● ● □ □ × ● ● ● ● ● ● × × × × × × × × × × × × × × ● ● ● ● ● ● × × × × × × × × × × × × × × ● ● ● ● ● ● × × × × × × × × × × × × × × ● ● ● ● ● ● × × × × × × × × × × × □ × × ● ● ● ● ● ● × ● ● ● × × × × × × × × □ □ ● ● ● ● ● ● ● ● ● ● ● × × × × × × × × □ ● ● ● ● ● ● ● ● ● ● □ □ □ × × × × × × × ● ● ● ● ● ● ● ● ● ● □ □ □ □ □ □ □ × × × ● ● ● ● ● ● ● ● ● ● □ □ □ □ □ □ □ □ □ □ ● ● ● ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ □ ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ × ● ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ ● × × ● ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ ● ● ● ● ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ ● × × □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ □ × × ×
[3]
● ● ● × × × × × □ □ □ □ □ □ □ □ □ □ □ □ ● ● ● × × × × × □ □ □ □ □ □ □ □ □ □ □ □ ● ● ● ● × × × × × × × × □ □ □ □ □ □ □ □ ● ● ● ● × × × × × × × × × × □ □ □ □ □ □ ● ● ● ● ● × × × × × × × × × × □ □ □ □ □ ● ● ● ● ● × × × × × × × × × × × □ □ □ □ ● ● ● ● ● × × × × × × × × × × × × × □ □ ● ● ● ● ● × × × × × × × × × × × × × × × ● ● ● ● ● ● × × × × × × × × × ● ● ● × × ● ● ● ● ● ● × × × × × × × × × ● ● ● × × ● ● ● ● ● ● × × × × × × × × ● ● ● ● ● ● ● ● ● ● ● ● × × × × × × × × □ ● ● ● ● ● ● ● ● ● ● ● ● ● × × × × × × □ □ □ □ □ ● ● ● ● ● ● ● ● ● × × × × × □ □ □ □ □ □ □ ● ● ● ● ● ● ● ● × × × × × □ □ □ □ □ □ □ ● ● ● ● ● ● ● ● × × × × □ □ □ □ □ □ □ □ ● ● ● ● ● ● ● ● ● × × × □ □ □ □ □ □ □ □ ● ● ● ● ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ ● ● ● ● ● □ ● □ □ □ □ × □ □ □ □ □ □ □ □ ● ● ● ● ● □ □ □ □ □ □ □ □ □ □ □ □ □ □ □
まずい、ある程度読めてしまう。 それは良いとして、なかなか面白い結果になった。今回は●×□の3種類でやってみたがN種類の色で自己組織化MAPを作ればグラデーションやBlurMaskに応用できそうだ。