当前位置: 首页 > 知识库问答 >
问题:

神经网络收敛不良

谈渊
2023-03-14

在过去的两周里,我读了很多关于NN的文章,我想我在网上看到了几乎所有的“XOR”方法教程。但是,我无法使工作成为我自己的工作。我从一个简单的“OR”神经元方法开始。给出良好的结果。我认为我的问题是反向传播的实现。我做了一个对象方法,所以这里是主线。

三类:

神经元

public class Neuron {

/*
 * Attributes
 */

double[] inputs;
double[] weights;

double output;
double error;

double delta;
double deltaWeight;

/*
 * Constructors
 */

public Neuron(int nInputs) 
{
    inputs = new double[nInputs + 1];
    inputs[inputs.length - 1] = 1; // bias
    weights = new double[nInputs + 1];
}

/*
 * Methods
 */

/**
 * Reset all weights of the neuron to random values between -1 and 1
 */
public void reset()
{       
    Random random = new Random();
    for (int i = 0; i < weights.length; i++)
        weights[i] = (random.nextDouble() * ((0.5d - (-0.5d))) + (-0.5d));
}

/**
 * Compute output for given inputs
 * @param inputs
 */
public void computeOutput(double inputs[])
{
    setInputs(inputs);
    output = Sigmoid.activation(getDotProduct());
}

/**
 * Compute error for given ideal
 * @param ideal
 */
public void computeError(double ideal)
{
    error = ideal - output;
    delta = error;
}

/**
 * Compute error for hidden neurons
 */
public void computeError(FeedForwardLayer previousLayer, int position)
{
    double sum = 0;
    for (int i = 0; i < previousLayer.neurons.length; i++)
        sum += (previousLayer.neurons[i].delta * previousLayer.neurons[i].weights[position]);

    delta = Sigmoid.derivative(getDotProduct()) * sum;
    error = delta;
}

/**
 * Adjust every weight of the neuron
 */
public void adjustWeights(double lambda, double momentum)
{
    for (int i = 0; i < weights.length; i++) 
    {
        double lastDeltaWeight = deltaWeight;
        deltaWeight = lambda * (delta * inputs[i]) + momentum * lastDeltaWeight;
        weights[i] += deltaWeight;
    }
}

@Override
public String toString() 
{
    String str = "";
    for (int i = 0; i < weights.length; i++)
        str = str.concat(String.format("IN|W --> %.6f | %.6f \n", (float) inputs[i], (float) weights[i]));

    str = str.concat("Output = " + output + "\n");
    str = str.concat("Error = " + error + "\n");
    return str;
}

/*
 * Getters & Setters
 */

/**
 * @return weights * inputs + bias
 */
public double getDotProduct()
{
    double sum = 0;
    for (int i = 0; i < inputs.length; i++)
        sum += (weights[i] * inputs[i]);

    return sum;
}

/**
 * Set inputs (keep bias input)
 * @param inputs
 */
public void setInputs(double[] inputs)
{
    for (int i = 0; i < inputs.length; i++)
        this.inputs[i] = inputs[i];
}

/**
 * Set every weight to a single value
 * @param weight
 */
public void setWeights(double weight)
{
    for (int i = 0; i < weights.length; i++)
        this.weights[i] = weight;
}
}

前馈层(包含神经元)

