Advertisement
Guest User

Untitled

a guest
Dec 31st, 2017
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.25 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <math.h>
  3. #include <stdint.h>
  4. #include <vector>
  5.  
  6.  
  7. struct Network {
  8.     #ifdef TINYNN_USE_DOUBLE
  9.     typedef double tinynnf;
  10.     #else
  11.     typedef float tinynnf;
  12.     #endif
  13.     const tinynnf limit = 3;
  14.     struct Layer {
  15.         std::vector<tinynnf> biases;
  16.         std::vector<tinynnf> outputs;
  17.         std::vector<tinynnf> errors;
  18.         Layer(const uint64_t & n) {
  19.             biases.resize(n);
  20.             outputs.resize(n);
  21.             errors.resize(n);
  22.         }
  23.     };
  24.     std::vector<Layer> layers;
  25.     std::vector<std::vector<tinynnf>> connections;
  26.     Network(const std::vector<uint64_t> & spec) {
  27.         for(const uint64_t & size : spec)
  28.             layers.push_back(Layer(size));
  29.         for(size_t i = 0; i+1 < layers.size(); i++)
  30.             connections.push_back(std::vector<tinynnf>(layers[i].outputs.size() * layers[i+1].outputs.size()));
  31.         for(auto & c : connections)
  32.             for(auto & w : c)
  33.                 w = ((tinynnf)rand())/RAND_MAX-0.5; // -0.5 ~ +0.5
  34.         for(auto & l : layers)
  35.             for(auto & b : l.biases)
  36.                 b = ((tinynnf)rand())/RAND_MAX-0.5;
  37.     }
  38.     void pair_forwards(const std::vector<tinynnf> & connectors, const Layer & left, Layer & right, bool is_last) {
  39.         for(size_t r = 0; r < right.outputs.size(); r++) {
  40.             right.outputs[r] = right.biases[r];
  41.             for(size_t l = 0; l < left.outputs.size(); l++)
  42.                 right.outputs[r] += left.outputs[l] * connectors[r*left.outputs.size() + l];
  43.             if(!is_last)
  44.                 right.outputs[r] = tanh(right.outputs[r]);
  45.         }
  46.     }
  47.     std::vector<tinynnf> forwards(std::vector<tinynnf> inputs) {
  48.         layers[0].outputs = inputs;
  49.         for(size_t i = 0; i+1 < layers.size(); i++)
  50.             pair_forwards(connections[i], layers[i], layers[i+1], i+2 == layers.size());
  51.         return layers[layers.size()-1].outputs;
  52.     }
  53.     void train(std::vector<tinynnf> output_errors, tinynnf rate) {
  54.         if(layers.size() == 0 or output_errors.size() != layers[layers.size()-1].errors.size()) return; // invalid network or output_errors
  55.         layers[layers.size()-1].errors = output_errors;
  56.         for(size_t i = layers.size()-1; i > 0; i--) {
  57.             auto & right = layers[i];
  58.             auto & left = layers[i-1];
  59.             auto & connectors = connections[i-1];
  60.             for(size_t l = 0; l < left.outputs.size(); l++) { // loop over left nodes to modify each one's error
  61.                 left.errors[l] = 0;
  62.                 for(size_t r = 0; r < right.outputs.size(); r++)
  63.                     left.errors[l] += right.errors[r] * connectors[r*left.outputs.size() + l];
  64.                 left.errors[l] *= 1.0f - left.outputs[l]*left.outputs[l];
  65.                 for(size_t r = 0; r < right.outputs.size(); r++) { // modify the connections to the left-side node based on the errors of the right-side nodes
  66.                     connectors[r*left.outputs.size() + l] -= left.outputs[l] * right.errors[r] * rate;
  67.                     if(limit != 0 && i+1 < layers.size())
  68.                     {
  69.                         if(connectors[r*left.outputs.size() + l] > limit) // in a saner language: replace with max(min(...)...) or clamp(...). count all four lines as one line.
  70.                             connectors[r*left.outputs.size() + l] = limit;
  71.                         if(connectors[r*left.outputs.size() + l] < -limit)
  72.                             connectors[r*left.outputs.size() + l] = -limit;
  73.                     }
  74.                 }
  75.             }
  76.             for(size_t r = 0; r < right.outputs.size(); r++) { // adjust each right node's bias input -- note i have no idea if this section is correct lmao
  77.                 tinynnf error = right.errors[r];
  78.                 error *= 1.0f - right.biases[r];
  79.                 right.biases[r] -= error * rate;
  80.                 if(limit != 0 && i+1 < layers.size())
  81.                 {
  82.                     if(right.biases[r] > limit) // in a saner language: replace with max(min(...)...) or clamp(...). count all four lines as one line.
  83.                         right.biases[r] = limit;
  84.                     if(right.biases[r] < -limit)
  85.                         right.biases[r] = -limit;
  86.                 }
  87.             }
  88.         }
  89.     }
  90. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement