jacobian

a basic keras-like neural network library for c++/python
Log | Files | Refs | README

checks.cpp (9717B)


      1 //
      2 //  checks.cpp
      3 //  Jacobian
      4 //
      5 
      6 #include "./src/utils.hpp"
      7 #include "./src/bpnn.hpp"
      8  
      9 #define ZERO_THRESHOLD 5*pow(10, -5)
     10 
     11 // Simple example network to be used in each check.
     12 Network default_net()
     13 {
     14     Network net ("./data_banknote_authentication.txt", 16, 0.0155, 0.03, L2, 0, 0.9);
     15     net.add_layer(4, "linear", linear, linear_deriv);
     16     net.add_layer(5, "lecun_tanh", lecun_tanh, lecun_tanh_deriv);
     17     net.add_layer(2, "linear", linear, linear_deriv);
     18     net.init_optimizer("momentum", 0);
     19     net.initialize();
     20     net.silenced = true;
     21     return net;
     22 }
     23 
     24 // Proper cloning of networks for providing a reference point.
     25 Network explicit_copy(Network src)
     26 {
     27     Network dst ("./data_banknote_authentication.txt", 16, 0.0155, 0.03, L2, 0, 0.9);
     28     dst = src;
     29     for (int i = 0; i < src.layers.size(); i++) {
     30         dst.layers[i] = src.layers[i];
     31     }
     32     return dst;
     33 }
     34 
     35 // Regularization should increase the cost.
     36 void regularization_check(int& sanity_passed, int& total_checks)
     37 {
     38     Network net = default_net();
     39     std::cout << "\u001b[4m\u001b[1mSANITY CHECKS:\u001b[0m\n";
     40     // Check if regularization strength increases loss (as it should).
     41     std::cout << "Regularization check...";
     42 
     43     net.list_net();
     44     Network copy1 = explicit_copy(net);
     45     Network copy2 = explicit_copy(net);
     46     copy1.next_batch(copy1.data);
     47     copy1.feedforward();
     48   
     49     copy2.next_batch(copy2.data);
     50     copy2.feedforward();
     51     net.list_net();
     52     if (copy1.cost() > copy2.cost()) {
     53         std::cout << " \u001b[32mPassed!\n\u001b[37m";
     54         sanity_passed++;
     55     }
     56     else std::cout << " \u001b[31mFailed.\n\u001b[37m";
     57     total_checks++;
     58 }
     59 
     60 // Given a small batch size and enough time, the network should be able to get its cost very close to zero.
     61 void zero_check(int& sanity_passed, int& total_checks)
     62 {
     63     Network net = default_net();
     64     std::cout << "Zero-cost check...";
     65     net.next_batch(net.data);
     66     float finalcost;
     67     for (int i = 0; i < 10000; i++) {
     68       net.feedforward();
     69       net.backpropagate();
     70       finalcost = net.cost();
     71       if (finalcost <= ZERO_THRESHOLD) {
     72         break;
     73       }
     74     }
     75     if (finalcost <= ZERO_THRESHOLD) {
     76       std::cout << " \u001b[32mPassed!\n\u001b[37m";
     77       sanity_passed++;
     78     }
     79     else std::cout << " \u001b[31mFailed.\n\u001b[37m";
     80     total_checks++;
     81 }
     82 
     83 // There should be no weird floating point numbers in layer updates.
     84 void floating_point_check(int& sanity_passed, int& total_checks)
     85 {
     86     Network net = default_net();
     87     std::cout << "Update floating-point check...";
     88     net.next_batch(net.data);
     89     net.feedforward();
     90     net.backpropagate();
     91     for (int i = 0; i < net.length-1; i++) {
     92         for (int j = 0; j < net.layers[i].m->rows(); j++) {
     93             for (int k = 0; k < net.layers[i].m->cols(); k++) {
     94                 if ((*net.layers[i].m)(j,k) == -0 || (*net.layers[i].m)(j,k) == INFINITY || (*net.layers[i].m)(j,k) == NAN || (*net.layers[i].m)(j,k) == -INFINITY) {
     95                     std::cout << " \u001b[31mFailed.\n\u001b[37m";
     96                     total_checks++;
     97                     return;
     98                 }
     99             }
    100         }
    101     }
    102     std::cout << " \u001b[32mPassed!\n\u001b[37m";
    103     sanity_passed++;
    104     total_checks++;
    105 }
    106 
    107 void update_check(int& sanity_passed, int& total_checks)
    108 {
    109     // std::cout << "Layer updates sanity check...";
    110     // Network copy6 ("./data_banknote_authentication.txt", 16, 0.05, 0.03, L2, 0, 0.9);
    111     // Network copy7 ("./data_banknote_authentication.txt", 16, 0.05, 0.03, L2, 0, 0.9);
    112     // //copy2.list_net();
    113     // //copy1.list_net();
    114     // int passed;
    115     // for (int i = 0; i < copy1.layers.size()-1; i++) {
    116     //   if (*copy1.layers[i].weights == *copy2.layers[i].weights) {
    117     //     //      std::cout << *copy2.layers[i].weights <<"uninitweight\n\n";
    118     //     //      std::cout << *copy1.layers[i].weights << " "<<i<<"weight\n\n";
    119     //     passed = -1;
    120     //   }
    121     // }
    122     // for (int i = 1; i < copy1.layers.size(); i++) {
    123     //   if (*copy1.layers[i].bias == *copy2.layers[i].bias) {
    124     //     //      std::cout << *copy2.layers[i].bias <<"uninitbias\n\n";
    125     //     //  std::cout << *copy1.layers[i].bias <<" " << i << "bias\n\n";
    126     //     passed = -1;
    127     //   }
    128     // }
    129     // if (passed == 1) {
    130     //   std::cout << " \u001b[32mPassed!\n\u001b[37m";
    131     //   sanity_passed++;
    132     // }
    133     // else std::cout << " \u001b[31mFailed.\n\u001b[37m";
    134 }
    135 
    136 void sanity_checks()
    137 {
    138     int sanity_passed = 0;
    139     int total_checks = 0;
    140     zero_check(sanity_passed, total_checks);
    141     floating_point_check(sanity_passed, total_checks);
    142     std::cout << "\u001b[1m\nPassed " << sanity_passed << "/" << total_checks <<" sanity checks.\u001b[0m\n";
    143     if ((float)sanity_passed/total_checks < 0.5) {
    144         std::cout << "Majority of sanity checks failed. Exiting." << "\n";
    145         exit(1);
    146     }
    147 }
    148 
    149 void run_check(int& basic_passed, int& total_checks)
    150 {
    151     std::cout << "Default net check...";
    152     try {
    153         Network net = default_net();
    154         for (int i = 0; i < 50; i++) {
    155             net.train();
    156         }
    157     }
    158     catch (...) {
    159         std::cout << " \u001b[31mFailed.\n\u001b[37m";
    160         total_checks++;
    161         return;
    162     }
    163     std::cout << " \u001b[32mPassed!\n\u001b[37m";
    164     basic_passed++;
    165     total_checks++;
    166 }
    167 
    168 void optimizers_check(int& basic_passed, int& total_checks)
    169 {
    170     std::cout << "Optimizers check...";
    171     try {
    172         std::string optimizers [5] = {"momentum", "demon", "adam", "adamax", "sgd"};
    173         for (std::string optimizer : optimizers) {
    174             Network net ("./data_banknote_authentication.txt", 16, 0.0155, 0.03, L2, 0, 0.9);
    175             net.add_layer(4, "linear", linear, linear_deriv);
    176             net.add_layer(5, "lecun_tanh", lecun_tanh, lecun_tanh_deriv);
    177             net.add_layer(2, "linear", linear, linear_deriv);
    178             if (optimizer == "momentum") net.init_optimizer("momentum", 0.9);
    179             if (optimizer == "demon") net.init_optimizer("demon", 0.9, 50);
    180             if (optimizer == "adam") net.init_optimizer("adam", 0.999, 0.9, pow(10,-6));
    181             if (optimizer == "adamax") net.init_optimizer("adamax", 0.999, 0.9, pow(10,-6));
    182             if (optimizer == "sgd") net.init_optimizer("sgd");
    183             net.initialize();
    184             net.silenced=true;
    185             for (int i = 0; i < 50; i++) {
    186                 net.train();
    187             }
    188         }
    189     }
    190     catch (...) {
    191         std::cout << " \u001b[31mFailed.\n\u001b[37m";
    192         total_checks++;
    193         return;
    194     }
    195     std::cout << " \u001b[32mPassed!\n\u001b[37m";
    196     basic_passed++;
    197     total_checks++;
    198 }
    199 
    200 void prelu_check(int& basic_passed, int& total_checks)
    201 {
    202     std::cout << "PReLU check...";
    203     try {
    204         Network net = default_net();
    205         for (int i = 0; i < 50; i++) {
    206             Network net ("./data_banknote_authentication.txt", 16, 0.0155, 0.03, L2, 0, 0.9);
    207             net.add_layer(4, "linear", linear, linear_deriv);
    208             net.add_prelu_layer(5, 0.01);
    209             net.add_layer(2, "linear", linear, linear_deriv);
    210             net.initialize();
    211             net.silenced=true;
    212         }
    213     }
    214     catch (...) {
    215         std::cout << " \u001b[31mFailed.\n\u001b[37m";
    216         total_checks++;
    217         return;
    218     }
    219     std::cout << " \u001b[32mPassed!\n\u001b[37m";
    220     basic_passed++;
    221     total_checks++;
    222 }
    223 
    224 void basic_checks()
    225 {
    226     int basic_passed = 0;
    227     int total_checks = 0;
    228     run_check(basic_passed, total_checks);
    229     optimizers_check(basic_passed, total_checks);
    230     prelu_check(basic_passed, total_checks);
    231     std::cout << "\u001b[1m\nPassed " << basic_passed << "/" << total_checks <<" basic checks.\u001b[0m\n";
    232     if ((float)basic_passed/total_checks < 0.5) {
    233         std::cout << "Majority of basic checks failed. Exiting." << "\n";
    234         exit(1);
    235     }
    236 }
    237 
    238 void grad_checks() {}
    239 
    240 // Eigen::MatrixXf Network::numerical_grad(int i, float epsilon)
    241 // {
    242 //     Eigen::MatrixXf gradient (layers[i].weights->rows(), layers[i].weights->cols());
    243 //     for (int j = 0; j < layers[i].weights->rows(); j++) {
    244 //         for (int k = 0; k < layers[i].weights->cols(); k++) {
    245 //             float current_cost = cost();
    246 //             std::vector<Layer> backup = layers;
    247 //             (*layers[i].weights)(j,k) += epsilon;
    248 //             feedforward();
    249 //             float end_cost = cost();
    250 //             gradient(j,k) = (end_cost - current_cost)/epsilon;
    251 //             layers = backup;
    252 //             batches = 0;
    253 //         }
    254 //     }
    255 //     return gradient;
    256 // }
    257 
    258 // void Network::grad_check()
    259 // {
    260 //     std::vector<Layer> backup = layers;
    261 //     feedforward();
    262 //     layers = backup;
    263 //     batches = 0;
    264 //     std::vector<Eigen::MatrixXf> gradients;
    265 //     std::vector<Eigen::MatrixXf> deltas;
    266 //     Eigen::MatrixXf error (layers[length-1].contents->rows(), layers[length-1].contents->cols());
    267 //     for (int i = 0; i < error.rows(); i++) {
    268 //         for (int j = 0; j < error.cols(); j++) {
    269 //             float truth;
    270 //             if (j==(*labels)(i,0)) truth = 1;
    271 //             else truth = 0;
    272 //             error(i,j) = (*layers[length-1].contents)(i,j) - truth;
    273 //             checknan(error(i,j), "gradient of final layer");
    274 //         }
    275 //     }
    276 //     int counter = 1;
    277 //     gradients.push_back(error);
    278 //     deltas.push_back((*layers[length-2].contents).transpose() * gradients[0]);
    279 //     for (int i = length-2; i >= 1; i--) {
    280 //         gradients.push_back(cwise_product(gradients[counter-1] * layers[i].weights->transpose(),*layers[i].dZ));
    281 //         std::cout << layers[i-1].contents->transpose() * gradients[counter];
    282 //         deltas.push_back(layers[i-1].contents->transpose() * gradients[counter]);
    283 //         counter++;
    284 //     }
    285 // }