public class FeedForwardLayer {

/*
 * Attributes
 */

Neuron[] neurons;
LayerTypes type;

/*
 * Constructors
 */

/**
 * First layer constructor
 * @param nNeurons
 */
public FeedForwardLayer(int nInputs, int nNeurons, LayerTypes type) 
{
    neurons = new Neuron[nNeurons];
    for (int i = 0; i < neurons.length; i++)
        neurons[i] = new Neuron(nInputs);

    this.type = type;
}

/*
 * Methods
 */

/**
 * Reset all weights of the layer's neurons to random values between -1 and 1
 */
public void reset()
{
    for (Neuron neuron : neurons) 
        neuron.reset();
}

/**
 * Compute output, if layer isn't input one, you can pass null into parameter
 * @param inputs
 */
public void computeOutputs(double[] inputs)
{
    for (int i = 0; i < neurons.length; i++) 
        neurons[i].computeOutput(inputs);
}

/**
 * Compute error, if layer is output one
 * @param ideals
 */
public void computeErrors(double[] ideals)
{
    for (int i = 0; i < neurons.length; i++)
        neurons[i].computeError(ideals[i]);
}

/**
 * Compute error, if layer isn't output one
 * @param layer n+1
 */
public void computeErrors(FeedForwardLayer next)
{
    for (int i = 0; i < neurons.length; i++)
        neurons[i].computeError(next, i);
}

/**
 * Adjust weights for every neurons
 */
public void adjustWeights(double lambda, double momentum)
{
    for (Neuron neuron : neurons) 
        neuron.adjustWeights(lambda, momentum);
}

@Override
public String toString()
{
    String str = "";
    for (int i = 0; i < neurons.length; i++)
        str = str.concat("Neuron " + i + "\n" + neurons[i]);
    return str;
}

/*
 * Getters - Setters
 */

/**
 * @return true if layer is input, false otherwise
 */
public boolean isInput()
{
    if (type == LayerTypes.INPUT)
        return true;

    return false;
}

/**
 * @return true if layer is input, false otherwise
 */
public boolean isOutput()
{
    if (type == LayerTypes.OUTPUT)
        return true;

    return false;
}

/**
 * @return an array of layer's outputs
 */
public double[] getOutputs()
{
    double[] outputs = new double[neurons.length];

    for (int i = 0; i < neurons.length; i++) 
        outputs[i] = neurons[i].output;

    return outputs;
}

/**
 * @return array of layer's errors
 */
public double[] getErrors()
{
    double[] errors = new double[neurons.length];

    for (int i = 0; i < neurons.length; i++)
        errors[i] = neurons[i].error;

    return errors;
}

/**
 * Set all the weights of the layer to given weight
 * @param weight
 */
public void setWeights(double weight)
{
    for (int i = 0; i < neurons.length; i++)
        neurons[i].setWeights(weight);
}
}

前馈网络(包含前馈层)

public class FeedForwardNetwork {

static final double lambda = 0.1;
static final double momentum = 0;

/*
 * Attributes
 */

private ArrayList<FeedForwardLayer> layers;

/*
 * Constructors
 */

public FeedForwardNetwork() 
{
    layers = new ArrayList<FeedForwardLayer>();
}

/*
 * Methods
 */

/**
 * Init all the weights to random values
 */
public void reset()
{       
    for (int i = 0; i < layers.size(); i++)
        layers.get(i).reset();;
}

/**
 * Compute output for all the neurons of all the layers for given inputs
 * @param inputs
 */
public void feedForward(double[] inputs)
{
    //System.err.println("FeedForwardNetwork.feedForward(" + inputs[0] + ", " + inputs[1] +")");
    for (int i = 0; i < layers.size(); i++) 
    {
        //System.err.println("\n*** COMPUTING OUTPUT FOR LAYER " + i + "***\n");
        if (layers.get(i).isInput())
            layers.get(i).computeOutputs(inputs);
        else
            layers.get(i).computeOutputs(layers.get(i - 1).getOutputs());
    }
}

/**
 * Compute errors for all the neurons of all the layers starting by output layer
 * @param ideals
 */
public void feedBackward(double[] ideals)
{
    //System.err.println("FeedForwardNetwork.feedBackward(" + ideals[0] + ")");
    // For each layers starting by output one
    for (int i = layers.size() - 1; i > 0; i--) 
    {
        //System.err.println("*** COMPUTING ERROR FOR LAYER " + i + "***");
        if (layers.get(i).isOutput())
            layers.get(i).computeErrors(ideals);
        else
            layers.get(i).computeErrors(layers.get(i + 1));
    }
}

/**
 * Adjust weights of every layer
 */
public void adjustWeights()
{
    for (FeedForwardLayer feedForwardLayer : layers) 
        feedForwardLayer.adjustWeights(lambda, momentum);
}

/**
 * Train the nn with given inputs and outputs
 * @param inputs
 * @param outputs
 */
public void train(double[] inputs, double... outputs)
{
    feedForward(inputs);
    feedBackward(outputs);
    adjustWeights();
}

/**
 * Add a layer to the network
 * @param layer
 */
public void addLayer(FeedForwardLayer layer)
{
    layers.add(layer);
}

@Override
public String toString() 
{
    String str = "";
    for (int i = 0; i < layers.size(); i++)
        str = str.concat("Layer " + LayerTypes.values()[i] + "\n" + layers.get(i));

    str = str.concat("\n");
    str = str.concat("OUTPUT = " + getOutputs()[0] + "\n");
    str = str.concat("ERROR = "  + getError(false) + "\n");
    return str;
}
/*
 * Getters & Setters
 */

public FeedForwardLayer getInputLayer()
{
    return layers.get(0);
}

public FeedForwardLayer getOutputLayer()
{
    return layers.get(layers.size() - 1);
}

public FeedForwardLayer getLayer(int index)
{
    return layers.get(index);
}

public double getError(boolean abs)
{
    if (abs)
        return Math.abs(getOutputLayer().neurons[0].error);

    return getOutputLayer().neurons[0].error;
}

public double[] getOutputs()
{
    return getOutputLayer().getOutputs();
}
}

