c - 错误反向传播陷入错误的值
问题描述
我目前正在做一项任务,需要我制作一个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;
}
但是当我打印出经过训练的输出时,它并没有接近预期的数据,而是卡在了一个特定的值上。
我看到很多其他人都遇到过这种问题,他们的解决方案是给初始权重随机非零值或改变学习率或迭代次数。我已经这样做了很多次,但它似乎与我的问题不符。如果有人能告诉我我现在做错了什么,我将非常感激。
解决方案
在隐藏层神经元激活//Sum up net_v and produce o
的加权输出在中累积的循环中,有一个错误的索引:v
h
net_v
k
net_v[n][k] += h[n][k] * v[k][j];
应该
net_v[n][k] += h[n][j] * v[k][j];
推荐阅读
- postgresql - 错误:关系“部门”不存在 SQL 状态:42P01 PostgreSQL
- swift - SwiftUI - 在保持 TabView 可滑动的同时检测长按
- java - 如何将我的高分存储在某个地方,以便我可以使用它们从商店购买?如何管理我的总分和高分
- typescript - 无法返回 Firebase 云存储上快照的值
- python - 为什么 Pillow.Image.open() 在 jupyter 中而不是终端/控制台中显示图像?
- docker - 在 shell 中以交互模式启动 Docker 容器
- python - 如何使用python将文本放在多个图像上?
- php - 为什么 for loop php 输出这个结果?
- swift - SwiftUI:如何在 macOS 中保存窗口的大小?
- visual-studio-code - 罕见的 unicode 字符后制表位被搞砸了