3

ニューラルネットワークが数字を認識するための基本的なフレームワークがありますが、トレーニングに問題があります。私のバックプロポーションは小さなデータセットでも機能しますが、データポイントが50を超えると、戻り値は0に収束し始めます。何千ものデータセットがある場合、NaNを取得して返します。ニューラルネットワークと大きなデータセット

基本構成:3層:784:15:1

784は、データ・セット当たりの画素、私の隠れ層15個のニューロン、および0から1までの値を返すつの出力ニューロンの数(ありますあなたは10を掛けて数字を得る)。

public class NetworkManager { 
    int inputSize; 
    int hiddenSize; 
    int outputSize; 
    public Matrix W1; 
    public Matrix W2; 

    public NetworkManager(int input, int hidden, int output) { 
     inputSize = input; 
     hiddenSize = hidden; 
     outputSize = output; 
     W1 = new Matrix(inputSize, hiddenSize); 
     W2 = new Matrix(hiddenSize, output); 
    } 

    Matrix z2, z3; 
    Matrix a2; 
    public Matrix forward(Matrix X) { 
     z2 = X.dot(W1); 
     a2 = sigmoid(z2); 

     z3 = a2.dot(W2); 
     Matrix yHat = sigmoid(z3); 

     return yHat; 
    } 

    public double costFunction(Matrix X, Matrix y) { 
     Matrix yHat = forward(X); 

     Matrix cost = yHat.sub(y); 
     cost = cost.mult(cost); 

     double returnValue = 0; 
     int i = 0; 
     while (i < cost.m.length) { 
      returnValue += cost.m[i][0]; 
      i++; 
     } 
     return returnValue; 
    } 

    Matrix yHat; 
    public Matrix[] costFunctionPrime(Matrix X, Matrix y) { 

     yHat = forward(X); 

     Matrix delta3 = (yHat.sub(y)).mult(sigmoidPrime(z3)); 
     Matrix dJdW2 = a2.t().dot(delta3); 

     Matrix delta2 = (delta3.dot(W2.t())).mult(sigmoidPrime(z2)); 
     Matrix dJdW1 = X.t().dot(delta2); 

     return new Matrix[]{dJdW1, dJdW2}; 
    } 
} 

ネットワークフレームワークのコードがあります。私は長さ784の倍精度配列を順方向メソッドに渡します。

int t = 0; 
    while (t < 10000) { 
     dJdW = Nn.costFunctionPrime(X, y); 

     Nn.W1 = Nn.W1.sub(dJdW[0].scalar(3)); 
     Nn.W2 = Nn.W2.sub(dJdW[1].scalar(3)); 

     t++; 
    } 

私はこれを使用して重みを調整します。小さなセットでは、コストは0に収束しますが、大きなセットはありません(100文字に関連するコストは常に13に収束します)。セットが大きすぎると、最初の調整が行われ(そしてコストは下がります)、2番目の調整が終わるとNaNになります。

なぜこの実装は大規模なデータセット(特にトレーニング)で失敗しますか?これをどのように修正できますか?私は同様の構造を1の代わりに10個の出力で試しました。ここではそれぞれ0または1に近い値をブール値のように返しますが、同じことが起こっていました。

私はJavaでこれをやっていますが、それが問題と関係しているのかどうか疑問です。私はそれが宇宙の不足で問題だったかどうか疑問に思っていましたが、私はヒープスペースメッセージを取得していません。どのように私は戻ってpropogatingや何か他のことが起きていることに問題がありますか?

編集:私は何が起こっているか知っていると思います。私は、私のバックプロパゲーション機能が地方の最低限に捕らえられていると思います。トレーニングが成功することがあり、大規模なデータセットでは失敗することがあります。ランダムウェイトから始めているので、ランダムな初期コストが発生します。私が気付いたことは、コストが最初に一定量(それが関係するデータセットの数に依存する)を超えると、コストはきれいな数に(時には27、その他は17.4に)収束し、アウトプットは0に収束する)。

私が始めたときのコスト関数の相対的な最小値が警告され、なぜそれが実現し始めているのですか?だから今質問は、どのように私は実際に世界最小を見つけるだろう私の勾配降下について行くのだろうか?私は途中でJavaで作業しています。

+2

数字の認識は分類問題であり、回帰問題ではありません。 1桁にそれぞれ対応する10個の出力を使用し、最も高い出力値を持つ出力ニューロンに基づいて認識された桁を選択することを検討する必要があります。 – Palle

+0

ええ、私は実際に10の出力フレームワークに戻ってきました –

答えて

1

あなたのバックプロップが小さなデータセットで動作する場合は、問題はないということが本当に良いという仮定があります。あなたがそれについて疑わしいときは、XORの問題であなたのBPを試すことができます。

ユニットにバイアスがかけられていますか?

私はかつてまったく同じことをやっている人と話しました。手のひらの認識と隠れた層の15単位。私はこの仕事をうまくやっているネットワークを見た。彼女のトポロジは:

入力:最初に隠された784

:第二に隠された500

:500

第三に隠された:2000

出力:

10あなたがセットを持っていますあなたは画像の784ピクセルを< 0、1>の15個の数値に非線形変換し、すべての画像でこれを行いますあなたのセットの。あなたは、これらの15の数字に基づいて数字を正しく区別できることを願っています。私の見解では、数千の例を持つデータセットを持っていると仮定した場合、隠されたユニットはあまりにも少なすぎるため、たとえば、500台の隠しユニットを試してみてください。

学習率はバックプロップに影響し、収束に問題を引き起こす可能性があります。

+0

私は実際にバイアスを使用していません。無作為に初期化しますが、訓練のバイアスをどのように調整しますか? –

+0

通常の重量とまったく同じです。しかしバイアスユニットの出力を1と見なすと、バイアスの更新ルールは、i番目のニューロン= error signal_ofithneuron * learning_rateのデルタバイアスになります。 – viceriel

+0

私は偏りを入れました。小さなデータセットの場合、ネットワークは以前より速く学習していますが、それはまだ大きなデータセットの出力が0に収束するという問題があります。 –

1

これは重量の初期化に問題があるようです。

私の知る限り、重みを特定の値に初期化することはありません。したがって、ネットワークは発散する。少なくともランダムな初期化を使用する必要があります。

+0

ランダムで初期化します値、私はちょうどコードのその部分を投稿していません –

+0

それから私は学習率を調整するでしょう。あなたのネットワークを広げることができる他のものの1つです。さらに、入力データが逆になる可能性があり、これも収束に影響します。 –

+0

学習率が高いか低いかをお勧めしますか?また、トレーニング中に学習率を変えるのが最善ではないでしょうか? –

関連する問題