0

ニューロンの数とホップフィールド ネットワークのパターン認識能力との間に関係はありますか?

ホップフィールド ネットワークでパターンを認識するニューラル ネットワーク プログラムを C# で作成します。私のネットワークには 64 個のニューロンがあります。2 つのパターンについてネットワークをトレーニングすると、すべてがうまく簡単に機能しますが、より多くのパターンについてネットワークをトレーニングすると、Hopfield は答えを見つけることができません!

では、私のコードによれば、Hopfield ネットワークを使用してより多くのパターンを学習するにはどうすればよいでしょうか?

このコードを変更する必要がありますか?

私のtrain()機能があります:

public void Train(bool[,] pattern)
{
    //N is number of rows in our square matrix
    //Convert input pattern to bipolar
    int[,] PatternBipolar = new int[N, N];

    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            {
                if (pattern[i, j] == true)
                {
                    PatternBipolar[i, j] = 1;
                }
                else
                {
                    PatternBipolar[i, j] = -1;
                }
            }

    //convert to row matrix
    int count1 = 0;
    int[] RowMatrix = new int[(int)Math.Pow(N, 2)];
    for (int j = 0; j < N; j++)
        for (int i = 0; i < N; i++)
            {
                RowMatrix[count1] = PatternBipolar[i, j];
                count1++;
            }

    //convert to column matrix
    int count2 = 0;
    int[] ColMatrix = new int[(int)Math.Pow(N, 2)];
    for (int j = 0; j < N; j++)
        for (int i = 0; i < N; i++)
            {
                ColMatrix[count2] = PatternBipolar[i, j];
                count2++;
            }

    //multiplication
    int[,] MultipliedMatrix = new int[(int)Math.Pow(N, 2), (int)Math.Pow(N, 2)];
    for (int i = 0; i < (int)Math.Pow(N, 2); i++)
        for (int j = 0; j < (int)Math.Pow(N, 2); j++)
            {
                MultipliedMatrix[i, j] = ColMatrix[i] * RowMatrix[j];
            }

    //cells in the northwest diagonal get set to zero
    for (int i = 0; i < (int)Math.Pow(N, 2); i++)
        MultipliedMatrix[i, i] = 0;

    // WightMatrix + MultipliedMatrix

    for (int i = 0; i < (int)Math.Pow(N, 2); i++)
        for (int j = 0; j < (int)Math.Pow(N, 2); j++)
            {
                WeightMatrix[i, j] += MultipliedMatrix[i, j];
            }

関数がありPresent()ます (この関数は、特定のパターンの回答を返すために使用されます)。

public void Present(bool[,] Pattern)
{
    int[] output = new int[(int)(int)Math.Pow(N, 2)];

    for (int j = 0; j < N; j++)
        for (int i = 0; i < N; i++)
            {
                OutputShowMatrix[i, j] = 0;
            }

    //convert bool to binary
    int[] PatternBinary = new int[(int)Math.Pow(N, 2)];
    int count = 0;
    for (int j = 0; j < N; j++)
        for (int i = 0; i < N; i++)
            {
                if (Pattern[i, j] == true)
                {
                    PatternBinary[count] = 1;
                }
                else
                {
                    PatternBinary[count] = 0;
                }
                count++;
            }

    count = 0;
    int activation = 0;
    for (int j = 0; j < (int)Math.Pow(N, 2); j++)
    {
        for (int i = 0; i < (int)Math.Pow(N, 2); i++)
        {
            activation = activation + (PatternBinary[i] * WeightMatrix[i, j]);
        }

        if (activation > 0)
        {
            output[count] = 1;
        }
        else
        {
            output[count] = 0;
        }

        count++;
        activation = 0;
    }

    count = 0;
    for (int j = 0; j < N; j++)
        for (int i = 0; i < N; i++)
        {
            OutputShowMatrix[i, j] = output[count++];
        }

以下の画像では、文字 A と P に対してホップフィールドをトレーニングしました。入力パターンが A または P のような場合、ネットワークはそれらを真の方法で認識します ここに画像の説明を入力 ここに画像の説明を入力

次に、キャラクター C 用にトレーニングします。 ここに画像の説明を入力

これはすべてがうまくいかないところです!

C のようなパターンを入力すると、次の問題が発生します。 ここに画像の説明を入力

A のようなパターンを入力すると、何が起こるかを確認します。 ここに画像の説明を入力

そして、さらにパターンを訓練すると、グリッド全体が黒くなります!

4

1 に答える 1

1

あなたのコードには 1 つだけ間違いがありました。値が収束したかどうかを確認せずに、ノード値の計算を 1 回だけ繰り返しています。この方法を次のように修正しました。

public bool[,] Present(bool[,] pattern)
{
    bool[,] result = new bool[N, N];
    int[] activation = new int[N * N];

    int count = 0;
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
        {
            activation[count++] = pattern[i, j] ? 1 : 0;
        }

    bool convergence = false;
    while (!convergence)
    {
        convergence = true;
        var previousActivation = (int[])activation.Clone();
        for (int i = 0; i < N * N; i++)
        {
            activation[i] = 0;
            for (int j = 0; j < N * N; j++)
            {
                activation[i] += (previousActivation[j] * WeightMatrix[i, j]);
            }

            activation[i] = activation[i] > 0 ? 1 : 0;

            if (activation[i] != previousActivation[i])
            {
                convergence = false;
            }
        }
    }

    count = 0;
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
        {
            result[i, j] = activation[count++] == 1;
        }

    return result;
}

これにより結果がわずかに改善されますが、サイクルを回避するために非同期で値を計算するように改善する必要があります。

残念ながら、これはあなたが説明した動作を導入します。これはスプリアスパターンと呼ばれる現象によるものです。ネットワークが複数のパターンを学習するには、Hebb ルールでトレーニングすることを検討してください。ホップフィールド ネットワークのスプリアス パターン、安定性、学習については、こちらこちらをご覧ください。

于 2013-10-13T00:09:57.233 に答える