错误反向传播陷入错误的值

时间:2019-06-11 15:43:09

标签: c machine-learning neural-network artificial-intelligence

我目前正在做一项作业,要求我建立一个f(x) = x(1-x)的神经网络。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define ITER 300000
#define L_RATE 0.5
#define N 11
#define I 1
#define J 4
#define K 1
#define SIGMOID(x) (1/(1+exp(-(x))))

因此,我目前正在使用4个隐藏节点(J)和学习率0.5(L_RATE),并计划将11个数据(N)作为训练的输入。

double error_v(double o, double t, double h)
{
    return -(t-o)*o*(1-o)*h;
}


double error_w(double x, double h, double w, double t, double o)
{
    return -x*h*(1-h)*w*(t-o)*o*(1-o);
}

这些将是每层重量的误差梯度。

int main(void)
{
    double x[N][I]; 
    double t[N][K];
    double w[J][I+1];
    double v[K][J+1];
    double net_w[N][J];
    double net_v[N][K];
    double h[N][J];
    double o[N][K];

    for(int n=0; n<N; n++)
    {
        for(int i=0; i<I; i++)
        {
            x[n][i] = 0.1 * n;
            t[n][i] = x[n][i] * (1 - x[n][i]);
        }
    }

    //INITIALIZE WEIGHT
    srand(time(NULL));
    for(int j=0; j<J; j++)
    {
        for(int i=0; i<I+1; i++)
        {
            w[j][i] = (double)rand()/RAND_MAX*2.0-1.0;
            printf("%.2f ", w[j][i]);
        }
    }
    for(int k=0; k<K; k++)
    {
        for(int j=0; j<J+1; j++)
        {
            v[k][j] = (double)rand()/RAND_MAX*2.0-1.0;
            printf("%.2f ", v[k][j]);
        }
    }

    for(int iter=0; iter<ITER; iter++)
    {   
        for(int n=0; n<N; n++)
        {
            //Initialize net zero
            for(int j=0; j<J; j++)
            {
                net_w[n][j] = 0;
            }
            for(int k=0; k<K; k++)
            {
                net_v[n][k] = 0;
            }
            //Sum up net_w and produce h
            for(int j=0; j<J; j++)
            {
                for(int i=0; i<I; i++)
                {
                    net_w[n][j] += x[n][i] * w[j][i];
                }
                net_w[n][j] += 1 * w[j][I];
                h[n][j] = SIGMOID(net_w[n][j]);
            }
            //Sum up net_v and produce o
            for(int k=0; k<K; k++)
            {
                for(int j=0; j<J; j++)
                {
                    net_v[n][k] += h[n][k] * v[k][j];
                }
                net_v[n][k] += 1 * v[k][J];
                o[n][k] = SIGMOID(net_v[n][k]);
            }
        }

所以直到这里,我通过将输入(包括一个偏差)和权重(w)相乘来计算第一个净值,并通过将第一个网络(包括一个偏差)的“ S”形值乘以权重来计算第二个净值(v)。

        for(int n=0; n<N; n++)
        {
            //error_v
            for(int k=0; k<K; k++)
            {
                for(int j=0; j<J; j++)
                {
                    v[k][j] -= L_RATE * error_v(o[n][k], t[n][k], h[n][j]);
                }
                v[k][J] -= L_RATE * error_v(o[n][k], t[n][k], 1);
            }
        }
        for(int n=0; n<N; n++)
        {
            //error_w
            for(int j=0; j<J; j++)
            {
                for(int i=0; i<I; i++)
                {
                    for(int k=0; k<K; k++)
                    {
                        w[j][i] -= L_RATE * error_w(x[n][i], h[n][j], w[k][j], t[n][k], o[n][k]);
                    }
                }
                for(int k=0; k<K; k++)
                {
                    w[j][I] -= L_RATE * error_w(1, h[n][j], w[k][j], t[n][k], o[n][k]);
                }
            }
        }

    }

但这是问题所在。通过将学习率和误差梯度乘以以下公式,校正了权重的误差。 enter image description here 我以为我必须在输入层,隐藏层,输出层和训练数据的每个数量上对第二层使用3-for-loop,对第二层使用4-for-loop。

    printf("INPUT\n");
    for(int n=0; n<N; n++)
    {
        printf("%.2f ", x[n][0]);
    }
    printf("\n");
    printf("OUTPUT\n");
    for(int n=0; n<N; n++)
    {
        printf("%.2f ", o[n][0]);
    }
    printf("\n");
    printf("EXPECTED\n");
    for(int n=0; n<N; n++)
    {
        printf("%.2f ", t[n][0]);
    }
    printf("\n");

    return 0;
}

但是,当我打印出经过训练的输出时,它并没有接近预期的数据,而是停留在特定的值上。 enter image description here

我看到许多其他人都遇到过这种问题,他们的解决方案是给初始权重赋予随机的非零值或更改学习率或迭代次数。我已经做过很多次了,但这似乎与我的问题不符。如果有人能告诉我我现在做错了,我将非常感谢。

1 个答案:

答案 0 :(得分:1)

在循环//Sum up net_v and produce o中,隐藏层神经元激活v的{​​{1}}加权输出累积在h中,存在错误的索引{{1} }:

net_v

应该是

k