所以我通过给网络赋予异或表xor表的历元来训练网络

X | Y | S
0   0   0
0   1   1
0   1   1
0   0   0

网络将在千历元后输出约0.5…有趣的是,如果我用AND表、OR表或NAND表替换训练集,nn将在训练集的S列中输出1的数字。(AND和NAND表格输出0.25,OR表格输出0.75)

我只想知道我的实现是否足够好,可以使其工作,ty!

共有1个答案

包德业
2023-03-14

所以,经过一些研究,我意识到我的实现很好,只是我不明白输入层是如何工作的。就是这样,输入层的工作原理类似于In=Out。

 类似资料:
  • 我一直在看一些关于深度学习/卷积神经网络的视频,比如这里和这里,我试图用C语言实现我自己的。在我第一次尝试时,我试图保持输入数据相当简单,所以我的想法是区分十字和圆,我有一个大约25个的小数据集(64*64个图像),它们如下所示: 网络本身有五层: 我的问题是我的网络没有收敛到任何东西上。权重似乎都没有改变。如果我运行它,预测基本保持不变,除了偶尔出现的异常值,它会在下一次迭代返回之前跳起来。 卷

  • 我实现了以下神经网络来解决Python中的异或问题。我的神经网络由2个神经元的输入层、1个2个神经元的隐藏层和1个神经元的输出层组成。我使用Sigmoid函数作为隐藏层的激活函数,使用线性(恒等式)函数作为输出层的激活函数: 反向传播似乎都是正确的;我想到的唯一问题是我在实现偏差单位时遇到的一些问题。无论哪种方式,每次运行代码时,每个输入的所有谓词都会收敛到大约0.5。我仔细检查了代码,似乎找不到

  • 我试图在DL4j中做一个简单的预测(稍后将用于具有n个特性的大型数据集),但无论我做什么,我的网络都不想学习,行为非常奇怪。当然,我学习了所有的教程,并执行了dl4j repo中显示的相同步骤,但不知何故,它对我不起作用。 对于虚拟特性,我使用以下数据: *双[val][x]特征;其中val=linspace(-10,10)...;和x=math.sqrt(math.abs(val))*val;

  • 神经网络 (Neural Network) 是机器学习的一个分支,全称人工神经网络(Artificial Neural Network,缩写 ANN),是一种模仿生物神经网络的结构和功能的数学模型或计算模型,用于对函数进行估计或近似。 Perceptron (感知器) 一个典型的神经网络由输入层、一个或多个隐藏层以及输出层组成,其中箭头代表着数据流动的方向,而圆圈代表激活函数(最常用的激活函数为

  • 译者:bat67 最新版会在译者仓库首先同步。 可以使用torch.nn包来构建神经网络. 我们以及介绍了autograd,nn包依赖于autograd包来定义模型并对它们求导。一个nn.Module包含各个层和一个forward(input)方法,该方法返回output。 例如,下面这个神经网络可以对数字进行分类: 这是一个简单的前馈神经网络(feed-forward network)。它接受一

  • 我玩神经网络。我了解卷积层、完全连接层和许多其他东西是如何工作的。我还知道什么是梯度,以及如何训练这样的网络。 框架千层面包含一个称为InverseLayer的层。 InverseLayer类通过应用要反转的层相对于其输入的偏导数,对神经网络的单层执行反转操作。 我不知道这是什么意思,或者我应该在什么时候使用这个层。或者倒置偏导数背后的想法是什么? 非常感谢你