HopfieldネットワークおよびC#実装

34385 ワード

著作権所有:ベースソフトウェア.作者メールアドレス:[email protected].本文はhttp://www.cnblogs.com/FoundationSoft.文章の転載はこの著作権情報を保持し、出典を明記してください.
最近本を読んでいます.Introduction to Neural Networks for CSharpです.その中の1章ではHopfieldネットワークを紹介しています.この章はHopfieldの紹介に対してとても簡単で、その運行過程はC#で実現するのも簡単で、ただネットの運行の原理、数学の証明を紹介していないで、プログラムは運行しても、その理由を知らないことを知っています.私はネット上でいくつかの資料を調べて、Hopfiedネットワークの数学理論の基礎と訓練方法の有効性の数学の証明を見つけることを期待して、しかししばらく本の上で言う訓練方法と一致する関連内容を見つけていないで、意外にも別の問題の対を発見します:みんなはHopfieldネットワークの模型と訓練の説明に対してすべていくつかの違いがあって、完全に一致する定義がありません.これからはいろいろな資料を見て、自分で理解して、他の人の言うことを選別しなければならないようです.いずれにしても、本で紹介されている内容は簡単で実用的で、本の訓練方法によって簡単なパターンを識別することができます.この文章は本の中のHopfieldネットの訓練と識別方法をまとめた.本で定義したHopfieldネットワークは,単層全相互接続自動連想ネットワーク(fully connected single layer autoassociative network)である.本で述べたHopfieldネットワークには,(1)ネットワークにN個のニューロンがある場合,重み行列WがN*Nの方程式であるという特徴がある.重み行列Wは対称行列である、対角線要素は0である.すなわち,ニューロンから自己への重み値は0である.(2)ニューロン入力は2値(すなわち0、1または-1、1)であり、本では0と1を用いる.(3)ニューロン出力は2値(すなわち0、1または-1、1)であり、本では0と1を用いる.訓練過程は以下の通りである:(1)初期化重み行列は0である.(2)次モードPを入力し、PはN次元ベクトル(p 1,p 2,p 3...pn)とする.(3)pにpを乗じた転置によりN*Nの行列Aが得られる.(4)ステップ3の行列Aの対角線要素を0に設定.(5)行列Aを重み行列Wに戻す.(6)より多くのパターンがある場合は、ステップ2に進む.(7)訓練終了.訓練終了後,Hopfieldネットワークを用いて前の訓練モード,あるいはそれらに近いモードを識別することができ,これはHopfieldの連想機能を体現している.Hopfieldは、トレーニングモードとは逆のモードを自動的に認識することができ、例えばトレーニングモードが[0,1,1,0]であれば、トレーニング後、ネットワークも認識することができる[1,0,0,1].Hopfieldネットワークを用いて,デジタル識別のような簡単なグラフィック識別を実現できる.パターンをドットマトリクスに分解し,2次元マトリクスを形成し,マトリクスを1次元のベクトルに引き延ばすことがHopfieldネットワークが認識するパターンである.このモードをHopfieldネットワークトレーニングに入力すればよい.HopfieldネットワークのC#コードは以下のように実現される.次のコードにはマトリクスクラスMatrixが使用されています.これは私が書いたクラスで、よく使われるマトリクス演算がカプセル化されています.コードはここです.
 


Hopfieldネットワークコード

   
     
