#include <stdio.h> #include <stdlib.h> #include <math.h> #define INPUT_DIM 3 /* 入力データの次元数 */ #define N 500 /* 入力データ数 */ #define SOM_DIM 2 /* コードベクトルの次元数 */ #define L 6 /* 各次元のコードベクトル数 */ #define MAX_T 100 /* 最大繰り返し学習回数 */ #define rnd() (((double)rand()/RAND_MAX-0.5)*2.0) #define square(x) ((x)*(x)) /* 入力データ */ typedef double InputData[INPUT_DIM]; InputData X[N]; /* コードブック */ typedef struct { InputData *M; int n; } CodeBookRec, *CodeBook; /* 距離の定義 */ double Distance(InputData x, InputData m) { register int i; double d; d=0.0; for(i=0; i<INPUT_DIM; i++) d+=square(x[i]-m[i]); return(d); } /* 学習係数関数 */ #define Lambda(t) (1.0/(t)) /* コードベクトル間の距離 */ double DistanceSOM(int winner, int k) { register int i; double d; int delta; d=0.0; for(i=0; i<SOM_DIM; i++) { delta=winner%L-k%L; d+=square(delta); winner/=L; k/=L; } return(sqrt(d)); } /* 近傍関数 */ #define Phi(d) (d<=1) /* コードブックの初期化 */ CodeBook Initialize() { register int i, j; CodeBook B; if((B=(CodeBook)malloc(sizeof(CodeBookRec)))==NULL) return(NULL); B->n=(int)pow(L, SOM_DIM); if((B->M=(InputData *)malloc(sizeof(InputData)*B->n))==NULL) return(NULL); /* コードブックの初期値設定 */ for(i=0; i<B->n; i++) for(j=0; j<INPUT_DIM; j++) B->M[i][j]=rnd(); return(B); } /* 最も近いコードベクトル番号を返す */ int Select(InputData x, CodeBook B) { register int i; int min=-1; double d, min_d; for(i=0; i<B->n; i++) { d=Distance(x, B->M[i]); if(min<0 || d<min_d) { min=i; min_d=d; } } return(min); } /* SOM の学習 */ void Learn(InputData x, InputData m, double alpha) { register int j; for(j=0; j<INPUT_DIM; j++) m[j]+=alpha*(x[j]-m[j]); } /* Winner とデータとの平均距離 */ double Delta(InputData X[], CodeBook B) { register int i; double delta; int winner; delta=0; for(i=0; i<N; i++) { winner=Select(X[i], B); delta+=Distance(X[i], B->M[winner]); } return(delta/N); } main() { register int t, i, j, k; CodeBook B; int winner; int *count; double r, delta, alpha; /* 入力データの生成(球のデータ) */ for(t=0; t<N; t++) { r=0.0; for(j=0; j<INPUT_DIM; j++) { X[t][j]=rnd(); r+=square(X[t][j]); } r=sqrt(r); for(j=0; j<INPUT_DIM; j++) { X[t][j]/=r; } } if((B=Initialize())==NULL) fprintf(stderr, "Cannot allocate Code Book\n"); printf("t=0 delta=%lf\n", Delta(X, B)); for(t=1; t<=MAX_T; t++) { for(i=0; i<N; i++) { winner=Select(X[i], B); for(k=0; k<B->n; k++) { alpha=Lambda(t)*Phi(DistanceSOM(winner, k)); Learn(X[i], B->M[k], alpha); } } printf("t=%d delta=%lf\n", t, Delta(X, B)); } /* 参照された回数のカウント */ if((count=(int *)calloc(sizeof(int), B->n))==NULL) { fprintf(stderr, "Not enough memory\n"); exit(1); } for(i=0; i<N; i++) { winner=Select(X[i], B); count[winner]++; } for(i=0; i<B->n; i++) { printf("%d: ", i); for(k=0; k<INPUT_DIM; k++) printf("%lf ", B->M[i][k]); printf("%d\n", count[i]); } }