Miyazawa’s Pukiwiki
自己組織化マップの概要
はすでに存在します。
開始行:
#access
#analog
*自己組織化マップの概要 [#bf7164ad]
#contents
**自己組織化マップ(Self-Organizing Maps, SOM)とは [#j9c...
-統計学的説明 : 多くのパラメータを使うことで近似的にノン...
--PCAとは … 多次元のデータを、できるだけ情報量を落とすこ...
---例 : [数学の点, 国語の点, 理科の点, 社会の点] → [数学+...
--非線形PCAとは … 非線形関数であっても推定可能、SOM や カ...
---例 : 三角関数(データが原点を中心にした円弧上に存在す...
-生理学的説明 : 大脳感覚野の特徴地図が知覚経験によって形...
--網膜細胞の入力から、[[一次視覚野の方位選択性+眼優位性構...
-応用的説明 : [[マインドウエア総研 自己組織化マップとは...
**理論 [#efd25dac]
-SOMは入力層(入力データを与える層)、SOM層(競合層)から...
--入力層は R 個のノード(ニューロン)からなる。1つのノー...
--SOM層は2次元または1次元にノードが配置された構造をもつ。...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---視覚に例えると、入力層が網膜のニューロン、SOM層が一次...
-入力層のノードは、ある時点でSOMに与えられる入力ベクトル...
--SOMに与えられる入力ベクトル
#mimetex( \vec{\mathbf{p}} = (p_1,p_2,\cdots,p_R) );
は、入力層のノード数と同じR次元で、絶対値1に規格化されて...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--ベクトル''p''の絶対値は、
#mimetex( \left\| \vec{\mathbf{p}} \right\| = \sqrt{({p_1...
であるので、''p''の絶対値が1になるように規格化するには、'...
---例えば、ベクトル (1,0,1) を規格化すると、(1/√2,0,1/√2)...
--続いて入力ベクトルの集合 ''P'' を定義する。
---学習を終えるまでにネットワークに与える全ての入力ベクト...
、以下のように表記できる。
#mimetex( \mathbf{P} = \left( \begin{array}{cccc} p_{1,1}...
-SOM層の各ノードは、参照ベクトル(reference vector)と呼ば...
--i番目のノードの参照ベクトルは以下のように定義できる。
#mimetex( \vec{\mathbf{m}_i} = (\mu_{i1},\mu_{i2},\cdots,...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---参照ベクトルは、入力ベクトルと同じくR次元で、全て絶対...
---SOM層の各ノードは、入力層の全てのノードと、参照ベクト...
---参照ベクトルは、生理学的には神経細胞同士のシナプス結合...
--SOM層は S 個のノードをもつので、各ノードについて参照ベ...
#mimetex( \mathbf{M} = \left( \begin{array}{cccc} \mu_{1,...
---初期状態では、各μの値はランダムに割り振るか、入力ベク...
-入力ベクトル''p''が入力層に与えられると、''p''に最も近い...
--ベクトル同士の「近さ」の判定方法は複数考えられるが、基...
--すなわち、勝者をc番目のノードとすると、
#mimetex( c = arg\max_i \left\{ \vec{\mathbf{m}_i} \cdot ...
---''m''i・''p''の値が最大になるiの値がcになる、というこ...
---「・」はベクトルの内積を示す。なお、ベクトル''x''と''y...
#mimetex( \vec{\mathbf{x}} = (x_1,x_2,\cdots,x_n) );
#mimetex( \vec{\mathbf{y}} = (y_1,y_2,\cdots,y_n) );
のとき、
#mimetex( \vec{\mathbf{x}} \cdot \vec{\mathbf{y}} = (x_1 ...
---入力ベクトルに対して、一つだけのノードが選択されるメカ...
-勝者ノードが選ばれたら、SOM層上において、勝利ノードとそ...
--SOMの学習は、参照ベクトルを入力ベクトル''p''に近づける...
#mimetex( \vec{\mathbf{m}_i} := \frac{ \vec{\mathbf{m}_i}...
---ベクトル''m''i の値を、「(''m''i + hci × ''p'')を絶対...
--上式の右辺の分子は、「ヘッブ学習」と呼ばれる、ニューラ...
#mimetex( h_{ci} = \alpha \exp{ ( - \frac{ \left\| \vec{\...
---αは学習の強さを表す1より小さな正の定数である。
---exp記号以降は、[[正規分布(ガウス分布)をあらわす関数:...
---''r''iはSOM層のi番目のノードの2次元配列上での位置をあ...
---σは近傍の広がりを現す正の定数で、正規分布の標準偏差(...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--上式hciは、近傍関数またはKohonen学習関数とよばれ、「勝...
---ためしに、MATLABで正規分布を作ってみましょう。
#geshi(matlab){{
mu = 3.0; %正規分布の平均値(中心座標、勝利ノー...
sigma = 2.0; %正規分布の標準偏差(勝利ノードの周辺...
normalDist = zeros(100, 2) %データを入力する配列を宣言
for x = 0.1:0.1:10 %xは0.1から0.1ずつ10まで...
%xについて正規分布の値を求める
y = exp( - (x - mu) .* (x - mu) / 2 * sigma .* si...
normalDist( int16(x*10), : ) = [x y]; %x×10番目...
end
figure(1);
plot(normalDist(:,1), normalDist(:,2)); %データを...
xlabel('SOM層の座標'); ylabel('強化の強さ');
}}
-SOMでは、入力ベクトルの集合''P''からランダムに入力ベクト...
--学習の回数を「ステップ数」といいます。
--入力ベクトルの集合''P''のデータ全てを1回ずつ与えたら、...
--αとσは定数でもよいが、学習の回数にしたがって減少させた...
--「似た入力ベクトルに対しては、SOM層上の近い座標のニュー...
-SOMの実行例は、[[こちら:http://shower.human.waseda.ac.jp...
-信号空間内で頻繁に現れる領域は、ノード配列上で広い範囲に...
--入力の確率密度関数 p(x)と、参照ベクトルの確率密度関数 ρ...
#mimetex( \rho(x) \propto p(x)^{\frac{2}{3}} );
--「A∝B」(AはBに比例する)
--上式が成り立つには、「ノード配列と入力がともに1次元であ...
**実装 [#z2b9820f]
-MATLABを使って、簡単なSOM(ヒモ状の内積型SOM)を再現して...
-縦方向のノード数 8 × 横方向のノード数 1 の、1次元のヒモ...
#geshi(matlab){{
som_node = cell(8,1)
}}
>
som_node =
[]
[]
[]
[]
[]
[]
[]
[]
--将来、多次元のSOMを作ることも考えて、セル配列 で定義し...
-入力層は4つのノードからなる(=入力ベクトルが4次元)であ...
--最初の重みの値は0~1までの間で、ランダムにする。
#geshi(matlab){{
for somNum = 1:1:length(som_node)
som_node{somNum,1} = rand(1,4);
end
}}
---初期状態では、もう少しばらつきが小さいほうがいいかも
--格納された値を確認するには、
#geshi(matlab){{
for somNum = 1:1:length(som_node)
disp( strcat('SOMのノード番号 : ', int2str(somNum), ...
disp( som_node{somNum,1} );
end
}}
>
SOMのノード番号 :1,1
0.3819 0.4322 0.0407 0.6870
SOMのノード番号 :2,1
0.8054 0.5061 0.1841 0.8513
...
SOMのノード番号 :8,1
0.5383 0.9785 0.2062 0.9239
&color(red){※実行結果は毎回変わります。};
---8つのノードそれぞれについて、4つの重み値が定義された。
--同じノード内で重みベクトルの%%内積が1%%&color(red){絶対...
#geshi(matlab){{
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
scPrSom = sqrt( sum(weight.*weight) ); %正規化前の...
newWeight = weight / scPrSom; %正規化後の...
som_node{somNum,1} = newWeight; %重み値を書...
disp( strcat('SOMのノード番号(正規化後) : ', int2st...
disp( som_node{somNum,1} );
end
}
>
SOMのノード番号(正規化後) :1,1
0.4253 0.4813 0.0453 0.7651
SOMのノード番号(正規化後) :2,1
0.6245 0.3924 0.1427 0.6601
...
SOMのノード番号(正規化後) :8,1
0.3677 0.6684 0.1408 0.6311
&color(red){※実行結果は毎回変わります。};
---これで、ネットワークの初期化は完了。
--初期状態の%%重み値%%&color(red){参照ベクトル};を視覚化...
#geshi(matlab){{
data = zeros(9,4);
for somNum = 1:1:length(som_node)
data(somNum,:) = som_node{somNum,1};
end
countNode = (1:1:length(som_node))';
surf( [data countNode] ); %色つき立体グラフで表示
view(2); %平面表示
xlabel('入力層ノードの番号'); ylabel('SOM層ノードの番号')
}}
---関数surfは一番端の行がプロットされないので、データの行...
-続いて、入力ベクトルの集合(4次元の入力ベクトル×150デー...
--4次元なので、Fisherのアヤメの測定データを使います。
--これは、以下のように、3種類のアヤメ150サンプルに対して...
| 花のID | 花の種類 | がくの長さ | がくの幅 | 花弁の長さ ...
| 1 | 1 | 5.1 | 3.5 | 1.4 | 0.2 |
| 2 | 1 | 4.9 | 3 | 1.4 | 0.2 |
| ... | ... | ... | ... | ... | ... |
| 150 | 3 | 5.9 | 3 | 5.1 | 1.8 |
--例えば、[[ここ:http://shower.human.waseda.ac.jp/~m-kouk...
#geshi(matlab){{
inputdata = csvread('アヤメのデータ.csv',1,2)
}}
//--&ref(iris_JMP.csv); をダウンロードして、以下を実行
//#geshi(matlab){{
// inputdata = csvread('iris_JMP.csv',1,2)
//}}
>
inputdata =
5.1000 3.5000 1.4000 0.2000
4.9000 3.0000 1.4000 0.2000
...
5.9000 3.0000 5.1000 1.8000
---引数の(1,2)は、「縦は1行目から最後まで読み込む(最初の...
---注意:基本的に、MATLABでは「0行目」「0列目」という言い...
--このままでは、次元(特徴量)ごとに数値の最大・最小値が...
#geshi(matlab){{
inputVector = zeros(150,4);
%次元(特徴量)ごとに処理する
for inpNum = 1:1:4
%まずは、各データからその次元の最小値を引く(0から...
zeroStartData = inputdata(:,inpNum) - min( inputdat...
%続いて、各データをその次元の最大値で割る(1で終わ...
inputVector(:,inpNum) = zeroStartData / max(zeroSta...
end
inputVector
}}
>
inputVector =
0.2222 0.6250 0.0678 0.0417
0.1667 0.4167 0.0678 0.0417
...
0.4444 0.4167 0.6949 0.7083
---これで、4列(次元、特徴量) × 150行で 0~1 の、入力ベ...
---&color(red){入力ベクトルも内積が1になるよう正規化する...
-ネットワークの学習を行います。
--inputVector の 1行目を入力層に与えます。
#geshi(matlab){{
input_node = inputVector(1,:)
}}
>
input_node =
0.2222 0.6250 0.0678 0.0417
--SOM層の各ノードの参照ベクトルと入力ベクトルを掛け合わせ...
#geshi(matlab){{
weightInputVector = zeros(8,4); %掛け合わせた値を代入...
for somNum = 1:1:length(som_node)
weightInputVector(somNum,:) = som_node{somNum,1} .* ...
disp( strcat('SOMのノード番号 : ', int2str(somNum), ...
disp( weightInputVector(somNum,:) );
end
}}
>
SOMのノード番号 :1,1
0.0945 0.3008 0.0031 0.0319
SOMのノード番号 :2,1
0.1388 0.2452 0.0097 0.0275
...
SOMのノード番号 :8,1
0.0817 0.4177 0.0095 0.0263
&color(red){※実行結果は毎回変わります。};
--更新された各ノードの重み4次元を足し合わせた結果、もっと...
#geshi(matlab){{
sumSomNode = zeros(8,1); % 各ノードの合計値を代入する...
for somNum = 1:1:length(som_node)
sumSomNode(somNum) = sum( weightInputVector(somNum,:...
end
%もっとも合計値が大きかったノードの番号を取得する
winnerSomNumber = find( sumSomNode == max(sumSomNode) );
disp( strcat('勝利ノードの番号 : ', int2str(winnerSomNu...
}}
>
勝利ノードの番号 :3
&color(red){※実行結果は毎回変わります。};
--勝利ノードとその周辺のノードの重みを、入力ベクトルに近...
---強化関数を定義します。
#geshi(matlab){{
somNum = [1:1:length(som_node)];
learningRate = 0.1; %学習率(1回の学習で、入力ベクト...
mu = winnerSomNumber; %正規分布の平均値(中心座標、勝...
sigma = 2.0; %正規分布の標準偏差(勝利ノード...
reinforcement = learningRate ...
* exp( (-(somNum - mu) .* (somNum - mu)) / 2 * sig...
figure(1);
plot(reinforcement); xlabel('SOMノードの番号'); ylabel(...
}}
---&color(red){learningRate = α に対応};
---強化の度合いの関数は、勝利ノードを中心した正規分布とし...
#mimetex(f(x) = exp { - \frac{(x - \mu)^2}{2 \sigma^2} } )
---強化関数は以下のようになります(&color(red){※平均値=勝...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---勝利ノードを中心として、標準偏差で指定した値のノードま...
---強化関数にしたがって、重み値を入力ベクトルに近づけます。
#geshi(matlab){{
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
newWeight = weight + ((input_node - weight) * reinf...
som_node{somNum,1} = newWeight; %重み値を書...
disp( strcat('SOMのノード番号(更新後) : ', int2str(...
disp( som_node{somNum,1} );
end
}}
>
SOMのノード番号(更新後) :1,1
0.4253 0.4813 0.0453 0.7651
SOMのノード番号(更新後) :2,1
0.6190 0.3955 0.1417 0.6517
...
SOMのノード番号(更新後) :8,1
0.3677 0.6684 0.1408 0.6311
&color(red){※実行結果は毎回変わります。};
--同じノード内で参照ベクトルの内積が1になるように、値を正...
#geshi(matlab){{
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
scPrSom = sqrt( sum(weight.*weight) ); %正規化前の...
newWeight = weight / scPrSom; %正規化後の...
som_node{somNum,1} = newWeight; %重み値を書...
end
}}
--これで、一回の学習の処理が終了しました。
-同様にして、入力ベクトルの集合からランダムに各行を取り出...
#geshi(matlab){{
learningSteps = 1000; %学習の回数を決める
for step = 1:1:learningSteps
disp(strcat('leanrnig steps... ', int2str(step)));
%今回使う入力ベクトルの番号をランダムに選択する
input_node_num = ceil(rand() * length(inputVector));
input_node = inputVector(input_node_num,:);
%勝利ノードを計算する
weightInputVector = zeros(8,4); %掛け合わせた値を...
sumSomNode = zeros(8,1); % 各ノードの合計値を代...
for somNum = 1:1:length(som_node)
weightInputVector(somNum,:) = som_node{somNum,...
sumSomNode(somNum) = sum( weightInputVector(so...
end
winnerSomNumber = find( sumSomNode == max(sumSomNo...
%重み値を更新する
somNum = [1:1:length(som_node)];
learningRate = 0.1; %学習率(1回の学習で、入力...
u = winnerSomNumber; %正規分布の平均値(中心座標...
sigma = 2.0; %正規分布の標準偏差(勝利ノ...
reinforcement = learningRate ...
* exp( (-(somNum - u) .* (somNum - u)) / 2 * ...
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
newWeight = weight + ((input_node - weight)...
som_node{somNum,1} = newWeight; %重...
end
%重み値を正規化する
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
scPrSom = sqrt( sum(weight.*weight) ); %正...
newWeight = weight / scPrSom; %正...
som_node{somNum,1} = newWeight; %重...
end
end
}}
--学習が終わった後の重み値は、以下のようにして確認します。
#geshi(matlab){{
for somNum = 1:1:length(som_node)
disp( strcat('SOMのノード番号(学習後) : ', int2str(...
disp( som_node{somNum,1} );
end
}}
>
SOMのノード番号(学習後) :1,1
0.4330 0.7556 0.0967 0.4819
SOMのノード番号(学習後) :2,1
0.3773 0.9137 0.1103 0.1035
...
SOMのノード番号(学習後) :8,1
0.3842 0.3107 0.5992 0.6300
&color(red){※実行結果は毎回変わります。};
--これで、ネットワークの学習は終了です。
-クローズドテストで正解率を求めてみます。
--入力データファイルの2列目(アヤメの種類)を読み込みます。
#geshi(matlab){{
targetdata = csvread('iris_JMP.csv',1,0);
targetdata = targetdata(:,2); %2列目を取得
}}
---アヤメの種類データは1,2,3の数値で表現されています。
--正解率の求め方はいろいろ考えられますが、ここでは「同じ...
#geshi(matlab){{
%入力データの種類ごとにヒストグラムを作る
dataHistgram = [];
%アヤメの種類:1 の勝利ノードを格納するベクトル
evalWinnerSomNumber_1 = [];
%アヤメの種類:2 の勝利ノードを格納するベクトル
evalWinnerSomNumber_2 = [];
%アヤメの種類:3 の勝利ノードを格納するベクトル
evalWinnerSomNumber_3 = [];
%勝利ノードを計算する
for evalNum = 1:1:length(inputVector)
input_node = inputVector(evalNum,:);
%勝利ノードを計算する
weightInputVector = zeros(8,4); %掛け合わせた値を...
sumSomNode = zeros(8,1); % 各ノードの合計値を代入...
for somNum = 1:1:length(som_node)
weightInputVector(somNum,:) = som_node{somNum,1...
sumSomNode(somNum) = sum( weightInputVector(som...
end
winnerSomNumber = find( sumSomNode == max(sumSomNod...
if(targetdata(evalNum)==1)
evalWinnerSomNumber_1 = [evalWinnerSomNumber_1 ...
elseif(targetdata(evalNum)==2)
evalWinnerSomNumber_2 = [evalWinnerSomNumber_2 ...
elseif(targetdata(evalNum)==3)
evalWinnerSomNumber_3 = [evalWinnerSomNumber_3 ...
end
end
%頻度分布を計算
dataHistgram = [ ...
hist(evalWinnerSomNumber_1, [1:1:length(som_node)])...
hist(evalWinnerSomNumber_2, [1:1:length(som_node)])...
hist(evalWinnerSomNumber_3, [1:1:length(som_node)])...
%ヒストグラムをプロット
figure(2);
bar(dataHistgram');
xlabel('SOMのノード番号'); ylabel('頻度(勝利ノードに選...
legend('1', '2', '3');
}}
--結果は以下のようになります(&color(red){※実行結果は毎回...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---カテゴリー1のアヤメを代表するSOMノードは2番(とその周...
---ただし、カテゴリー1に比べて、カテゴリー2と3の弁別は十...
**【拡張】カテゴリの数を推定する [#rb69b7b8]
***(寺島,1996)による方法 [#c2f28358]
-母音体系の獲得過程をシミュレーションする上で、従来のSOM...
-例として、分散が等しく平均が異なる正規分布をSOMによって...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--上図に示したのはクラスタごとに平均の異なる、3種類の(3...
-ここで、分類したいクラスタ(カテゴリ)数が既知の場合を考...
-SOMの学習では、「分類したいクラスタ数 = S(出力層のノー...
--値はランダムな順番でSOMに提示していくとする。
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--上図は学習結果の例である(S = 1×3 = 3ノードの1次元SOM)。
--それぞれ、ほぼ正しいクラスタ境界を学習できている。
-次に、クラスタ数が不明の場合を考える。
--母音数は言語によって異なり、乳児は母国語に応じた母音数...
--入力がどのような分布をとるか不明で、何種類のクラスタに...
-SOMによる学習の結果を示す(S = 1×6 = 6ノードの1次元SOM)。
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
-SOMでは、カテゴリ間の境界付近にニューロンが割り当てられ...
--ヒトの範疇化知覚を再現できているとはいえない。
--学習結果をもとに、類似したカテゴリを同一のカテゴリに統...
-ニューロンが1列に配置された1次元SOM について、以下のよう...
++学習を終えたSOM にテストデータセットを提示し、SOMのそれ...
++ヒストグラムのピークピッキングを行い、カテゴリの中心と...
++カテゴリ中心以外のノードの重みを0にして、入力データとの...
-上記の学習結果(S = 1×6 = 6ノードの1次元SOM)に対して、...
--SOMの学習結果のカテゴリ集積度を示すヒストグラム
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---カテゴリ集積度をみると、①④⑥番のノードがカテゴリ中心に...
--2,3,5番のSOMのノードの重みをゼロにして、各データがどの...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--再計算によってカテゴリが統合され、3つの正規分布を抽出で...
-要検討事項
--SOMのノード数が正解のカテゴリ数に対して多くなると、ピー...
--- → &color(red){ヒストグラムの曲線の平滑化が必要};
-データ密度ヒストグラムを用いたクラスタ分類法(寺島,1996...
---以下のプログラムは、[[MATLAB Neural Network Toolbox の...
--入力の数のみによる判定( L = V )
---'''[[20110729_useTerashimaMethod.zip:http://shower.hum...
--入力の数+重みによる判定( L = V / dM )
---'''[[20110729_useTerashimaMethod.zip:http://shower.hum...
---両端のノードの、(すなわち存在しない)隣接ノードの重み...
***(加藤,2009)による(寺島,1996)の拡張 [#jbe69f4f]
-(寺島,1996)の方法で獲得したカテゴリーをさらに正確に統合...
--獲得したカテゴリーの隣あう各ペアについて、「統合した一...
--AICとBIC([[ベイズ情報量規準:http://ja.wikipedia.org/wi...
-サンプルプログラム &ref(RUN_TerashimaAndKatoMethod.m);
--そこそこの頻度で、カテゴリー数の推定がうまくいかない場...
---例えば以下の場合、AIC, BICどちらも、誤って2クラスタに...
#ref(AIC_errorsample1.png,,50%);
---以下の場合は両基準ともに正しく1クラスタに分類できた。
#ref(AIC_errorsample2.png,,50%);
---以下の場合は、AIC, BICどちらも、誤って1クラスタに分類...
#ref(AIC_errorsample3.png,,50%);
---以下はAICは誤って2クラスタに分類してしまったが、BICは...
#ref(AIC_errorsample4.png,,50%);
---この手法によって取り出される分布は正規分布ではなく、分...
終了行:
#access
#analog
*自己組織化マップの概要 [#bf7164ad]
#contents
**自己組織化マップ(Self-Organizing Maps, SOM)とは [#j9c...
-統計学的説明 : 多くのパラメータを使うことで近似的にノン...
--PCAとは … 多次元のデータを、できるだけ情報量を落とすこ...
---例 : [数学の点, 国語の点, 理科の点, 社会の点] → [数学+...
--非線形PCAとは … 非線形関数であっても推定可能、SOM や カ...
---例 : 三角関数(データが原点を中心にした円弧上に存在す...
-生理学的説明 : 大脳感覚野の特徴地図が知覚経験によって形...
--網膜細胞の入力から、[[一次視覚野の方位選択性+眼優位性構...
-応用的説明 : [[マインドウエア総研 自己組織化マップとは...
**理論 [#efd25dac]
-SOMは入力層(入力データを与える層)、SOM層(競合層)から...
--入力層は R 個のノード(ニューロン)からなる。1つのノー...
--SOM層は2次元または1次元にノードが配置された構造をもつ。...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---視覚に例えると、入力層が網膜のニューロン、SOM層が一次...
-入力層のノードは、ある時点でSOMに与えられる入力ベクトル...
--SOMに与えられる入力ベクトル
#mimetex( \vec{\mathbf{p}} = (p_1,p_2,\cdots,p_R) );
は、入力層のノード数と同じR次元で、絶対値1に規格化されて...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--ベクトル''p''の絶対値は、
#mimetex( \left\| \vec{\mathbf{p}} \right\| = \sqrt{({p_1...
であるので、''p''の絶対値が1になるように規格化するには、'...
---例えば、ベクトル (1,0,1) を規格化すると、(1/√2,0,1/√2)...
--続いて入力ベクトルの集合 ''P'' を定義する。
---学習を終えるまでにネットワークに与える全ての入力ベクト...
、以下のように表記できる。
#mimetex( \mathbf{P} = \left( \begin{array}{cccc} p_{1,1}...
-SOM層の各ノードは、参照ベクトル(reference vector)と呼ば...
--i番目のノードの参照ベクトルは以下のように定義できる。
#mimetex( \vec{\mathbf{m}_i} = (\mu_{i1},\mu_{i2},\cdots,...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---参照ベクトルは、入力ベクトルと同じくR次元で、全て絶対...
---SOM層の各ノードは、入力層の全てのノードと、参照ベクト...
---参照ベクトルは、生理学的には神経細胞同士のシナプス結合...
--SOM層は S 個のノードをもつので、各ノードについて参照ベ...
#mimetex( \mathbf{M} = \left( \begin{array}{cccc} \mu_{1,...
---初期状態では、各μの値はランダムに割り振るか、入力ベク...
-入力ベクトル''p''が入力層に与えられると、''p''に最も近い...
--ベクトル同士の「近さ」の判定方法は複数考えられるが、基...
--すなわち、勝者をc番目のノードとすると、
#mimetex( c = arg\max_i \left\{ \vec{\mathbf{m}_i} \cdot ...
---''m''i・''p''の値が最大になるiの値がcになる、というこ...
---「・」はベクトルの内積を示す。なお、ベクトル''x''と''y...
#mimetex( \vec{\mathbf{x}} = (x_1,x_2,\cdots,x_n) );
#mimetex( \vec{\mathbf{y}} = (y_1,y_2,\cdots,y_n) );
のとき、
#mimetex( \vec{\mathbf{x}} \cdot \vec{\mathbf{y}} = (x_1 ...
---入力ベクトルに対して、一つだけのノードが選択されるメカ...
-勝者ノードが選ばれたら、SOM層上において、勝利ノードとそ...
--SOMの学習は、参照ベクトルを入力ベクトル''p''に近づける...
#mimetex( \vec{\mathbf{m}_i} := \frac{ \vec{\mathbf{m}_i}...
---ベクトル''m''i の値を、「(''m''i + hci × ''p'')を絶対...
--上式の右辺の分子は、「ヘッブ学習」と呼ばれる、ニューラ...
#mimetex( h_{ci} = \alpha \exp{ ( - \frac{ \left\| \vec{\...
---αは学習の強さを表す1より小さな正の定数である。
---exp記号以降は、[[正規分布(ガウス分布)をあらわす関数:...
---''r''iはSOM層のi番目のノードの2次元配列上での位置をあ...
---σは近傍の広がりを現す正の定数で、正規分布の標準偏差(...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--上式hciは、近傍関数またはKohonen学習関数とよばれ、「勝...
---ためしに、MATLABで正規分布を作ってみましょう。
#geshi(matlab){{
mu = 3.0; %正規分布の平均値(中心座標、勝利ノー...
sigma = 2.0; %正規分布の標準偏差(勝利ノードの周辺...
normalDist = zeros(100, 2) %データを入力する配列を宣言
for x = 0.1:0.1:10 %xは0.1から0.1ずつ10まで...
%xについて正規分布の値を求める
y = exp( - (x - mu) .* (x - mu) / 2 * sigma .* si...
normalDist( int16(x*10), : ) = [x y]; %x×10番目...
end
figure(1);
plot(normalDist(:,1), normalDist(:,2)); %データを...
xlabel('SOM層の座標'); ylabel('強化の強さ');
}}
-SOMでは、入力ベクトルの集合''P''からランダムに入力ベクト...
--学習の回数を「ステップ数」といいます。
--入力ベクトルの集合''P''のデータ全てを1回ずつ与えたら、...
--αとσは定数でもよいが、学習の回数にしたがって減少させた...
--「似た入力ベクトルに対しては、SOM層上の近い座標のニュー...
-SOMの実行例は、[[こちら:http://shower.human.waseda.ac.jp...
-信号空間内で頻繁に現れる領域は、ノード配列上で広い範囲に...
--入力の確率密度関数 p(x)と、参照ベクトルの確率密度関数 ρ...
#mimetex( \rho(x) \propto p(x)^{\frac{2}{3}} );
--「A∝B」(AはBに比例する)
--上式が成り立つには、「ノード配列と入力がともに1次元であ...
**実装 [#z2b9820f]
-MATLABを使って、簡単なSOM(ヒモ状の内積型SOM)を再現して...
-縦方向のノード数 8 × 横方向のノード数 1 の、1次元のヒモ...
#geshi(matlab){{
som_node = cell(8,1)
}}
>
som_node =
[]
[]
[]
[]
[]
[]
[]
[]
--将来、多次元のSOMを作ることも考えて、セル配列 で定義し...
-入力層は4つのノードからなる(=入力ベクトルが4次元)であ...
--最初の重みの値は0~1までの間で、ランダムにする。
#geshi(matlab){{
for somNum = 1:1:length(som_node)
som_node{somNum,1} = rand(1,4);
end
}}
---初期状態では、もう少しばらつきが小さいほうがいいかも
--格納された値を確認するには、
#geshi(matlab){{
for somNum = 1:1:length(som_node)
disp( strcat('SOMのノード番号 : ', int2str(somNum), ...
disp( som_node{somNum,1} );
end
}}
>
SOMのノード番号 :1,1
0.3819 0.4322 0.0407 0.6870
SOMのノード番号 :2,1
0.8054 0.5061 0.1841 0.8513
...
SOMのノード番号 :8,1
0.5383 0.9785 0.2062 0.9239
&color(red){※実行結果は毎回変わります。};
---8つのノードそれぞれについて、4つの重み値が定義された。
--同じノード内で重みベクトルの%%内積が1%%&color(red){絶対...
#geshi(matlab){{
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
scPrSom = sqrt( sum(weight.*weight) ); %正規化前の...
newWeight = weight / scPrSom; %正規化後の...
som_node{somNum,1} = newWeight; %重み値を書...
disp( strcat('SOMのノード番号(正規化後) : ', int2st...
disp( som_node{somNum,1} );
end
}
>
SOMのノード番号(正規化後) :1,1
0.4253 0.4813 0.0453 0.7651
SOMのノード番号(正規化後) :2,1
0.6245 0.3924 0.1427 0.6601
...
SOMのノード番号(正規化後) :8,1
0.3677 0.6684 0.1408 0.6311
&color(red){※実行結果は毎回変わります。};
---これで、ネットワークの初期化は完了。
--初期状態の%%重み値%%&color(red){参照ベクトル};を視覚化...
#geshi(matlab){{
data = zeros(9,4);
for somNum = 1:1:length(som_node)
data(somNum,:) = som_node{somNum,1};
end
countNode = (1:1:length(som_node))';
surf( [data countNode] ); %色つき立体グラフで表示
view(2); %平面表示
xlabel('入力層ノードの番号'); ylabel('SOM層ノードの番号')
}}
---関数surfは一番端の行がプロットされないので、データの行...
-続いて、入力ベクトルの集合(4次元の入力ベクトル×150デー...
--4次元なので、Fisherのアヤメの測定データを使います。
--これは、以下のように、3種類のアヤメ150サンプルに対して...
| 花のID | 花の種類 | がくの長さ | がくの幅 | 花弁の長さ ...
| 1 | 1 | 5.1 | 3.5 | 1.4 | 0.2 |
| 2 | 1 | 4.9 | 3 | 1.4 | 0.2 |
| ... | ... | ... | ... | ... | ... |
| 150 | 3 | 5.9 | 3 | 5.1 | 1.8 |
--例えば、[[ここ:http://shower.human.waseda.ac.jp/~m-kouk...
#geshi(matlab){{
inputdata = csvread('アヤメのデータ.csv',1,2)
}}
//--&ref(iris_JMP.csv); をダウンロードして、以下を実行
//#geshi(matlab){{
// inputdata = csvread('iris_JMP.csv',1,2)
//}}
>
inputdata =
5.1000 3.5000 1.4000 0.2000
4.9000 3.0000 1.4000 0.2000
...
5.9000 3.0000 5.1000 1.8000
---引数の(1,2)は、「縦は1行目から最後まで読み込む(最初の...
---注意:基本的に、MATLABでは「0行目」「0列目」という言い...
--このままでは、次元(特徴量)ごとに数値の最大・最小値が...
#geshi(matlab){{
inputVector = zeros(150,4);
%次元(特徴量)ごとに処理する
for inpNum = 1:1:4
%まずは、各データからその次元の最小値を引く(0から...
zeroStartData = inputdata(:,inpNum) - min( inputdat...
%続いて、各データをその次元の最大値で割る(1で終わ...
inputVector(:,inpNum) = zeroStartData / max(zeroSta...
end
inputVector
}}
>
inputVector =
0.2222 0.6250 0.0678 0.0417
0.1667 0.4167 0.0678 0.0417
...
0.4444 0.4167 0.6949 0.7083
---これで、4列(次元、特徴量) × 150行で 0~1 の、入力ベ...
---&color(red){入力ベクトルも内積が1になるよう正規化する...
-ネットワークの学習を行います。
--inputVector の 1行目を入力層に与えます。
#geshi(matlab){{
input_node = inputVector(1,:)
}}
>
input_node =
0.2222 0.6250 0.0678 0.0417
--SOM層の各ノードの参照ベクトルと入力ベクトルを掛け合わせ...
#geshi(matlab){{
weightInputVector = zeros(8,4); %掛け合わせた値を代入...
for somNum = 1:1:length(som_node)
weightInputVector(somNum,:) = som_node{somNum,1} .* ...
disp( strcat('SOMのノード番号 : ', int2str(somNum), ...
disp( weightInputVector(somNum,:) );
end
}}
>
SOMのノード番号 :1,1
0.0945 0.3008 0.0031 0.0319
SOMのノード番号 :2,1
0.1388 0.2452 0.0097 0.0275
...
SOMのノード番号 :8,1
0.0817 0.4177 0.0095 0.0263
&color(red){※実行結果は毎回変わります。};
--更新された各ノードの重み4次元を足し合わせた結果、もっと...
#geshi(matlab){{
sumSomNode = zeros(8,1); % 各ノードの合計値を代入する...
for somNum = 1:1:length(som_node)
sumSomNode(somNum) = sum( weightInputVector(somNum,:...
end
%もっとも合計値が大きかったノードの番号を取得する
winnerSomNumber = find( sumSomNode == max(sumSomNode) );
disp( strcat('勝利ノードの番号 : ', int2str(winnerSomNu...
}}
>
勝利ノードの番号 :3
&color(red){※実行結果は毎回変わります。};
--勝利ノードとその周辺のノードの重みを、入力ベクトルに近...
---強化関数を定義します。
#geshi(matlab){{
somNum = [1:1:length(som_node)];
learningRate = 0.1; %学習率(1回の学習で、入力ベクト...
mu = winnerSomNumber; %正規分布の平均値(中心座標、勝...
sigma = 2.0; %正規分布の標準偏差(勝利ノード...
reinforcement = learningRate ...
* exp( (-(somNum - mu) .* (somNum - mu)) / 2 * sig...
figure(1);
plot(reinforcement); xlabel('SOMノードの番号'); ylabel(...
}}
---&color(red){learningRate = α に対応};
---強化の度合いの関数は、勝利ノードを中心した正規分布とし...
#mimetex(f(x) = exp { - \frac{(x - \mu)^2}{2 \sigma^2} } )
---強化関数は以下のようになります(&color(red){※平均値=勝...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---勝利ノードを中心として、標準偏差で指定した値のノードま...
---強化関数にしたがって、重み値を入力ベクトルに近づけます。
#geshi(matlab){{
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
newWeight = weight + ((input_node - weight) * reinf...
som_node{somNum,1} = newWeight; %重み値を書...
disp( strcat('SOMのノード番号(更新後) : ', int2str(...
disp( som_node{somNum,1} );
end
}}
>
SOMのノード番号(更新後) :1,1
0.4253 0.4813 0.0453 0.7651
SOMのノード番号(更新後) :2,1
0.6190 0.3955 0.1417 0.6517
...
SOMのノード番号(更新後) :8,1
0.3677 0.6684 0.1408 0.6311
&color(red){※実行結果は毎回変わります。};
--同じノード内で参照ベクトルの内積が1になるように、値を正...
#geshi(matlab){{
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
scPrSom = sqrt( sum(weight.*weight) ); %正規化前の...
newWeight = weight / scPrSom; %正規化後の...
som_node{somNum,1} = newWeight; %重み値を書...
end
}}
--これで、一回の学習の処理が終了しました。
-同様にして、入力ベクトルの集合からランダムに各行を取り出...
#geshi(matlab){{
learningSteps = 1000; %学習の回数を決める
for step = 1:1:learningSteps
disp(strcat('leanrnig steps... ', int2str(step)));
%今回使う入力ベクトルの番号をランダムに選択する
input_node_num = ceil(rand() * length(inputVector));
input_node = inputVector(input_node_num,:);
%勝利ノードを計算する
weightInputVector = zeros(8,4); %掛け合わせた値を...
sumSomNode = zeros(8,1); % 各ノードの合計値を代...
for somNum = 1:1:length(som_node)
weightInputVector(somNum,:) = som_node{somNum,...
sumSomNode(somNum) = sum( weightInputVector(so...
end
winnerSomNumber = find( sumSomNode == max(sumSomNo...
%重み値を更新する
somNum = [1:1:length(som_node)];
learningRate = 0.1; %学習率(1回の学習で、入力...
u = winnerSomNumber; %正規分布の平均値(中心座標...
sigma = 2.0; %正規分布の標準偏差(勝利ノ...
reinforcement = learningRate ...
* exp( (-(somNum - u) .* (somNum - u)) / 2 * ...
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
newWeight = weight + ((input_node - weight)...
som_node{somNum,1} = newWeight; %重...
end
%重み値を正規化する
for somNum = 1:1:length(som_node)
weight = som_node{somNum,1};
scPrSom = sqrt( sum(weight.*weight) ); %正...
newWeight = weight / scPrSom; %正...
som_node{somNum,1} = newWeight; %重...
end
end
}}
--学習が終わった後の重み値は、以下のようにして確認します。
#geshi(matlab){{
for somNum = 1:1:length(som_node)
disp( strcat('SOMのノード番号(学習後) : ', int2str(...
disp( som_node{somNum,1} );
end
}}
>
SOMのノード番号(学習後) :1,1
0.4330 0.7556 0.0967 0.4819
SOMのノード番号(学習後) :2,1
0.3773 0.9137 0.1103 0.1035
...
SOMのノード番号(学習後) :8,1
0.3842 0.3107 0.5992 0.6300
&color(red){※実行結果は毎回変わります。};
--これで、ネットワークの学習は終了です。
-クローズドテストで正解率を求めてみます。
--入力データファイルの2列目(アヤメの種類)を読み込みます。
#geshi(matlab){{
targetdata = csvread('iris_JMP.csv',1,0);
targetdata = targetdata(:,2); %2列目を取得
}}
---アヤメの種類データは1,2,3の数値で表現されています。
--正解率の求め方はいろいろ考えられますが、ここでは「同じ...
#geshi(matlab){{
%入力データの種類ごとにヒストグラムを作る
dataHistgram = [];
%アヤメの種類:1 の勝利ノードを格納するベクトル
evalWinnerSomNumber_1 = [];
%アヤメの種類:2 の勝利ノードを格納するベクトル
evalWinnerSomNumber_2 = [];
%アヤメの種類:3 の勝利ノードを格納するベクトル
evalWinnerSomNumber_3 = [];
%勝利ノードを計算する
for evalNum = 1:1:length(inputVector)
input_node = inputVector(evalNum,:);
%勝利ノードを計算する
weightInputVector = zeros(8,4); %掛け合わせた値を...
sumSomNode = zeros(8,1); % 各ノードの合計値を代入...
for somNum = 1:1:length(som_node)
weightInputVector(somNum,:) = som_node{somNum,1...
sumSomNode(somNum) = sum( weightInputVector(som...
end
winnerSomNumber = find( sumSomNode == max(sumSomNod...
if(targetdata(evalNum)==1)
evalWinnerSomNumber_1 = [evalWinnerSomNumber_1 ...
elseif(targetdata(evalNum)==2)
evalWinnerSomNumber_2 = [evalWinnerSomNumber_2 ...
elseif(targetdata(evalNum)==3)
evalWinnerSomNumber_3 = [evalWinnerSomNumber_3 ...
end
end
%頻度分布を計算
dataHistgram = [ ...
hist(evalWinnerSomNumber_1, [1:1:length(som_node)])...
hist(evalWinnerSomNumber_2, [1:1:length(som_node)])...
hist(evalWinnerSomNumber_3, [1:1:length(som_node)])...
%ヒストグラムをプロット
figure(2);
bar(dataHistgram');
xlabel('SOMのノード番号'); ylabel('頻度(勝利ノードに選...
legend('1', '2', '3');
}}
--結果は以下のようになります(&color(red){※実行結果は毎回...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---カテゴリー1のアヤメを代表するSOMノードは2番(とその周...
---ただし、カテゴリー1に比べて、カテゴリー2と3の弁別は十...
**【拡張】カテゴリの数を推定する [#rb69b7b8]
***(寺島,1996)による方法 [#c2f28358]
-母音体系の獲得過程をシミュレーションする上で、従来のSOM...
-例として、分散が等しく平均が異なる正規分布をSOMによって...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--上図に示したのはクラスタごとに平均の異なる、3種類の(3...
-ここで、分類したいクラスタ(カテゴリ)数が既知の場合を考...
-SOMの学習では、「分類したいクラスタ数 = S(出力層のノー...
--値はランダムな順番でSOMに提示していくとする。
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--上図は学習結果の例である(S = 1×3 = 3ノードの1次元SOM)。
--それぞれ、ほぼ正しいクラスタ境界を学習できている。
-次に、クラスタ数が不明の場合を考える。
--母音数は言語によって異なり、乳児は母国語に応じた母音数...
--入力がどのような分布をとるか不明で、何種類のクラスタに...
-SOMによる学習の結果を示す(S = 1×6 = 6ノードの1次元SOM)。
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
-SOMでは、カテゴリ間の境界付近にニューロンが割り当てられ...
--ヒトの範疇化知覚を再現できているとはいえない。
--学習結果をもとに、類似したカテゴリを同一のカテゴリに統...
-ニューロンが1列に配置された1次元SOM について、以下のよう...
++学習を終えたSOM にテストデータセットを提示し、SOMのそれ...
++ヒストグラムのピークピッキングを行い、カテゴリの中心と...
++カテゴリ中心以外のノードの重みを0にして、入力データとの...
-上記の学習結果(S = 1×6 = 6ノードの1次元SOM)に対して、...
--SOMの学習結果のカテゴリ集積度を示すヒストグラム
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
---カテゴリ集積度をみると、①④⑥番のノードがカテゴリ中心に...
--2,3,5番のSOMのノードの重みをゼロにして、各データがどの...
#ref(http://shower.human.waseda.ac.jp/~m-kouki/images/som...
--再計算によってカテゴリが統合され、3つの正規分布を抽出で...
-要検討事項
--SOMのノード数が正解のカテゴリ数に対して多くなると、ピー...
--- → &color(red){ヒストグラムの曲線の平滑化が必要};
-データ密度ヒストグラムを用いたクラスタ分類法(寺島,1996...
---以下のプログラムは、[[MATLAB Neural Network Toolbox の...
--入力の数のみによる判定( L = V )
---'''[[20110729_useTerashimaMethod.zip:http://shower.hum...
--入力の数+重みによる判定( L = V / dM )
---'''[[20110729_useTerashimaMethod.zip:http://shower.hum...
---両端のノードの、(すなわち存在しない)隣接ノードの重み...
***(加藤,2009)による(寺島,1996)の拡張 [#jbe69f4f]
-(寺島,1996)の方法で獲得したカテゴリーをさらに正確に統合...
--獲得したカテゴリーの隣あう各ペアについて、「統合した一...
--AICとBIC([[ベイズ情報量規準:http://ja.wikipedia.org/wi...
-サンプルプログラム &ref(RUN_TerashimaAndKatoMethod.m);
--そこそこの頻度で、カテゴリー数の推定がうまくいかない場...
---例えば以下の場合、AIC, BICどちらも、誤って2クラスタに...
#ref(AIC_errorsample1.png,,50%);
---以下の場合は両基準ともに正しく1クラスタに分類できた。
#ref(AIC_errorsample2.png,,50%);
---以下の場合は、AIC, BICどちらも、誤って1クラスタに分類...
#ref(AIC_errorsample3.png,,50%);
---以下はAICは誤って2クラスタに分類してしまったが、BICは...
#ref(AIC_errorsample4.png,,50%);
---この手法によって取り出される分布は正規分布ではなく、分...
ページ名:
既存のページ名で編集する