Source browser
examples/neural_checks.hpp
Read the complete file below or download its original bytes. Line numbers provide stable links to a declaration or processing step.
File fingerprint
1/** @file neural_checks.hpp
2 * @brief Training, inference and numerical validation shared by the ANN/CNN applications.
3 */
4#ifndef SHDR_EXAMPLES_NEURAL_CHECKS_HPP // Open this include guard or optional feature branch.
5#define SHDR_EXAMPLES_NEURAL_CHECKS_HPP // Define SHDR_EXAMPLES_NEURAL_CHECKS_HPP for the declarations that follow.
6#include "runner.hpp" // Include runner.hpp declarations.
7#include "neural_support.hpp" // Include neural_support.hpp declarations.
8
9namespace shdr_examples { // Group these helpers within their namespace.
10
11/** @brief Run complete model checks on the selected backend, including every parameter. */
12inline int binary_example_main(int argc, char** argv, bool cnn) { // Implement binary example main for the operations below.
13 try { // Run the operation while retaining the error handling below.
14 runner run(argc, argv); // Construct run with these initial values.
15 binary_network model(cnn); // Construct model with these initial values.
16 check_binary_gradients(model); // Apply check binary gradients to these arguments.
17 const float* cpu_gradients = // Set cpu gradients from this expression.
18 static_cast<const shdr::buffer<float>&>(model.gradients).data(); // Apply data to these arguments.
19 const std::vector<float> expected_gradient(cpu_gradients, // Declare expected gradient with the parameters continued below.
20 cpu_gradients + model.gradients.size()); // Apply size to these arguments.
21 if (run.gpu()) { // Check this condition before entering the following branch.
22 run.run(model.gradient_pipeline()); // Execute the configured pipeline on the requested backend.
23 const float* gpu_gradients = // Set gpu gradients from this expression.
24 static_cast<const shdr::buffer<float>&>(model.gradients).data(); // Apply data to these arguments.
25 for (std::size_t i = 0; i < expected_gradient.size(); ++i) // Iterate over i for this calculation.
26 require_close( // Check the computed value against the independent reference.
27 gpu_gradients[i], expected_gradient[i], "neural CPU/GPU gradient", 0.0002f); // Continue the expression using gpu gradients, i, expected gradient.
28 } // End this block.
29 run.run(model.evaluation_pipeline()); // Execute the configured pipeline on the requested backend.
30 const float initial_loss = static_cast<const shdr::buffer<float>&>(model.loss).data()[0]; // Use a constant buffer view so GPU writes synchronize before host reads.
31 const unsigned steps = cnn ? 180u : 160u; // Set steps from this expression.
32 for (unsigned step = 0; step < steps; ++step) // Iterate over step for this calculation.
33 run.run(model.training_pipeline()); // Execute the configured pipeline on the requested backend.
34 run.run(model.evaluation_pipeline()); // Execute the configured pipeline on the requested backend.
35 const float final_loss = static_cast<const shdr::buffer<float>&>(model.loss).data()[0]; // Use a constant buffer view so GPU writes synchronize before host reads.
36 const shdr::buffer<float>& parameter_buffer = model.parameters; // Use a constant buffer view so GPU writes synchronize before host reads.
37 const std::vector<double> weights(parameter_buffer.data(), // Declare weights with the parameters continued below.
38 parameter_buffer.data() + parameter_buffer.size()); // Apply data to these arguments.
39 const float* probabilities = // Set probabilities from this expression.
40 static_cast<const shdr::buffer<float>&>(model.predictions).data(); // Apply data to these arguments.
41 const float* labels = static_cast<const shdr::buffer<float>&>(model.targets).data(); // Use a constant buffer view so GPU writes synchronize before host reads.
42 unsigned correct = 0; // Set correct from this expression.
43 for (unsigned sample = 0; sample < model.batch_count(); ++sample) { // Iterate over sample for this calculation.
44 require_close(probabilities[sample], // Check the computed value against the independent reference.
45 float(binary_reference_probability(model, weights, sample)), // Apply float to these arguments.
46 "neural inference oracle", // Provide this text argument for the operation above.
47 0.0002f); // Complete this expression or declaration.
48 if ((probabilities[sample] >= 0.5f) == (labels[sample] >= 0.5f)) // Check this condition before entering the following branch.
49 ++correct; // Continue the expression using correct.
50 } // End this block.
51 if (!(final_loss < initial_loss * 0.8f) || correct < model.batch_count() * 9u / 10u) // Check this condition before entering the following branch.
52 throw shdr::error( // Report this failed operation.
53 "neural training did not reduce loss and learn the seeded classification task"); // Provide this text argument for the operation above.
54 if (run.gpu()) { // Check this condition before entering the following branch.
55 binary_network cpu(cnn); // Construct cpu with these initial values.
56 for (unsigned step = 0; step < steps; ++step) // Iterate over step for this calculation.
57 cpu.training_pipeline().run(); // Execute the configured pipeline on the requested backend.
58 cpu.prediction_pipeline().run(); // Execute the configured pipeline on the requested backend.
59 const float* cpu_weights = // Set cpu weights from this expression.
60 static_cast<const shdr::buffer<float>&>(cpu.parameters).data(); // Apply data to these arguments.
61 const float* cpu_probabilities = // Set cpu probabilities from this expression.
62 static_cast<const shdr::buffer<float>&>(cpu.predictions).data(); // Apply data to these arguments.
63 for (unsigned parameter = 0; parameter < model.parameter_count(); ++parameter) // Iterate over parameter for this calculation.
64 require_close(float(weights[parameter]), // Check the computed value against the independent reference.
65 cpu_weights[parameter], // Continue the expression using cpu weights, parameter.
66 "neural trained CPU/GPU weights", // Provide this text argument for the operation above.
67 0.002f); // Complete this expression or declaration.
68 for (unsigned sample = 0; sample < model.batch_count(); ++sample) // Iterate over sample for this calculation.
69 require_close(probabilities[sample], // Check the computed value against the independent reference.
70 cpu_probabilities[sample], // Continue the expression using cpu probabilities, sample.
71 "neural trained CPU/GPU predictions", // Provide this text argument for the operation above.
72 0.002f); // Complete this expression or declaration.
73 } // End this block.
74 std::cout << (cnn ? "CNN" : "ANN") << ": " << model.parameter_count() // Write this part of the example result or diagnostic.
75 << " parameters trained for " << steps << " steps, loss " << initial_loss // Write this part of the example result or diagnostic.
76 << " -> " << final_loss << ", accuracy " << correct << '/' << model.batch_count() // Write this part of the example result or diagnostic.
77 << "; analytic gradients and inference verified\n"; // Write this part of the example result or diagnostic.
78 return 0; // Report successful completion.
79 } // End this block.
80#ifdef SHDR_HAVE_EGL // Enable this branch when its feature macro is defined.
81 catch (const context_unavailable& e) { // Handle the indicated exception from the preceding operation.
82 std::cerr << "SKIP: " << e.what() << '\n'; // Write this part of the example result or diagnostic.
83 return 77; // Report an unavailable optional GPU backend.
84 } // End this block.
85#endif // Finish this conditional compilation branch.
86 catch (const std::exception& e) { // Handle the indicated exception from the preceding operation.
87 std::cerr << e.what() << '\n'; // Write this part of the example result or diagnostic.
88 return 1; // Report a failed check or operation.
89 } // End this block.
90} // End this block.
91} // namespace shdr_examples
92#endif // Finish this conditional compilation branch.