简体   繁体   English

训练神经网络进行函数逼近

[英]Training neural network for function approximation

I've got absolutely no experience with neural networks and for now I'm just playing with FANN library to learn them. 我对神经网络完全没有经验,现在我只是在玩FANN库来学习它们。 So the objective is to train the network to approximate the sine function. 因此,目标是训练网络以近似正弦函数。 For that I'm using 3 layer NN 1 input, 3 hidden and 1 output neuron. 为此,我使用3层NN 1输入,3隐藏和1输出神经元。 the code is 该代码是

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);

However I've got results that has nothing to do with the real sine function. 但是,我得到的结果与真正的正弦函数无关。 I suppose that there is some fundamental error in my network design. 我想我的网络设计中存在一些基本错误。

You choose the optimization algorithm Resilient Backpropagation (Rprop) in this line: 您可以在以下行中选择优化算法弹性反向传播(Rprop):

fann_set_training_algorithm(ann, FANN_TRAIN_RPROP);

Rprop is a batch update algorithm. Rprop是一个批处理更新算法。 This means you have to present the whole training set for each update. 这意味着您必须提供每次更新的整个培训集。 The documentation for fann_train says fann_train的文档说

This training is always incremental training (see fann_train_enum), since only one pattern is presented. 此训练始终是增量训练(请参阅fann_train_enum),因为仅显示了一种模式。

So the appropriate optimization option would be FANN_TRAIN_INCREMENTAL . 因此,合适的优化选项将是FANN_TRAIN_INCREMENTAL You have to use one of these methods for batch learning: fann_train_on_data , fann_train_on_file or fann_train_epoch . 您必须使用以下方法之一进行批处理学习: fann_train_on_datafann_train_on_filefann_train_epoch

What I noticed when I changed your code was: 当我更改您的代码时,我注意到的是:

  • Your steepness is too high. 你的陡度太高了。 I used the default value (0.5). 我使用默认值(0.5)。
  • You have too few training epochs. 您的训练时期太少了。 I use about 20,000. 我用了大约20,000。
  • Your function is too complex for only 3 hidden neurons. 您的功能太复杂,仅3个隐藏的神经元。 It is not easy at all because it is a periodic function. 根本不容易,因为它是周期函数。 So I changed the range of the sine function I approximated to [0,3] which is much simpler. 因此,我将正弦函数的范围更改为[0,3],这非常简单。
  • The bit fail limit is too hard. 位失败限制太难了。 :) I set it to 0.02f . :)我将其设置为0.02f
  • Rprop is not a very good training algorithm, they should implement something like Levenberg-Marquardt, which is much faster. Rprop不是一个很好的训练算法,他们应该实现像Levenberg-Marquardt这样的东西,它要快得多。

The solution I got is not perfect but it is at least approximately correct: 我得到的解决方案并不完美,但至少是正确的:

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
...

I used this modified code: 我使用了以下修改的代码:

#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;
}

Note that fann_create_train is available since FANN 2.2.0. 请注意, fann_create_train自FANN 2.2.0起可用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM