tocomの調査録(機械学習、強化学習多め)

機械学習関連のことをまとめていきます。強化学習関連が多いかもしれません

ホップフィールドネットワーク(hopfield network)

ホップフィールドネットワーク概要

ホップフィールドネットワーク(hopfield network)とは、 全結合の無効グラフのニューラルネットワークで、
情報を記憶し、その情報を想起することができるネットワークのことを言います。

以下、イメージ図

f:id:ttt242242:20170128203338p:plain

ホップフィールドネットの処理

ネットワークの初期化

データ数分のノードがネットワークを作成します。
記憶するデータが[1, -1, 1, -1]のような配列であれば、ノード数は4になります。
以下はネットワークのイメージです。

f:id:ttt242242:20190727144052p:plain

ネットワークに記憶

ネットワークに元の情報を覚えさせます。
つまり、リンクの重みとして記憶させます。

各リンクは以下の式で情報を覚えさせます。

$$ \begin{equation} w_{ij} = x_i x_j \end{equation} $$

  • $x_i$はノード$i$の値。つまり、覚えさせたいデータ
  • $w_{ij}$はノード$i$とノード$j$のリンクの重み

式の意味としては、リンクの両端のノードが同じ値であれば、結合を強くするというものである。
これをヘブ則と言います。

データが複数ある時には、単純に総和を取るだけです。 $$ \begin{equation} w_{ij} = \sum_{d \in D} x^{d}_i x^{d}_j \end{equation} $$

Dはデータの集合です。

ちなみに上述した式は$x_i \in {1,-1}$の時です。
$x_i \in {0,1}$の場合については補足を参照してください。

ノイズありデータからの想起

記憶させたデータにノイズを加えたデータから、元のデータを想起させる処理についてです。

例えば、元データが[1, -1, 1]で、
ノイズありデータが[-1, -1, 1]だとしたら、
ノイズありデータをネットワークに入力すると、元データ[1, -1, 1]を出力するということです。

0. ノイズありデータをネットワークに入力
1. ランダムにノードを選択、更新

ノード$x_i$の値、つまり入力されたデータを値を変更していきます。

まず、以下の式を用いて、各ノード$x_i$に対応した$y_i$を計算します。

$$ \begin{equation} y_i = \sum_{j=1}^{N} w_{ij} x_j \end{equation} $$

$y_i$は選択されたノードの値と、そのノードに結合しているリンクの積の総和になります。

そして、$y_i$の値によって、以下のルールに従って、ノード$x_i$をの値を更新します。

$$ x_{i}= \left\{ \begin{array}{rcl} 1 & y_i > 0 \\ x_i & y_i = 0 \\ -1 & y_i < 0 \\ \end{array} \right. $$

2. エネルギー関数の計算

次にネットワーク全体の状態を表すエネルギー関数$E$を計算します。

エネルギー関数$E$は以下のように計算します。

$$ E= -\frac{1}{2}\sum_{ij}^{N} w_{ij} x_i x_j \ $$

3. 1,2をエネルギー関数が最小化するまで繰り返す

補足(入力値が{0,1}の場合)

入力値が{0,1}の場合には、 ヘブ則による更新式が異なります。 具体的には以下の式を用います。

 \displaystyle 
w_{ij} =  (2x_i - 1)  (2x_j - 1) \\

上記の式も同様にリンクの両端のノードの値が一致していれば、 そのリンクの重みを強くすることを表しています。

実装

データを1つだけ記憶するhopfield networkを実装しました。

このプログラムでは、
まず、[1., 1., -1., 1., -1., 1., -1., 1., 1., -1., -1., 1., 1.] というデータを元データとして、ネットワークに記憶させます。 このデータにノイズを加えたテストデータ(最初の2つの値を-1にした)を作成します。
そして、このテストデータをhopfiled networkに入力させ、
元データを想起させています。

上記のプログラムを実行すると、

original data
[1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0]
test data
[-1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0]
result
[1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0]

うまく元データを想起させることができています。