首页 > 解决方案 > 错误反向传播陷入错误的值

问题描述

我目前正在做一项任务,需要我制作一个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)相乘来计算第一个净值,通过将第一个网络的“sigmoided”值(包括一个偏差)和权重(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]);
                }
            }
        }

    }

但这就是问题所在。我通过将学习率和误差梯度乘以以下公式来纠正权重的误差。 在此处输入图像描述 我想我必须对第二层使用 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;
}

但是当我打印出经过训练的输出时,它并没有接近预期的数据,而是卡在了一个特定的值上。 在此处输入图像描述

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

标签: cmachine-learningneural-networkartificial-intelligence

解决方案


在隐藏层神经元激活//Sum up net_v and produce o的加权输出在中累积的循环中,有一个错误的索引:vhnet_vk

                    net_v[n][k] += h[n][k] * v[k][j];

应该

                    net_v[n][k] += h[n][j] * v[k][j];

推荐阅读