2010-11-16 3 views
2

Я пытаюсь научить нейронную сеть 2 входам, 4 скрытым узлам (все на одном уровне) и 1 выходному узлу. Бинарное представление работает отлично, но у меня проблемы с Bipolar. Я не могу понять, почему, но общая ошибка иногда сходится к тому же числу около 2.xx. Мой сигмоид равен 2/(1+ exp (-x)) - 1. Возможно, я сигмоид в неправильном месте. Например, чтобы вычислить выходную ошибку, следует ли сравнивать сигмоидный результат с ожидаемым значением или с ожидаемым значением sigmoided?Преподавание нейронной сети: биполярный XOR

Я следил за этим сайтом здесь: http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html, но они используют разные функции, после чего мне было поручено использовать. Даже когда я пытался реализовать свои функции, я все еще сталкивался с той же проблемой. В любом случае я получаю около половины времени на одном и том же номере (другое число для разных реализаций). Скажите, пожалуйста, если я допустил ошибку в моем коде где-нибудь или если это нормально (я не понимаю, как это может быть). Momentum установлен в 0. Является ли это общей проблемой с импульсом 0? Функции ошибок мы должны использовать, являются:

, если пользовательский интерфейс выходной блок

Error(i) = (Ci - ui) * f'(Si)

если щ скрытый блок

Error(i) = Error(Output) * weight(i to output) * f'(Si)

public double sigmoid(double x) { 
    double fBipolar, fBinary, temp; 
    temp = (1 + Math.exp(-x)); 
    fBipolar = (2/temp) - 1; 
    fBinary = 1/temp; 
    if(bipolar){ 
     return fBipolar; 
    }else{ 
     return fBinary; 
    } 

} 

// Initialize the weights to random values. 
private void initializeWeights(double neg, double pos) { 
    for(int i = 0; i < numInputs + 1; i++){ 
     for(int j = 0; j < numHiddenNeurons; j++){ 
      inputWeights[i][j] = Math.random() - pos; 
      if(inputWeights[i][j] < neg || inputWeights[i][j] > pos){ 
       print("ERROR "); 
       print(inputWeights[i][j]); 
      } 
     } 
    } 
    for(int i = 0; i < numHiddenNeurons + 1; i++){ 
     hiddenWeights[i] = Math.random() - pos; 
     if(hiddenWeights[i] < neg || hiddenWeights[i] > pos){ 
      print("ERROR "); 
      print(hiddenWeights[i]); 
     } 
    } 
} 

// Computes output of the NN without training. I.e. a forward pass 
public double outputFor (double[] argInputVector) { 
    for(int i = 0; i < numInputs; i++){ 
     inputs[i] = argInputVector[i]; 
    } 
    double weightedSum = 0; 
    for(int i = 0; i < numHiddenNeurons; i++){ 
     weightedSum = 0; 
     for(int j = 0; j < numInputs + 1; j++){ 
      weightedSum += inputWeights[j][i] * inputs[j]; 
     } 
     hiddenActivation[i] = sigmoid(weightedSum); 
    } 

    weightedSum = 0; 
    for(int j = 0; j < numHiddenNeurons + 1; j++){ 
     weightedSum += (hiddenActivation[j] * hiddenWeights[j]); 
    } 

    return sigmoid(weightedSum); 
} 

    //Computes the derivative of f 
public static double fPrime(double u){ 
    double fBipolar, fBinary; 
    fBipolar = 0.5 * (1 - Math.pow(u,2)); 
    fBinary = u * (1 - u); 
    if(bipolar){ 
     return fBipolar; 
    }else{ 
     return fBinary; 
    } 
} 

// This method is used to update the weights of the neural net. 
public double train (double [] argInputVector, double argTargetOutput){ 
    double output = outputFor(argInputVector); 
    double lastDelta; 

    double outputError = (argTargetOutput - output) * fPrime(output); 

    if(outputError != 0){ 
     for(int i = 0; i < numHiddenNeurons + 1; i++){ 
      hiddenError[i] = hiddenWeights[i] * outputError * fPrime(hiddenActivation[i]); 
      deltaHiddenWeights[i] = learningRate * outputError * hiddenActivation[i] + (momentum * lastDelta); 
      hiddenWeights[i] += deltaHiddenWeights[i]; 
     } 

     for(int in = 0; in < numInputs + 1; in++){ 
      for(int hid = 0; hid < numHiddenNeurons; hid++){ 
       lastDelta = deltaInputWeights[in][hid]; 
       deltaInputWeights[in][hid] = learningRate * hiddenError[hid] * inputs[in] + (momentum * lastDelta); 
       inputWeights[in][hid] += deltaInputWeights[in][hid]; 
      } 
     } 
    } 

    return 0.5 * (argTargetOutput - output) * (argTargetOutput - output); 
} 

ответ

3

Общее кодирование комментарии:

initializeWeights(-1.0, 1.0); 

может фактически не получить начальные значения, которые вы ожидали.

initializeWeights, вероятно, следует:

inputWeights[i][j] = Math.random() * (pos - neg) + neg; 
// ... 
hiddenWeights[i] = (Math.random() * (pos - neg)) + neg; 

вместо:

Math.random() - pos; 

так, что это работает:

initializeWeights(0.0, 1.0); 

и дает начальные значения между 0,0 и 1,0, а не между -1,0 и 0,0.

lastDelta используется, прежде чем он объявлен:

deltaHiddenWeights[i] = learningRate * outputError * hiddenActivation[i] + (momentum * lastDelta); 

Я не уверен, если + 1 на numInputs + 1 и numHiddenNeurons + 1 необходимы.

Не забывайте следить за округлением цепей: 5/2 = 2, а не 2.5! Вместо этого используйте 5.0/2.0. В общем случае добавьте .0 в свой код, когда вывод должен быть двойным.

Самое главное, вы достаточно долго тренировали NeuralNet?

Попробуйте запустить его с numInputs = 2, numHiddenNeurons = 4, learningRate = 0.9 и поезд на 1000 или 10000 раз.

Использование numHiddenNeurons = 2 иногда пытается «застревать» при попытке решить проблему XOR.

См. Также XOR problem - simulation

Смежные вопросы