【问题标题】:Training neural network for function approximation用于函数逼近的训练神经网络
【发布时间】:2012-05-14 18:21:20
【问题描述】:

我完全没有神经网络方面的经验,现在我只是在玩 FANN 库来学习它们。所以目标是训练网络逼近正弦函数。为此,我使用 3 层 NN 1 个输入、3 个隐藏和 1 个输出神经元。代码是

const unsigned int num_input = 1;
const unsigned int num_output = 1;
const unsigned int num_layers = 3;
const unsigned int num_neurons_hidden = 3;

struct fann *ann;

ann = fann_create_standard(num_layers, num_input, num_neurons_hidden, num_output);

fann_set_activation_steepness_hidden(ann, 1);
fann_set_activation_steepness_output(ann, 1);

fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);

fann_set_train_stop_function(ann, FANN_STOPFUNC_BIT);
fann_set_bit_fail_limit(ann, 0.01f);

fann_set_training_algorithm(ann, FANN_TRAIN_RPROP);

fann_randomize_weights(ann, 0, 1);

for(int i=0; i<2; ++i) {
    for(float angle=0; angle<10; angle+=0.1) {
        float sin_anle = sinf(angle);
        fann_train(ann, &angle, &sin_anle);
    }
}

int k = 0;
for(float angle=0; angle<10; angle+=0.1) {
    float sin_anle = sinf(angle);
    float *o = fann_run(ann, &angle);
    printf("%d\t%f\t%f\t\n", k++, *o, sin_anle);
}

fann_destroy(ann);

但是,我得到的结果与真正的正弦函数无关。我认为我的网络设计存在一些根本性错误。

【问题讨论】:

  • 我目前找不到错误。但我不是 FANN 专家。您是否尝试过使用参数?优化算法(RPROP)、隐藏单元的数量、训练时期……实际上 2 个训练时期应该不够。我试图增加数量,但这并没有给我更好的结果。
  • @alfa 是的,我尝试了很多不同的参数。我认为问题在于只有1 in和1 output参数。
  • 你是对的。我会在一分钟内发布答案。

标签: c neural-network fann


【解决方案1】:

您在此行中选择优化算法 Resilient Backpropagation (Rprop):

fann_set_training_algorithm(ann, FANN_TRAIN_RPROP);

Rprop 是一种批量更新算法。这意味着您必须为每次更新提供整个训练集。 fann_train 的文档说

这种训练始终是增量训练(参见 fann_train_enum),因为只呈现一种模式。

所以适当的优化选项是FANN_TRAIN_INCREMENTAL。您必须使用以下方法之一进行批量学习:fann_train_on_datafann_train_on_filefann_train_epoch

我在更改您的代码时注意到的是:

  • 您的坡度太高了。我使用了默认值 (0.5)。
  • 您的训练周期太少。我用了大约 20,000 个。
  • 对于只有 3 个隐藏神经元来说,您的函数太复杂了。这一点都不容易,因为它是一个周期函数。所以我改变了我近似为 [0,3] 的正弦函数的范围,这要简单得多。
  • 位故障限制太硬。 :) 我将其设置为0.02f
  • Rprop 不是一个很好的训练算法,它们应该实现类似 Levenberg-Marquardt 的算法,它要快得多。

我得到的解决方案并不完美,但至少大致正确:

0       0.060097        0.000000
1       0.119042        0.099833
2       0.188885        0.198669
3       0.269719        0.295520
4       0.360318        0.389418
5       0.457665        0.479426
6       0.556852        0.564642
7       0.651718        0.644218
8       0.736260        0.717356
9       0.806266        0.783327
10      0.860266        0.841471
11      0.899340        0.891207
12      0.926082        0.932039
...

我使用了这个修改后的代码:

#include <cstdio>
#include <cmath>
#include <fann.h>
#include <floatfann.h>

int main()
{
  const unsigned int num_input = 1;
  const unsigned int num_output = 1;
  const unsigned int num_layers = 3;
  const unsigned int num_neurons_hidden = 2;

  const float angleRange = 3.0f;
  const float angleStep = 0.1;
  int instances = (int)(angleRange/angleStep);

  struct fann *ann;

  ann = fann_create_standard(num_layers, num_input, num_neurons_hidden, num_output);

  fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
  fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);

  fann_set_train_stop_function(ann, FANN_STOPFUNC_BIT);
  fann_set_bit_fail_limit(ann, 0.02f);

  fann_set_training_algorithm(ann, FANN_TRAIN_INCREMENTAL);

  fann_randomize_weights(ann, 0, 1);

  fann_train_data *trainingSet;
  trainingSet = fann_create_train(instances, 1, 1); // instances, input dimension, output dimension
  float angle=0;
  for(int instance=0; instance < instances; angle+=angleStep, instance++) {
      trainingSet->input[instance][0] = angle;
      trainingSet->output[instance][0] = sinf(angle);
  }

  fann_train_on_data(ann, trainingSet, 20000, 10, 1e-8f); // epochs, epochs between reports, desired error

  int k = 0;
  angle=0;
  for(int instance=0; instance < instances; angle+=angleStep, instance++) {
      float sin_angle = sinf(angle);
      float *o = fann_run(ann, &angle);
      printf("%d\t%f\t%f\t\n", k++, *o, sin_angle);
  }

  fann_destroy(ann);

  return 0;
}

请注意,fann_create_train 自 FANN 2.2.0 起可用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 2013-04-14
    • 2018-09-10
    • 2017-04-01
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多