| 3544 | // ---------------------------------------------------------------------------------------- |
| 3545 | |
| 3546 | void test_simple_autoencoder() |
| 3547 | { |
| 3548 | print_spinner(); |
| 3549 | |
| 3550 | srand(1234); |
| 3551 | |
| 3552 | const int output_width = 7; |
| 3553 | const int output_height = 7; |
| 3554 | const int num_samples = 100; |
| 3555 | ::std::vector<matrix<float>> x(num_samples); |
| 3556 | |
| 3557 | matrix<float> tmp(output_width, output_height); |
| 3558 | for (int i = 0; i < num_samples; ++i) |
| 3559 | { |
| 3560 | const int model = i % 4; |
| 3561 | |
| 3562 | for (int r = 0; r < output_height; ++r) |
| 3563 | for (int c = 0; c < output_width; ++c) |
| 3564 | switch (model) { |
| 3565 | case 0: tmp(r, c) = r / output_height; break; |
| 3566 | case 1: tmp(r, c) = c / output_width; break; |
| 3567 | case 2: tmp(r, c) = 1.0 - r / output_height; break; |
| 3568 | case 3: tmp(r, c) = 1.0 - c / output_width; break; |
| 3569 | default: DLIB_TEST_MSG(false, "Invalid model: " << model << " (should be between 0 and 3)"); |
| 3570 | } |
| 3571 | |
| 3572 | x[i] = tmp; |
| 3573 | } |
| 3574 | |
| 3575 | using net_type = loss_mean_squared_per_pixel< |
| 3576 | cont<1,output_height,output_width,2,2, |
| 3577 | relu<con<4,output_height,output_width,2,2, |
| 3578 | input<matrix<float>>>>>>; |
| 3579 | net_type net; |
| 3580 | |
| 3581 | const auto autoencoder_error = [&x, &net, &output_height, &output_width]() |
| 3582 | { |
| 3583 | const auto y = net(x); |
| 3584 | double error = 0.0; |
| 3585 | for (size_t i = 0; i < x.size(); ++i) |
| 3586 | for (int r = 0; r < output_height; ++r) |
| 3587 | for (int c = 0; c < output_width; ++c) |
| 3588 | error += fabs(y[i](r, c) - x[i](r, c)); |
| 3589 | |
| 3590 | return error / (x.size() * output_height * output_width); |
| 3591 | }; |
| 3592 | |
| 3593 | // The autoencoder can't be very good before it's been trained |
| 3594 | // (or at least the probability of the reconstruction error |
| 3595 | // being small should be super low; in fact, the error ought to |
| 3596 | // be much higher than 0.01, however since the initialization |
| 3597 | // is random, putting the limit below too high could make the |
| 3598 | // tests fail when other, unrelated tests are added into the |
| 3599 | // sequence) |
| 3600 | const double error_before = autoencoder_error(); |
| 3601 | DLIB_TEST_MSG(error_before > 0.01, "Autoencoder error before training = " << error_before); |
| 3602 | |
| 3603 | // Make sure there's an information bottleneck, as intended |
no test coverage detected