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 // }