mirror of
https://github.com/codeplea/genann.git
synced 2026-09-17 14:33:36 +00:00
Add convergence and gradient tests for tanh and relu backpropagation
This commit is contained in:
108
test.c
108
test.c
@@ -193,6 +193,108 @@ void train_xor() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef genann_act
|
||||||
|
void train_xor_act(genann_actfun act) {
|
||||||
|
double input[4][2] = {{0, 0}, {0, 1}, {1, 0}, {1, 1}};
|
||||||
|
double output[4] = {0, 1, 1, 0};
|
||||||
|
|
||||||
|
int i, j, r;
|
||||||
|
int solved = 0;
|
||||||
|
|
||||||
|
/* An unlucky starting position can strand training (e.g. dead relu
|
||||||
|
* units), so allow a few restarts. */
|
||||||
|
for (r = 0; r < 10 && !solved; ++r) {
|
||||||
|
genann *ann = genann_init(2, 1, 4, 1);
|
||||||
|
ann->activation_hidden = act;
|
||||||
|
|
||||||
|
for (i = 0; i < 2000; ++i) {
|
||||||
|
for (j = 0; j < 4; ++j) {
|
||||||
|
genann_train(ann, input[j], output + j, .5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
solved = 1;
|
||||||
|
for (j = 0; j < 4; ++j) {
|
||||||
|
if ((*genann_run(ann, input[j]) > .5) != (output[j] > .5)) solved = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
genann_free(ann);
|
||||||
|
}
|
||||||
|
|
||||||
|
lok(solved);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void train_xor_tanh() {
|
||||||
|
train_xor_act(genann_act_tanh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void train_xor_relu() {
|
||||||
|
train_xor_act(genann_act_relu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gradient_act(genann_actfun hidden, genann_actfun output) {
|
||||||
|
double input[2] = {.3, -.2};
|
||||||
|
double target[1] = {.7};
|
||||||
|
const double eps = 1e-6;
|
||||||
|
const double rate = .1;
|
||||||
|
double checked = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
genann *ann = genann_init(2, 1, 3, 1);
|
||||||
|
ann->activation_hidden = hidden;
|
||||||
|
ann->activation_output = output;
|
||||||
|
|
||||||
|
/* Fixed, varied weights keep this test deterministic. */
|
||||||
|
for (i = 0; i < ann->total_weights; ++i) {
|
||||||
|
ann->weight[i] = sin(i * 1.7) * .5;
|
||||||
|
}
|
||||||
|
|
||||||
|
genann *trained = genann_copy(ann);
|
||||||
|
genann_train(trained, input, target, rate);
|
||||||
|
|
||||||
|
/* Each weight update must match the central-difference gradient of
|
||||||
|
* the squared error E = (target - out)^2 / 2. */
|
||||||
|
for (i = 0; i < ann->total_weights; ++i) {
|
||||||
|
const double save = ann->weight[i];
|
||||||
|
double o, e1, e2, numeric;
|
||||||
|
|
||||||
|
ann->weight[i] = save + eps;
|
||||||
|
o = *genann_run(ann, input);
|
||||||
|
e1 = .5 * (target[0] - o) * (target[0] - o);
|
||||||
|
|
||||||
|
ann->weight[i] = save - eps;
|
||||||
|
o = *genann_run(ann, input);
|
||||||
|
e2 = .5 * (target[0] - o) * (target[0] - o);
|
||||||
|
|
||||||
|
ann->weight[i] = save;
|
||||||
|
numeric = (e1 - e2) / (2 * eps);
|
||||||
|
checked += fabs(numeric);
|
||||||
|
|
||||||
|
lok(fabs((trained->weight[i] - save) - (-rate * numeric)) < 1e-7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Guard against passing trivially with an all-zero gradient. */
|
||||||
|
lok(checked > .001);
|
||||||
|
|
||||||
|
genann_free(ann);
|
||||||
|
genann_free(trained);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gradient_tanh() {
|
||||||
|
gradient_act(genann_act_tanh, genann_act_tanh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gradient_relu() {
|
||||||
|
gradient_act(genann_act_relu, genann_act_sigmoid);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void persist() {
|
void persist() {
|
||||||
genann *first = genann_init(1000, 5, 50, 10);
|
genann *first = genann_init(1000, 5, 50, 10);
|
||||||
|
|
||||||
@@ -266,6 +368,12 @@ int main(int argc, char *argv[])
|
|||||||
lrun("train and", train_and);
|
lrun("train and", train_and);
|
||||||
lrun("train or", train_or);
|
lrun("train or", train_or);
|
||||||
lrun("train xor", train_xor);
|
lrun("train xor", train_xor);
|
||||||
|
#ifndef genann_act
|
||||||
|
lrun("train tanh", train_xor_tanh);
|
||||||
|
lrun("train relu", train_xor_relu);
|
||||||
|
lrun("gradient tanh", gradient_tanh);
|
||||||
|
lrun("gradient relu", gradient_relu);
|
||||||
|
#endif
|
||||||
lrun("persist", persist);
|
lrun("persist", persist);
|
||||||
lrun("copy", copy);
|
lrun("copy", copy);
|
||||||
lrun("sigmoid", sigmoid);
|
lrun("sigmoid", sigmoid);
|
||||||
|
|||||||
Reference in New Issue
Block a user