utils.cpp (4778B)
1 #include <iostream> 2 #include <fstream> 3 #include <algorithm> 4 #include <cstdlib> 5 #include <ctime> 6 #include <cmath> 7 #include <cstdio> 8 #include <fcntl.h> 9 #include <unistd.h> 10 #include <sys/stat.h> 11 #include <Eigen/Dense> 12 13 #include "utils.hpp" 14 15 namespace Jacobian { 16 namespace activations { 17 18 inline float sgn(float val) {return (0.0f < val) - (val < 0.0f);} 19 20 double fexp(double val) 21 { 22 long tmp = static_cast<long>(1512775 * val + 1072632447) << 32; 23 return *reinterpret_cast<double*>(&tmp); 24 } 25 26 float ftanh(float x) 27 { 28 return (x*(10+pow(x,2))*(60+pow(x,2)))/ 29 (600+(270*pow(x,2))+(11*pow(x,4))+(pow(x,6)/24)); 30 } 31 32 //float ftanh(float val) {return sgn(val) * (1 - 2/(fexp(2*abs(val))+1));} 33 float fcosh(float val) {return (fexp(val) + fexp(-val)) * 0.5;} 34 35 // A bunch of hardcoded activation functions. Avoids much of the slowness of custom functions. 36 // Although the std::function makes it not the fastest way, the functionality is worth it. 37 // Yes, these functions may be a frustrating to read but they're just equations and I want to conserve space. 38 39 float sigmoid(float x) {return 1.0/(1+fexp(-x));} 40 float sigmoid_deriv(float x) {return 1.0/(1+fexp(-x)) * (1 - 1.0/(1+fexp(-x)));} 41 42 float linear(float x) {return x;} 43 float linear_deriv(float x) {return 1;} 44 45 float lecun_tanh(float x) { 46 //std::cout << ftanh(x) << " vs " << tanh(x) << "\n"; 47 return 1.7159 * ftanh(0.66f * x);} 48 float lecun_tanh_deriv(float x) {return 1.14393 * pow(1.0/fcosh(0.66f * x), 2);} 49 50 float inverse_logit(float x) {return (fexp(x)/(fexp(x)+1));} 51 float inverse_logit_deriv(float x) {return (fexp(x)/pow(fexp(x)+1, 2));} 52 53 float softplus(float x) {return log(1+fexp(x));} 54 float softplus_deriv(float x) {return fexp(x)/(fexp(x)+1);} 55 56 float cloglog(float x) {return 1-fexp(-fexp(x));} 57 float cloglog_deriv(float x) {return fexp(x-fexp(x));} 58 59 float step(float x) 60 { 61 if (x > 0) return 1; 62 else return 0; 63 } 64 float step_deriv(float x) {return 0;} 65 66 float bipolar(float x) 67 { 68 if (x > 0) return 1; 69 else if (x == 0) return 0; 70 else return -1; 71 } 72 float bipolar_deriv(float x) {return 0;} 73 74 float bipolar_sigmoid(float x) {return (1-fexp(-x))/(1+fexp(-x));} 75 float bipolar_sigmoid_deriv(float x) {return (2*fexp(x))/(pow(fexp(x)+1,2));} 76 77 float hard_tanh(float x) {return fmax(-1, fmin(1,x));} 78 float hard_tanh_deriv(float x) 79 { 80 if (-1 < x && x < 1) return 1; 81 else return 0; 82 } 83 84 float leaky_relu(float x) 85 { 86 if (x > 0) return x; 87 else return 0.01 * x; 88 } 89 90 float leaky_relu_deriv(float x) 91 { 92 if (x > 0) return 1; 93 else return 0.01; 94 } 95 96 std::function<float(float)> rectifier(float (*activation)(float)) 97 { 98 auto rectified = [activation](float x) -> float { 99 if (x > 0) 100 return (*activation)(x); 101 else 102 return 0; 103 }; 104 return rectified; 105 } 106 } // namespace activations 107 108 namespace optimizers { 109 std::function<void(Layer&, Eigen::MatrixXf, float)> momentum(float beta) { 110 return [beta](Layer& layer, const Eigen::MatrixXf delta, const float learning_rate) { 111 layer.weights -= (beta * layer.m) + (learning_rate * delta); 112 layer.m = (learning_rate * delta); 113 }; 114 } 115 116 std::function<void(Layer&, Eigen::MatrixXf, float)> demon(float beta, int max_ep) { 117 float beta_init = beta; 118 float prev_epoch = -1; 119 float epochs = 0; 120 return [max_ep, epochs, beta_init, beta](Layer& layer, const Eigen::MatrixXf delta, const float learning_rate) mutable { 121 beta = beta_init * (1-(epochs/max_ep)) / ((beta_init * (1-(epochs/max_ep))) + (1-beta_init)); 122 layer.weights -= (beta * layer.m) + (learning_rate * delta); 123 layer.m = (learning_rate * delta); 124 epochs++; 125 }; 126 } 127 128 std::function<void(Layer&, Eigen::MatrixXf, float)> adam(float beta1, float beta2, float epsilon) { 129 return [beta1, beta2, epsilon](Layer& layer, const Eigen::MatrixXf delta, const float learning_rate) { 130 layer.m = (beta1 * layer.m) + ((1-beta1)*delta); 131 layer.v = (beta2 * layer.v) + (1-beta2)*(delta.cwiseProduct(delta)); 132 layer.weights -= learning_rate * 133 ((layer.v.cwiseSqrt()).array()+epsilon).pow(-1).cwiseProduct(layer.m.array()).matrix(); 134 }; 135 } 136 137 std::function<void(Layer&, Eigen::MatrixXf, float)> adamax(float beta1, float beta2, float epsilon) { 138 return [beta1, beta2, epsilon](Layer &layer, 139 const Eigen::MatrixXf delta, 140 const float learning_rate) { 141 layer.m = (beta1 * layer.m) + ((1 - beta1) * delta); 142 if ((beta2 * layer.v).sum() > delta.array().abs().sum()) 143 layer.v = (beta2 * layer.v); 144 else 145 layer.v = delta.array().abs().matrix(); 146 layer.weights -= 147 learning_rate * 148 (layer.v.array().pow(-1).cwiseProduct(layer.m.array())) 149 .matrix(); 150 }; 151 } 152 } 153 }