jacobian

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

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 }