neural-network - 教学神经网络 : Bipolar XOR

标签 neural-network xor

我正在尝试教授一个由 2 个输入、4 个隐藏节点(全部位于同一层)和 1 个输出节点组成的神经网络。二进制表示工作正常,但我对双极有问题。我不明白为什么,但总误差有时会收敛到 2.xx 左右的相同数字。我的 sigmoid 是 2/(1+ exp(-x)) - 1。也许我在错误的地方进行了 sigmoid 处理。例如,要计算输出误差,我应该将 sigmoid 输出与预期值进行比较,还是与 sigmoid 预期值进行比较?

我在这里关注了这个网站:http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html ,但它们使用的功能与我被指示使用的功能不同。即使当我尝试实现它们的功能时,我仍然遇到同样的问题。不管怎样,我大约有一半的时间被困在相同的数字上(不同的实现有不同的数字)。请告诉我我的代码是否在某个地方犯了错误或者这是否正常(我不明白这是怎么回事)。动量设置为 0。这是常见的 0 动量问题吗?我们应该使用的错误函数是:

如果 ui 是输出单位

误差(i) = (Ci - ui ) * f'(Si )

如果 ui 是隐藏单元

误差(i) = 误差(输出) * 权重(i 到输出) * 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);
}

最佳答案

一般编码注释:

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);

我不确定 numInputs + 1numHiddenNeurons + 1 上的 + 1 是否必要。

记住要注意整数的舍入:5/2 = 2,而不是 2.5! 请改用 5.0/2.0。一般来说,当输出应该是 double 时,请在代码中添加 .0。

最重要的是,您对 NeuralNet 的训练时间是否足够长?

尝试使用 numInputs = 2、numHiddenNeurons = 4、learningRate = 0.9 运行它,并训练 1,000 或 10,000 次。

使用 numHiddenNeurons = 2 在尝试解决 XOR 问题时有时会“卡住”。

另请参阅XOR problem - simulation

关于neural-network - 教学神经网络 : Bipolar XOR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4190494/

相关文章:

java - 为什么这条语句在java中不起作用 x ^= y ^= x ^= y;

c++ - 使用字母字符加密/解密 XOR

python-3.x - 如何加载经过训练的自动编码器(Keras)、获取编码器部分并将其卡住?

python - 如何将两个训练有素的神经网络权重矩阵合并为一个?

python - tensorflow 不训练(只有偏见改变)

python - 了解 CRC8 SAE J1850(正常)与 "Zero"的结果

python - 在Python中查找两个列表之间单个不同元素的索引的有效方法

c - 在具有整数的数组中,一个值在数组中出现两次。你如何确定是哪一个?

php - 如何将神经网络从 C 语言转换为 PHP

python - 如何迭代 Tensorflow 中的张量?