/// <summary>
/// Hopfield , , 。
/// </summary>
/// <remarks>
/// ,2010-10-18
/// [email protected]
/// </remarks>
public class HopfieldNetwork
{
#region
private Matrix weightMatrix;
/// <summary>
///
/// </summary>
public Matrix weight
{
get
{
return weightMatrix;
}
}
/// <summary>
///
/// </summary>
public int size
{
get
{
return weightMatrix.rowNum;
}
}
#endregion

#region
/// <summary>
/// Hopfield
/// </summary>
/// <param name="size"> </param>
public HopfieldNetwork( int size)
{
this .weightMatrix = new Matrix(size, size);

}
#endregion
/// <summary>
/// ( )
/// </summary>
/// <param name="pattern"> </param>
/// <returns> </returns>
public bool [] Present( bool [] pattern)
{
bool [] output = new bool [pattern.Length];
// ( )
Matrix row = new Matrix(BipolarUtil.Bipolar2double(pattern));
//
for ( int c = 0 ; c < pattern.Length; c ++ )
{
Matrix column
= weightMatrix.getColumn(c);
double dotProduct = (row * column)[ 0 , 0 ];
output[c]
= dotProduct > 0 ;
}
return output;
}

/// <summary>
///
/// </summary>
/// <param name="pattern"> </param>
public void Train( bool [] pattern)
{
if (pattern.Length != weightMatrix.rowNum)
throw new AnnException( " Hopfield 。 " );

//
Matrix input = new Matrix(BipolarUtil.Bipolar2double(pattern));
//
Matrix inpute2 = Matrix.transpose(input);
// , , 0
Matrix t = inpute2 * input;
for ( int i = 0 ; i < input.columnNum; i ++ )
t[i, i]
= 0 ;
//
weightMatrix = weightMatrix + t;
}
}

Hopfieldネットワークをテストするコードは以下の通りです.このコードは8ニューロンで2つの事前定義されたモード01011100と0011111を識別し,Hopfieldネットワークの連想記憶機能により訓練サンプルに近似したモードを識別することができ,これはファジイ識別に非常に有用である.
この例のコードや考え方によれば,デジタル認識のプログラムを書きやすい.デジタルグラフィックをドットマトリクスに編成し,このドットマトリクスを行ベクトルに引き伸ばしてHopfieldネットワークのトレーニングサンプルとすればよい.例えば0~9の数字をパターンごとに16*16のドットマトリクスにすると、16*16=256個のニューロンが必要になる.もちろんこれほどは使えないはずですが、具体的な数は実験で決めることができます.
次のコードは私が8つのニューロンで2つのモードを識別した例です.まず標準サンプルで訓練し,その後ユーザにモードを入力させ認識させる.


Hopfieldネットワークテストコード

   
     
1 /// <summary>
2   /// 8 Hopfield ,
3   /// </summary>
4 public void simplePattern()
5 {
6 const int SIZE = 8 ;
7 HopfieldNetwork hopfield = new HopfieldNetwork(SIZE);
8 Console.WriteLine( " " );
9 Console.WriteLine(hopfield.weight.toMatrixString( 0 ));
10 // 2
11 bool [] sample1 = new bool [] { false , true , false , true , true , true , false , false }; // 01011100
12 bool [] sample2 = new bool [] { false , false , true , true , true , true , true , true }; // 00111111
13 // 2
14 hopfield.train(sample1);
15 Console.WriteLine( " 01010101 : " );
16 Console.WriteLine(hopfield.weight.toMatrixString( 0 ));
17 hopfield.train(sample2);
18 Console.WriteLine( " 0011 : " );
19 Console.WriteLine(hopfield.weight.toMatrixString( 0 ));
20 string input = null ;
21 bool [] pattern = new bool [SIZE];
22 bool [] result = new bool [SIZE];
23 StringBuilder sb = new StringBuilder();
24 // 8
25 // , 2 ,
26 while ( true )
27 {
28 Console.Write( " ( 01011100, 00111111),exit : " );
29 input = Console.ReadLine();
30 if (input == " exit " ) break ;
31 if (input.Length != SIZE) continue ;
32 for ( int i = 0 ; i < SIZE; i ++ )
33 pattern[i] = (input[i] != ' 0 ' );
34 result = hopfield.present(pattern);
35 sb.Clear();
36 for ( int i = 0 ; i < SIZE; i ++ )
37 sb.Append(result[i] ? " 1 " : " 0 " );
38 Console.WriteLine( " " + sb.ToString());
39 }
40 }

 
the end of this article