commit 27782f158e1d58d64e02623f3880407ad5f54574
parent 673085cac2b11077699adb8bc35967cb24832817
Author: David Freifeld <freifeld.david@gmail.com>
Date: Tue, 16 Jun 2020 18:43:44 -0700
Restructuring, strange malloc bug
Diffstat:
| M | bpnn.c | | | 143 | ++++--------------------------------------------------------------------------- |
| A | bpnn.cpp | | | 263 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | mr_bpnn_1.cpp | | | 89 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | test.cpp | | | 396 | ------------------------------------------------------------------------------- |
| D | test.hpp | | | 15 | --------------- |
5 files changed, 359 insertions(+), 547 deletions(-)
diff --git a/bpnn.c b/bpnn.c
@@ -1,145 +1,16 @@
-#include <stdio.h>
#include <stdlib.h>
-#include <math.h>
-
-/* #include "../mapreduce/mapreduce.h" */
-/* #include "../mapreduce/server.h" */
-/* #include "../mapreduce/worker.h" */
-
-#define BUFSIZE 2048
-
-struct node;
-
-struct edge {
- struct node * source;
- struct node * target;
- double weight;
-};
-
-struct node {
- struct edge* incoming;
- struct edge* outgoing;
- float activation;
-};
+#include <stdio.h>
-struct layer {
- struct node* nodes;
- int length;
-};
+typedef struct {
+ int** rows;
+}Matrix;
struct network {
- struct layer* layers;
- int length;
-};
-
-double activate (double value) {
- // Sigmoid
- return 1/(1+pow(M_E, -value));
-}
-
-struct network initialize (char* path, int inputs, int neurons, int hidden, int outputs) {
- // Read from CSV
- FILE* fptr = fopen(path, "r");
- double data[inputs];
- fscanf(fptr, "%d,%d,%d,%d,*d", &data[0], &data[1], &data[2], &data[3]);
-
- // Initialize network
- struct network net;
- net.layers = malloc((hidden + 2) * sizeof(struct layer));
- net.length = hidden + 2;
- // Initialize input nodes
- net.layers[0].nodes = malloc(inputs * sizeof(struct node));
- for (int i = 0; i < inputs; i++) {
- net.layers[0].nodes[i].activation = activate(data[i]);
- }
- net.layers[0].length = inputs;
-
- /* // Init hidden layer nodes and output nodes to 0 (will be replaced by feedforward) */
- for (int i = 1; i <= hidden; i++) {
- net.layers[i].nodes = malloc(neurons * sizeof(struct node));
- for (int j = 0; j < neurons; j++) {
- net.layers[i].nodes[j].activation = 0;
- }
- net.layers[i].length = neurons;
- printf("inside %i\n", net.layers[i].length);
- }
- printf("outsidee %i\n", net.layers[0].length);
- net.layers[hidden-1].nodes = malloc(outputs * sizeof(struct node));
- for (int i = 0; i < outputs; i++) {
- net.layers[hidden-1].nodes[i].activation = 0;
- }
- net.layers[hidden+1].length = outputs;
-
- // Init edges between layers with random numbers TODO make a function to initialize edges between two layers for the love of God
- for (int i = 0; i < inputs; i++) {
- net.layers[0].nodes[i].outgoing = malloc(neurons * sizeof(struct edge));
- for (int j = 0; j < neurons; j++) {
- net.layers[1].nodes[j].incoming = malloc(inputs * sizeof(struct edge));
- struct edge connection = {&net.layers[0].nodes[i], &net.layers[1].nodes[j], rand()};
- net.layers[0].nodes[i].outgoing[j] = connection;
- net.layers[1].nodes[j].incoming[i] = connection;
- }
- }
- for (int i = 1; i <= hidden; i++) {
- for (int j = 0; j < neurons; j++) {
- net.layers[i].nodes[j].outgoing = malloc(neurons * sizeof(struct edge));
- for (int k = 0; k < neurons; k++) {
- printf("CHECKCHECKCHECK!?\n");
- net.layers[i+1].nodes[k].outgoing = malloc(neurons * sizeof(struct edge));
- printf("Checkcheck1\n");
- struct edge connection = {&net.layers[i].nodes[j], &net.layers[i+1].nodes[k], rand()};
- printf("Checkcheck2\n");
- net.layers[i].nodes[j].outgoing[k] = connection;
- printf("Checkcheck3\n");
- net.layers[i+1].nodes[k].incoming[j] = connection;
- }
- }
- }
- /* for (int i = 0; i < neurons; i++) { */
- /* net.layers[hidden].nodes[i].outgoing = malloc(outputs * sizeof(struct edge)); */
- /* for (int j = 0; j < outputs; j++) { */
- /* net.layers[hidden+1].nodes[j].incoming = 204892141; //malloc(neurons * sizeof(struct edge)); */
- /* struct edge connection = {&net.layers[0].nodes[0], &net.layers[1].nodes[0], rand()}; */
- /* net.layers[hidden].nodes[i].outgoing[j] = connection; */
- /* net.layers[hidden+1].nodes[j].incoming[i] = connection; */
- /* } */
- /* } */
- /* Epic, everything's initialized TODO add biases! */
- return net;
-}
+};
-void feedforward(struct network net)
+int main()
{
- /* printf("Checkcheck\n"); */
- for (int i = 1; i < net.length; i++) {
- /* printf("%i\n", net.layers[i].length); */
- for (int j = 0; j < net.layers[i].length; j++) {
- double sum = 0;
- for (int k = 0; k < net.layers[i-1].length; k++) {
- sum += net.layers[i].nodes[j].incoming->source->activation * net.layers[i].nodes[j].incoming->weight;
- }
- printf("%f\n", sum);
- net.layers[i].nodes[j].activation = activate(sum);
- printf("Node %i in layer %i has activation %f\n", j, i, net.layers[i].nodes[j].activation);
- }
- }
-}
-
-/* struct int_pair* map (struct str_pair file) */
-/* { */
-/* struct network neuralnet = initialize("./data_banknote_authentication.txt", 4, 5, 2, 2); */
-/* feedforward(neuralnet); */
-/* } */
-/* struct int_pair* reduce (struct int_pair* input) */
-/* { */
-
-/* } */
-
-int main(int argc, char** argv)
-{
- struct network neuralnet = initialize("./data_banknote_authentication.txt", 4, 5, 2, 2);
- feedforward(neuralnet);
- /* mapreduce(argv[3], map, reduce, strtol(argv[2], NULL, 10), 50, strtol(argv[1], NULL, 10), 1); */
+ return 0;
}
diff --git a/bpnn.cpp b/bpnn.cpp
@@ -0,0 +1,263 @@
+#include "bpnn.hpp"
+
+Layer::Layer(float* vals, int batch_sz, int nodes)
+{
+ contents = new Eigen::MatrixXd (batch_sz, nodes);
+ int datalen = batch_sz*nodes;
+ for (int i = 0; i < datalen; i++) {
+ (*contents)((int)i / nodes,i%nodes) = vals[i];
+ }
+ bias = new Eigen::MatrixXd (1, nodes);
+ for (int i = 0; i < nodes; i++) {
+ (*bias)(0,i) = 0.001;
+ }
+}
+
+Layer::Layer(int batch_sz, int nodes)
+{
+ contents = new Eigen::MatrixXd (batch_sz, nodes);
+ int datalen = batch_sz*nodes;
+ for (int i = 0; i < datalen; i++) {
+ (*contents)((int)i / nodes,i%nodes) = 0;
+ }
+ bias = new Eigen::MatrixXd (1, nodes);
+ for (int i = 0; i < nodes; i++) {
+ (*bias)(0,i) = 0.001;
+ }
+ dZ = new Eigen::MatrixXd (batch_sz, nodes);
+}
+
+void Layer::initWeights(Layer next)
+{
+ weights = new Eigen::MatrixXd (contents->cols(), next.contents->cols());
+ int nodes = weights->cols();
+ for (int i = 0; i < (weights->rows()*weights->cols()); i++) {
+ (*weights)((int)i / nodes, i%nodes) = rand() / double(RAND_MAX);
+ }
+}
+
+Network::Network(char* path, int inputs, int hidden, int outputs, int neurons, int batch_sz, float rate)
+{
+ learning_rate = rate;
+ fpath = path;
+ length = hidden + 2;
+ batch_size = batch_sz;
+ FILE* fptr = fopen(path, "r");
+ int datalen = batch_sz*inputs;
+ float batch[datalen];
+ labels = new Eigen::MatrixXd (batch_sz, 1);
+ int label;
+ char line[1024] = {' '};
+ for (int i = 0; i < batch_sz; i++) {
+ fgets(line, 1024, fptr);
+ sscanf(line, "%f,%f,%f,%f,%i", &batch[0+(i*inputs)], &batch[1+(i*inputs)], &batch[2+(i*inputs)], &batch[3+(i*inputs)], &label);
+ (*labels)(i,0) = label;
+ }
+ float* batchptr = batch;
+ layers.emplace_back(batchptr, batch_sz, inputs);
+ for (int i = 0; i < hidden; i++) {
+ layers.emplace_back(batch_sz, neurons);
+ }
+ layers.emplace_back(batch_sz, outputs);
+ for (int i = 0; i < hidden+1; i++) {
+ layers[i].initWeights(layers[i+1]);
+ }
+}
+
+Eigen::MatrixXd Network::activate(Eigen::MatrixXd matrix)
+{
+ int nodes = matrix.cols();
+ for (int i = 0; i < (matrix.rows()*matrix.cols()); i++) {
+ (matrix)((float)i / nodes, i%nodes) = 1.0/(1+exp(-(matrix)((float)i / nodes, i%nodes)));
+ }
+ return matrix;
+}
+
+Eigen::MatrixXd Network::activate_deriv(Eigen::MatrixXd matrix)
+{
+ int nodes = matrix.cols();
+ for (int i = 0; i < (matrix.rows()*matrix.cols()); i++) {
+ (matrix)((float)i / nodes, i%nodes) = 1.0/(1+exp(-(matrix)((float)i / nodes, i%nodes))) * (1 - 1.0/(1+exp(-(matrix)((float)i / nodes, i%nodes))));
+ }
+ return matrix;
+}
+
+void Network::feedforward()
+{
+ for (int i = 0; i < length-1; i++) {
+ *layers[i+1].contents = (*layers[i].contents) * (*layers[i].weights);
+ for (int j = 0; j < layers[i+1].contents->rows(); j++) {
+ // layers[i+1].contents->row(j) += *layers[i+1].bias; TODO ADD ME BACK!
+ }
+ // if (i != length-2) {
+ *layers[i+1].contents = activate(*layers[i+1].contents);
+ *layers[i+1].dZ = activate_deriv(*layers[i+1].contents);
+ // }
+ // else {
+ // *layers[i + 1].dZ = (layers[i + 1].dZ->array() + 1).matrix();
+ // }
+ // list_net();
+ }
+}
+
+void Network::list_net()
+{
+ for (int i = 0; i < length-1; i++) {
+ std::cout << " LAYER " << i << "\n\n" << *layers[i].contents << "\n\n AND BIAS\n" << *layers[i].bias << "\n\n W/ WEIGHTS \n" << *layers[i].weights << "\n\n\n";
+ }
+ std::cout << " LAYER " << length-1 << "\n\n" << *layers[length-1].contents << "\n\n AND BIAS\n" << *layers[length-1].bias << "\n\n\n";
+}
+
+float Network::cost()
+{
+ float sum = 0;
+ for (int i = 0; i < layers[length-1].contents->rows(); i++) {
+ sum += pow((*labels)(i, 0)*100 - (*layers[length-1].contents)(i, 0)*100,2);
+ }
+ return (1.0/batch_size) * sum;
+}
+
+void Network::backpropagate()
+{
+ // std::cout << "\nROUND\n\n\n\n\n\n";
+ std::vector<Eigen::MatrixXd> gradients;
+ std::vector<Eigen::MatrixXd> deltas;
+ gradients.push_back(((*layers[length-1].contents) - (*labels)).cwiseProduct(*layers[length-1].dZ));
+ deltas.push_back((*layers[length-2].contents).transpose() * gradients[0]);
+ int counter = 1;
+ for (int i = length-2; i >= 1; i--) {
+ // std::cout << gradients[counter-1] << "\n\nTHAT WAS GRADIENT\n\n" <<*layers[i].weights << "\n\nTHAT WAS WEIGHTS\n"
+ gradients.push_back((gradients[counter-1] * layers[i].weights->transpose()).cwiseProduct(*layers[i].dZ));
+ deltas.push_back((*layers[i-1].contents).transpose() * gradients[counter]);
+ // std::cout << gradients[counter] << "\n\nand\n\n" << *layers[i-1].weights << "\n\nweights\n\n" << deltas[counter] << "\n\ndelta above\n\n\n\n\n";
+ counter++;
+ }
+ for (int i = 1; i < gradients.size(); i++) {
+ Eigen::MatrixXd gradient = gradients[i];
+ *layers[length-2-i].weights -= learning_rate * (deltas[i]);
+ }
+}
+
+void Network::update_layer(float* vals, int datalen, int index)
+{
+ for (int i = 0; i < datalen; i++) {
+ (*layers[index].contents)((int)i / layers[index].contents->cols(),i%layers[index].contents->cols()) = vals[i];
+ }
+}
+
+int Network::next_batch()
+{
+ FILE* fptr = fopen(fpath, "r");
+ char line[1024] = {' '};
+ int inputs = layers[0].contents->cols();
+ int datalen = batch_size * inputs;
+ float batch[datalen];
+ int label = 100;
+ for (int i = 0; i < batch_size*batches + 1; i++) {
+ if (fgets(line, 1024, fptr)==NULL) {
+ break;
+ }
+ if (i >= batches) {
+ for (int j = 0; j < batch_size; j++) {
+ fgets(line, 1024, fptr);
+ sscanf(line, "%f,%f,%f,%f,%i", &batch[0 + (j * inputs)],
+ &batch[1 + (j * inputs)], &batch[2 + (j * inputs)],
+ &batch[3 + (j * inputs)], &label);
+ (*labels)(j, 0) = label;
+ }
+ }
+ }
+ float* batchptr = batch;
+ update_layer(batchptr, datalen, 0);
+ fclose(fptr);
+ return 0;
+}
+
+int prep_file(char* path)
+{
+ FILE* rptr = fopen(path, "r");
+ char line[1024];
+ std::vector<std::string> lines;
+ int count = 0;
+ while (fgets(line, 1024, rptr) != NULL) {
+ lines.emplace_back(line);
+ count++;
+ }
+ std::random_device rd;
+ std::mt19937 g(rd());
+ std::shuffle(lines.begin(), lines.end(), g);
+ fclose(rptr);
+ std::ofstream out("./shuffled.txt");
+ for (int i = 0; i < lines.size(); i++) {
+ out << lines[i];
+ }
+ return count;
+}
+
+void Network::test(char* path)
+{
+ int rounds = 1;
+ int exit = 0;
+ float totalcost = -1;
+ int linecount = prep_file(path);
+ while (exit == 0) {
+ FILE* fptr = fopen(fpath, "r");
+ char line[1024] = {' '};
+ int inputs = layers[0].contents->cols();
+ int datalen = batch_size * inputs;
+ float batch[datalen];
+ for (int i = 0; i < batch_size*rounds + 1; i++) {
+ if (fgets(line, 1024, fptr)==NULL) {
+ exit = -1;
+ }
+ if (i >= rounds) {
+ for (int j = 0; j < batch_size; j++) {
+ fgets(line, 1024, fptr);
+ sscanf(line, "%f,%f,%f,%f,*i", &batch[0 + (j * inputs)], &batch[1 + (j * inputs)], &batch[2 + (j * inputs)], &batch[3 + (j * inputs)]);
+ }
+ }
+ }
+ float *batchptr = batch;
+ update_layer(batchptr, datalen, 0);
+ fclose(fptr);
+ feedforward();
+ list_net();
+ // std::cout << *layers[length-1].contents << "\n\nvs\n\n" << *labels << "\n\n";
+ totalcost += cost();
+ rounds++;
+ }
+ std::cout << "TEST COST: " << 1.0/((float) linecount) * totalcost << "\n";
+}
+
+void demo()
+{
+ // std::cout << "\n\n\n";
+ int linecount = prep_file("./data_banknote_authentication.txt");
+ Network net ("./shuffled.txt", 4, 2, 1, 5, 10, 1);
+ float epoch_cost = 1000;
+ int epochs = 0;
+ net.batches= 1;
+ // net.feedforward();
+ // net.backpropagate();
+ // std::cout << net.cost() << "\n";
+
+ while (epochs < 500) {
+ int linecount = prep_file("./data_banknote_authentication.txt");
+ float cost_sum = 0;
+ for (int i = 0; i < linecount-net.batch_size; i+=net.batch_size) {
+ net.feedforward();
+ net.backpropagate();
+ cost_sum += net.cost();
+ // std::cout << net.cost() << " as it is " << net.labels[0] << " vs " << *net.layers[net.length-1].contents << "\n";
+ net.batches++;
+ int exit = net.next_batch();
+ if (exit == -1) {
+ break;
+ }
+ }
+ net.batches=1;
+ epoch_cost = 1.0/((float) linecount) * cost_sum;
+ printf("EPOCH %i: Cost is %f for %i instances.\n", epochs, epoch_cost, linecount);
+ epochs++;
+ }
+}
diff --git a/mr_bpnn_1.cpp b/mr_bpnn_1.cpp
@@ -0,0 +1,89 @@
+#include "bpnn.hpp"
+
+struct int_pair* map (struct str_pair input_pair)
+{
+ int_pair* output_pairs = new int_pair[1024];
+ int linecount = prep_file("./data_banknote_authentication.txt");
+ Network net ("./shuffled.txt", 4, 2, 1, 5, 1, 1);
+ float epoch_cost = 1000;
+ int epochs = 0;
+ net.batches= 1;
+
+ while (epochs < 1) {
+ int linecount = prep_file("./data_banknote_authentication.txt");
+ float cost_sum = 0;
+ for (int i = 0; i < linecount-net.batch_size; i+=net.batch_size) {
+ net.feedforward();
+ net.backpropagate();
+ cost_sum += net.cost();
+ net.batches++;
+ int exit = net.next_batch();
+ if (exit == -1) {
+ break;
+ }
+ }
+ net.batches=1;
+ epoch_cost = 1.0/((float) linecount) * cost_sum;
+ printf("EPOCH %i: Cost is %f for %i instances.\n", epochs, epoch_cost, linecount);
+ epochs++;
+ }
+ int rounds = 1;
+ int exit = 0;
+ float totalcost = -1;
+ while (exit == 0) {
+ FILE* fptr = fopen(input_pair.key, "r");
+ char line[1024] = {' '};
+ int inputs = net.layers[0].contents->cols();
+ int datalen = net.batch_size * inputs;
+ float batch[datalen];
+ for (int i = 0; i < net.batch_size*rounds + 1; i++) {
+ if (fgets(line, 1024, fptr)==NULL) {
+ exit = -1;
+ }
+ if (i >= rounds) {
+ for (int j = 0; j < net.batch_size; j++) {
+ fgets(line, 1024, fptr);
+ sscanf(line, "%f,%f,%f,%f,%lf", &batch[0 + (j * inputs)], &batch[1 + (j * inputs)], &batch[2 + (j * inputs)], &batch[3 + (j * inputs)], &(*net.labels)(j));
+ }
+ }
+ }
+ float *batchptr = batch;
+ net.update_layer(batchptr, datalen, 0);
+ net.feedforward();
+ for (int i = 0; i < net.batch_size; i++) {
+ char key[1024];
+ sprintf(key, "%i", net.batch_size);
+ output_pairs[i].key = key;
+ output_pairs[i].value = net.cost();
+ }
+ totalcost += net.cost();
+ rounds++;
+ }
+ return output_pairs;
+}
+
+int_pair* reduce (int_pair* input_pairs)
+{
+ int_pair* output_pairs = new int_pair[2];
+ int keysum = 0;
+ int valsum = 0;
+ for (int i = 0; input_pairs[i].key != NULL; i++) {
+ printf("CHECKPOINT\n");
+ printf("%s\n", input_pairs[i].key);
+ keysum += strtol(input_pairs[i].key, NULL, 10);
+ valsum += input_pairs[i].value;
+ }
+ char key[1024];
+ std::cout << keysum << " and " << valsum << " are SUMS\n";
+ sprintf(key, "%d", keysum);
+ output_pairs[0].key = key;
+ output_pairs[0].value = valsum;
+ output_pairs[1].key = (char*) '\0';
+ output_pairs[1].value = -1;
+ return output_pairs;
+}
+
+int main(int argc, char** argv)
+{
+ begin(argv[2], map, reduce, strtol(argv[1], NULL, 10), 1, argv[3]);
+}
diff --git a/test.cpp b/test.cpp
@@ -1,396 +0,0 @@
-// extern "C" void C_library_function(int x, int y);
-#include "test.hpp"
-
-extern "C" {
- #include "../mapreduce/mapreduce.h"
-}
-
-class Layer {
-public:
- Eigen::MatrixXd* contents;
- Eigen::MatrixXd* weights;
- Eigen::MatrixXd* bias;
- Eigen::MatrixXd* dZ;
-
- Layer(float* vals, int rows, int columns);
- Layer(int rows, int columns);
- void initWeights(Layer next);
-};
-
-Layer::Layer(float* vals, int batch_sz, int nodes)
-{
- contents = new Eigen::MatrixXd (batch_sz, nodes);
- int datalen = batch_sz*nodes;
- for (int i = 0; i < datalen; i++) {
- (*contents)((int)i / nodes,i%nodes) = vals[i];
- }
- bias = new Eigen::MatrixXd (1, nodes);
- for (int i = 0; i < nodes; i++) {
- (*bias)(0,i) = 0.001;
- }
-}
-
-Layer::Layer(int batch_sz, int nodes)
-{
- contents = new Eigen::MatrixXd (batch_sz, nodes);
- int datalen = batch_sz*nodes;
- for (int i = 0; i < datalen; i++) {
- (*contents)((int)i / nodes,i%nodes) = 0;
- }
- bias = new Eigen::MatrixXd (1, nodes);
- for (int i = 0; i < nodes; i++) {
- (*bias)(0,i) = 0.001;
- }
- dZ = new Eigen::MatrixXd (batch_sz, nodes);
-}
-
-void Layer::initWeights(Layer next)
-{
- weights = new Eigen::MatrixXd (contents->cols(), next.contents->cols());
- int nodes = weights->cols();
- for (int i = 0; i < (weights->rows()*weights->cols()); i++) {
- (*weights)((int)i / nodes, i%nodes) = rand() / double(RAND_MAX);
- }
-}
-
-class Network {
-public:
- char* fpath;
-
- std::vector<Layer> layers;
- int length;
-
- float learning_rate;
- int batch_size;
- int batches;
- Eigen::MatrixXd* labels;
-
- Network(char* path, int inputs, int hidden, int outputs, int neurons, int batch_sz, float rate);
- void update_layer(float* vals, int datalen, int index);
-
- Eigen::MatrixXd activate(Eigen::MatrixXd matrix);
- Eigen::MatrixXd activate_deriv(Eigen::MatrixXd matrix);
- void feedforward();
- void list_net();
-
- float cost();
- float gradient(int mode, int layer, int node);
- void backpropagate();
- int next_batch();
- void test(char* path);
-};
-
-Network::Network(char* path, int inputs, int hidden, int outputs, int neurons, int batch_sz, float rate)
-{
- learning_rate = rate;
- fpath = path;
- length = hidden + 2;
- batch_size = batch_sz;
- FILE* fptr = fopen(path, "r");
- int datalen = batch_sz*inputs;
- float batch[datalen];
- labels = new Eigen::MatrixXd (batch_sz, 1);
- int label;
- char line[1024] = {' '};
- for (int i = 0; i < batch_sz; i++) {
- fgets(line, 1024, fptr);
- sscanf(line, "%f,%f,%f,%f,%i", &batch[0+(i*inputs)], &batch[1+(i*inputs)], &batch[2+(i*inputs)], &batch[3+(i*inputs)], &label);
- (*labels)(i,0) = label;
- }
- float* batchptr = batch;
- layers.emplace_back(batchptr, batch_sz, inputs);
- for (int i = 0; i < hidden; i++) {
- layers.emplace_back(batch_sz, neurons);
- }
- layers.emplace_back(batch_sz, outputs);
- for (int i = 0; i < hidden+1; i++) {
- layers[i].initWeights(layers[i+1]);
- }
-}
-
-Eigen::MatrixXd Network::activate(Eigen::MatrixXd matrix)
-{
- int nodes = matrix.cols();
- for (int i = 0; i < (matrix.rows()*matrix.cols()); i++) {
- (matrix)((float)i / nodes, i%nodes) = 1.0/(1+exp(-(matrix)((float)i / nodes, i%nodes)));
- }
- return matrix;
-}
-
-Eigen::MatrixXd Network::activate_deriv(Eigen::MatrixXd matrix)
-{
- int nodes = matrix.cols();
- for (int i = 0; i < (matrix.rows()*matrix.cols()); i++) {
- (matrix)((float)i / nodes, i%nodes) = 1.0/(1+exp(-(matrix)((float)i / nodes, i%nodes))) * (1 - 1.0/(1+exp(-(matrix)((float)i / nodes, i%nodes))));
- }
- return matrix;
-}
-
-void Network::feedforward()
-{
- for (int i = 0; i < length-1; i++) {
- *layers[i+1].contents = (*layers[i].contents) * (*layers[i].weights);
- for (int j = 0; j < layers[i+1].contents->rows(); j++) {
- // layers[i+1].contents->row(j) += *layers[i+1].bias; TODO ADD ME BACK!
- }
- // if (i != length-2) {
- *layers[i+1].contents = activate(*layers[i+1].contents);
- *layers[i+1].dZ = activate_deriv(*layers[i+1].contents);
- // }
- // else {
- // *layers[i + 1].dZ = (layers[i + 1].dZ->array() + 1).matrix();
- // }
- // list_net();
- }
-}
-
-void Network::list_net()
-{
- for (int i = 0; i < length-1; i++) {
- std::cout << " LAYER " << i << "\n\n" << *layers[i].contents << "\n\n AND BIAS\n" << *layers[i].bias << "\n\n W/ WEIGHTS \n" << *layers[i].weights << "\n\n\n";
- }
- std::cout << " LAYER " << length-1 << "\n\n" << *layers[length-1].contents << "\n\n AND BIAS\n" << *layers[length-1].bias << "\n\n\n";
-}
-
-float Network::cost()
-{
- float sum = 0;
- for (int i = 0; i < layers[length-1].contents->rows(); i++) {
- sum += pow((*labels)(i, 0)*100 - (*layers[length-1].contents)(i, 0)*100,2);
- }
- return (1.0/batch_size) * sum;
-}
-
-void Network::backpropagate()
-{
- // std::cout << "\nROUND\n\n\n\n\n\n";
- std::vector<Eigen::MatrixXd> gradients;
- std::vector<Eigen::MatrixXd> deltas;
- gradients.push_back(((*layers[length-1].contents) - (*labels)).cwiseProduct(*layers[length-1].dZ));
- deltas.push_back((*layers[length-2].contents).transpose() * gradients[0]);
- int counter = 1;
- for (int i = length-2; i >= 1; i--) {
- // std::cout << gradients[counter-1] << "\n\nTHAT WAS GRADIENT\n\n" <<*layers[i].weights << "\n\nTHAT WAS WEIGHTS\n"
- gradients.push_back((gradients[counter-1] * layers[i].weights->transpose()).cwiseProduct(*layers[i].dZ));
- deltas.push_back((*layers[i-1].contents).transpose() * gradients[counter]);
- // std::cout << gradients[counter] << "\n\nand\n\n" << *layers[i-1].weights << "\n\nweights\n\n" << deltas[counter] << "\n\ndelta above\n\n\n\n\n";
- counter++;
- }
- for (int i = 1; i < gradients.size(); i++) {
- Eigen::MatrixXd gradient = gradients[i];
- *layers[length-2-i].weights -= learning_rate * (deltas[i]);
- }
-}
-
-void Network::update_layer(float* vals, int datalen, int index)
-{
- for (int i = 0; i < datalen; i++) {
- (*layers[index].contents)((int)i / layers[index].contents->cols(),i%layers[index].contents->cols()) = vals[i];
- }
-}
-
-int Network::next_batch()
-{
- FILE* fptr = fopen(fpath, "r");
- char line[1024] = {' '};
- int inputs = layers[0].contents->cols();
- int datalen = batch_size * inputs;
- float batch[datalen];
- int label = 100;
- for (int i = 0; i < batch_size*batches + 1; i++) {
- if (fgets(line, 1024, fptr)==NULL) {
- break;
- }
- if (i >= batches) {
- for (int j = 0; j < batch_size; j++) {
- fgets(line, 1024, fptr);
- sscanf(line, "%f,%f,%f,%f,%i", &batch[0 + (j * inputs)],
- &batch[1 + (j * inputs)], &batch[2 + (j * inputs)],
- &batch[3 + (j * inputs)], &label);
- (*labels)(j, 0) = label;
- }
- }
- }
- float* batchptr = batch;
- update_layer(batchptr, datalen, 0);
- fclose(fptr);
- return 0;
-}
-
-int prep_file(char* path)
-{
- FILE* rptr = fopen(path, "r");
- char line[1024];
- std::vector<std::string> lines;
- int count = 0;
- while (fgets(line, 1024, rptr) != NULL) {
- lines.emplace_back(line);
- count++;
- }
- std::random_device rd;
- std::mt19937 g(rd());
- std::shuffle(lines.begin(), lines.end(), g);
- fclose(rptr);
- std::ofstream out("./shuffled.txt");
- for (int i = 0; i < lines.size(); i++) {
- out << lines[i];
- }
- return count;
-}
-
-void Network::test(char* path)
-{
- int rounds = 1;
- int exit = 0;
- float totalcost = -1;
- int linecount = prep_file(path);
- while (exit == 0) {
- FILE* fptr = fopen(fpath, "r");
- char line[1024] = {' '};
- int inputs = layers[0].contents->cols();
- int datalen = batch_size * inputs;
- float batch[datalen];
- for (int i = 0; i < batch_size*rounds + 1; i++) {
- if (fgets(line, 1024, fptr)==NULL) {
- exit = -1;
- }
- if (i >= rounds) {
- for (int j = 0; j < batch_size; j++) {
- fgets(line, 1024, fptr);
- sscanf(line, "%f,%f,%f,%f,*i", &batch[0 + (j * inputs)], &batch[1 + (j * inputs)], &batch[2 + (j * inputs)], &batch[3 + (j * inputs)]);
- }
- }
- }
- float *batchptr = batch;
- update_layer(batchptr, datalen, 0);
- fclose(fptr);
- feedforward();
- list_net();
- // std::cout << *layers[length-1].contents << "\n\nvs\n\n" << *labels << "\n\n";
- totalcost += cost();
- rounds++;
- }
- std::cout << "TEST COST: " << 1.0/((float) linecount) * totalcost << "\n";
-}
-
-void demo()
-{
- // std::cout << "\n\n\n";
- int linecount = prep_file("./data_banknote_authentication.txt");
- Network net ("./shuffled.txt", 4, 2, 1, 5, 10, 1);
- float epoch_cost = 1000;
- int epochs = 0;
- net.batches= 1;
- // net.feedforward();
- // net.backpropagate();
- // std::cout << net.cost() << "\n";
-
- while (epochs < 500) {
- int linecount = prep_file("./data_banknote_authentication.txt");
- float cost_sum = 0;
- for (int i = 0; i < linecount-net.batch_size; i+=net.batch_size) {
- net.feedforward();
- net.backpropagate();
- cost_sum += net.cost();
- // std::cout << net.cost() << " as it is " << net.labels[0] << " vs " << *net.layers[net.length-1].contents << "\n";
- net.batches++;
- int exit = net.next_batch();
- if (exit == -1) {
- break;
- }
- }
- net.batches=1;
- epoch_cost = 1.0/((float) linecount) * cost_sum;
- printf("EPOCH %i: Cost is %f for %i instances.\n", epochs, epoch_cost, linecount);
- epochs++;
- }
-}
-
-struct int_pair* map (struct str_pair input_pair)
-{
- int_pair* output_pairs = new int_pair[1024];
- int linecount = prep_file("./data_banknote_authentication.txt");
- Network net ("./shuffled.txt", 4, 2, 1, 5, 1, 1);
- float epoch_cost = 1000;
- int epochs = 0;
- net.batches= 1;
-
- while (epochs < 10) {
- int linecount = prep_file("./data_banknote_authentication.txt");
- float cost_sum = 0;
- for (int i = 0; i < linecount-net.batch_size; i+=net.batch_size) {
- net.feedforward();
- net.backpropagate();
- cost_sum += net.cost();
- net.batches++;
- int exit = net.next_batch();
- if (exit == -1) {
- break;
- }
- }
- net.batches=1;
- epoch_cost = 1.0/((float) linecount) * cost_sum;
- printf("EPOCH %i: Cost is %f for %i instances.\n", epochs, epoch_cost, linecount);
- epochs++;
- }
- int rounds = 1;
- int exit = 0;
- float totalcost = -1;
- while (exit == 0) {
- FILE* fptr = fopen(input_pair.key, "r");
- char line[1024] = {' '};
- int inputs = net.layers[0].contents->cols();
- int datalen = net.batch_size * inputs;
- float batch[datalen];
- for (int i = 0; i < net.batch_size*rounds + 1; i++) {
- if (fgets(line, 1024, fptr)==NULL) {
- exit = -1;
- }
- if (i >= rounds) {
- for (int j = 0; j < net.batch_size; j++) {
- fgets(line, 1024, fptr);
- sscanf(line, "%f,%f,%f,%f,%lf", &batch[0 + (j * inputs)], &batch[1 + (j * inputs)], &batch[2 + (j * inputs)], &batch[3 + (j * inputs)], &(*net.labels)(j));
- }
- }
- }
- float *batchptr = batch;
- net.update_layer(batchptr, datalen, 0);
- net.feedforward();
- for (int i = 0; i < net.batch_size; i++) {
- char key[1024];
- sprintf(key, "%i", net.batch_size);
- output_pairs[i].key = key;
- output_pairs[i].value = net.cost();
- }
- output_pairs[net.batch_size].key = (char*)'\0';
- output_pairs[net.batch_size].value = -1;
- totalcost += net.cost();
- rounds++;
- }
- return output_pairs;
-}
-
-int_pair* reduce (int_pair* input_pairs)
-{
- int_pair* output_pairs = new int_pair[2];
- int keysum = 0;
- int valsum = 0;
- for (int i = 0; i < 2; i++) {
- std::cout << input_pairs[i].key << " and " << strtol(input_pairs[i].key, NULL, 10) << "\n";
- keysum += strtol(input_pairs[i].key, NULL, 10);
- valsum += input_pairs[i].value;
- }
- char* key;
- std::cout << keysum << " and " << valsum << " are SUMS\n";
- sprintf(key, "%d", keysum);
- output_pairs[0].key = key;
- output_pairs[0].value = valsum;
- output_pairs[1].key = (char*) '\0';
- output_pairs[1].value = -1;
- return output_pairs;
-}
-
-int main(int argc, char** argv)
-{
- begin(argv[2], map, reduce, strtol(argv[1], NULL, 10), 2, argv[3]);
-}
diff --git a/test.hpp b/test.hpp
@@ -1,15 +0,0 @@
-#include "/Users/davidfreifeld/Downloads/eigen-3.3.7/Eigen/Dense"
-
-// extern "C"
-// {
-// #include "/Users/davidfreifeld/projects/mapreduce/mapreduce.h"
-// }
-
-#include <vector>
-#include <array>
-#include <iostream>
-#include <string>
-#include <cstdio>
-#include <fstream>
-#include <random>
-#include <algorithm>