次の行で、最適化アルゴリズムの Resilient Backpropagation (Rprop) を選択します。
fann_set_training_algorithm(ann, FANN_TRAIN_RPROP);
Rpropはバッチ更新アルゴリズムです。これは、更新ごとにトレーニング セット全体を提示する必要があることを意味します。fann_trainのドキュメントには、
提示されるパターンは 1 つだけなので、このトレーニングは常に増分トレーニングです (fann_train_enum を参照)。
したがって、適切な最適化オプションはFANN_TRAIN_INCREMENTAL
. バッチ学習fann_train_on_data
には、 、fann_train_on_file
またはのいずれかの方法を使用する必要がありfann_train_epoch
ます。
コードを変更したときに気づいたことは次のとおりです。
- あなたの急勾配は高すぎます。デフォルト値 (0.5) を使用しました。
- トレーニング エポックが少なすぎます。20万くらい使ってる
- 関数が複雑すぎて、隠れニューロンが 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 以降で利用可能であることに注意してください。