2

すでにここで説明したように、Torch/Lua にシャム ニューラル ネットワークを実装しようとしています。これで、最初の実装ができました。これは良いと思います。

残念ながら、私は問題に直面しています: バックプロパゲーションのトレーニング中に、勾配降下はエラーを更新しません。つまり、常に同じ値 (+1 または -1) を変更せずに計算します。正しい実装では、エラーは +1 から -1 または -1 から +1 になるはずです。私の場合、上限値にとどまっているだけで、何も変わりません。

なんで?ヒントをくれる人を本当に探しています。

実行しようとする可能性のある私の作業コードは次のとおりです。

LEARNING_RATE_CONST = 0.01;
output_layer_number = 1;
MAX_ITERATIONS_CONST = 10;

require 'os'
require 'nn'

-- rounds a real number num to the number having idp values after the dot
function round(num, idp)
  local mult = 10^(idp or 0)
  return math.floor(num * mult + 0.5) / mult
end

-- gradient update for the siamese neural network
function gradientUpdate(perceptron, dataset_vector, targetValue, learningRate, max_iterations)

print('gradientUpdate()\n')

  for i = 1, max_iterations do

      predictionValue = perceptron:forward(dataset_vector)[1]
      sys.sleep(0.2)
      gradientWrtOutput = torch.Tensor({-targetValue});

      perceptron:zeroGradParameters()
      perceptron:backward(dataset_vector, gradientWrtOutput) -- 

      perceptron:updateParameters(learningRate)

      predictionValue = perceptron:forward(dataset_vector)[1]
      io.write("i="..i..") optimization predictionValue= "..predictionValue.."\n");

      if(predictionValue==targetValue) then
      io.write("\t@@@ (i="..i..") optimization predictionValue "..predictionValue.." @@@\n");
      break
    end

    end
  return perceptron;
end

input_number = 6; -- they are 6
dim = 10
hiddenUnits = 3

trueTarget=1; falseTarget=-trueTarget; 

trainDataset = {}; targetDataset = {};
for i=1, dim do
     trainDataset[i]={torch.rand(input_number),  torch.rand(input_number)}
     if i%2==0 then targetDataset[i] = trueTarget
     else  targetDataset[i] = falseTarget 
     end
      -- print('targetDataset['..i..'] '..targetDataset[i]);
      -- sys.sleep(0.2)
end

for i=1, dim do
  for j=1, input_number do
     print(round(trainDataset[i][1][j],2)..' '..round(trainDataset[i][2][j],2));
  end
end

-- imagine we have one network we are interested in, it is called "perceptronUpper"
    perceptronUpper= nn.Sequential()
    print('input_number='..input_number..'\thiddenUnits='..hiddenUnits);
    perceptronUpper:add(nn.Linear(input_number, hiddenUnits))
    perceptronUpper:add(nn.Tanh())
    if dropOutFlag==TRUE then perceptronUpper:add(nn.Dropout()) end

    perceptronUpper:add(nn.Linear(hiddenUnits,output_layer_number))
    perceptronUpper:add(nn.Tanh())

    perceptronLower = perceptronUpper:clone('weight', 'gradWeight', 'gradBias', 'bias')

    parallel_table = nn.ParallelTable()
    parallel_table:add(perceptronUpper)
    parallel_table:add(perceptronLower)

    perceptron= nn.Sequential()
    perceptron:add(parallel_table)
    perceptron:add(nn.CosineDistance())

    max_iterations = MAX_ITERATIONS_CONST;
    learnRate = LEARNING_RATE_CONST;


    -- # TRAINING:
    for k=1, dim do
      print('\n[k='..k..'] gradientUpdate()');
      perceptron = gradientUpdate(perceptron, trainDataset[k], targetDataset[k], learnRate, max_iterations)
    end

問題は、 predictionValue変数が常に同じである理由です。更新が届かないのはなぜですか?

編集:問題は、出力レイヤーの次元を1つしか使用していないことに気付きました。6に移動しましたが、残念ながら新たな問題が発生しました。グラデーションが正しい方向に更新されていません。たとえば、前のコードを output_layer_number=6 で使用すると、次のようになります。

i=1) predictionValue=0.99026757478549 target=-1
i=2) predictionValue=0.9972249767451 target=-1
i=3) predictionValue=0.95910828489725 target=-1
i=4) predictionValue=0.98960431921481 target=-1
i=5) predictionValue=0.9607511165448 target=-1
i=6) predictionValue=0.7774414068913 target=-1
i=7) predictionValue=0.78994300446018 target=-1
i=8) predictionValue=0.96893163039218 target=-1
i=9) predictionValue=0.99786687264848 target=-1
i=10) predictionValue=0.92254348014872 target=-1
i=11) predictionValue=0.84935926907926 target=-1
i=12) predictionValue=0.93696147024616 target=-1
i=13) predictionValue=0.93469525917962 target=-1
i=14) predictionValue=0.9584800936415 target=-1
i=15) predictionValue=0.99376832219916 target=-1
i=16) predictionValue=0.97381161559835 target=-1
i=17) predictionValue=0.94124227912993 target=-1
i=18) predictionValue=0.94947181918451 target=-1
i=19) predictionValue=0.9946839455962 target=-1
i=20) predictionValue=0.9637013147803 target=-1
i=21) predictionValue=0.94853981221519 target=-1
i=22) predictionValue=0.95441294067747 target=-1
i=23) predictionValue=0.99999485148281 target=-1
i=24) predictionValue=0.9900480694373 target=-1
i=25) predictionValue=0.99316158138794 target=-1

つまり、predictionValue が -1 になることはありません。なんで?

4

1 に答える 1

3

なぜpredictionValue変数は常に同じなのですか? 更新が届かないのはなぜですか?

まずpredictionValue*targetValue < 1、ペアを一緒に押したり ( targetValue = 1) 離したり( ) する必要がある場合にのみ逆伝播するようにする場合にのみ、逆伝播を実行する必要がありtargetValue = -1ます。

これを説明するこの torch/nnの公式の例も参照してください。

そうは言っても、出力ユニットは 1 つしかありません( output_layer_number = 1)。これは、シャム ネットワークの各ブランチがそれぞれ 1 つのスカラーを生成することを意味します。uv。次に、このスカラーのペアが余弦距離によって比較されます。

C(u,v) = cosine(u, v) = (u / |u|) x (v / |v|)

注: この基準は、ここでは 1 または -1 の 2 つの値のみを取ることができます (以下の青色の部分を参照)。

逆伝播するときは、この基準の導関数を入力、つまりdC/duおよびに対して計算しますdC/dv。しかし、これらの導関数は nullであり、0 では未定義です (以下の赤字を参照)。

ここに画像の説明を入力

これが、バックプロパゲーションがここで何もしない理由です。つまり、静的なままです (これらの導関数のノルムを出力することで、実際にこれを確認できます)。

于 2015-06-13T11:34:38.207 に答える