jacobian

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit dca5b3e70a6964c668ca1d59b2de7ce8773959d8
parent 7e832f190fc0352ef10cae204227579a30e6e458
Author: David Freifeld <freifeld.david@gmail.com>
Date:   Mon, 22 Jun 2020 17:59:24 -0700

Merge python-bindings

Diffstat:
AMakefile | 6++++++
Mbpnn.cpp | 32+++++++++++++++++++++++++++++++-
Mbpnn.hpp | 2++
Mmr_bpnn_2.cpp | 28++++++++++++++++++++++------
Mreadme.md | 19++++++++++++++-----
5 files changed, 75 insertions(+), 12 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,6 @@ + +all: mr_bpnn_2.cpp bpnn.cpp mapreduce.a + g++ -w -O2 -Wall -shared -std=c++11 -undefined dynamic_lookup `python3 -m pybind11 --includes` mr_bpnn_2.cpp bpnn.cpp mapreduce.a -o mrbpnn`python3-config --extension-suffix` + +clean: + $(RM) mrbpnn diff --git a/bpnn.cpp b/bpnn.cpp @@ -41,7 +41,8 @@ void Layer::initWeights(Layer next) Network::Network(char* path, int inputs, int hidden, int outputs, int neurons, int batch_sz, float rate) { learning_rate = rate; - fpath = path; + instances = prep_file(path, "./shuffled.txt"); + fpath = "./shuffled.txt"; length = hidden + 2; batch_size = batch_sz; FILE* fptr = fopen(fpath, "r"); @@ -252,6 +253,35 @@ float Network::test(char* path) return acc_sum/chunks; } +void Network::train(int total_epochs) +{ + float epoch_cost = 1000; + float epoch_accuracy = -1; + int epochs = 0; + printf("Beginning train on %i instances for %i epochs...\n", instances, total_epochs); + while (epochs < total_epochs) { + auto ep_begin = std::chrono::high_resolution_clock::now(); + float cost_sum = 0; + float acc_sum = 0; + for (int i = 0; i <= instances-batch_size; i+=batch_size) { + feedforward(); + backpropagate(); + cost_sum += cost(); + acc_sum += accuracy(); + if (i != instances-batch_size) { // Don't try to advance batch on final batch. + next_batch(fpath); + } batches++; + } + epoch_accuracy = 1.0/((float) instances/batch_size) * acc_sum; + epoch_cost = 1.0/((float) instances/batch_size) * cost_sum; + auto ep_end = std::chrono::high_resolution_clock::now(); + double epochtime = (double) std::chrono::duration_cast<std::chrono::nanoseconds>(ep_end-ep_begin).count() / pow(10,9); + printf("Epoch %i/%i - time %f - cost %f - acc %f\n", epochs+1, total_epochs, epochtime, epoch_cost, epoch_accuracy); + batches=1; + epochs++; + } +} + void demo(int total_epochs) { int linecount = prep_file("./extra.txt", "./shuffled.txt"); diff --git a/bpnn.hpp b/bpnn.hpp @@ -28,6 +28,7 @@ public: class Network { public: char* fpath; + int instances; std::vector<Layer> layers; int length; @@ -51,6 +52,7 @@ public: void backpropagate(); int next_batch(char* path); float test(char* path); + void train(int total_epochs); }; void demo(int total_epochs); diff --git a/mr_bpnn_2.cpp b/mr_bpnn_2.cpp @@ -1,4 +1,6 @@ +#include <pybind11/pybind11.h> #include "bpnn.hpp" +namespace py = pybind11; struct pair* map (struct pair input_pair) { @@ -101,13 +103,27 @@ void translate(char* path) free(line); } - - -int main(int argc, char** argv) +double benchmark(int epochs) { auto prog_begin = std::chrono::high_resolution_clock::now(); - prep_file(argv[2], "./shuffled"); - begin("./shuffled", map, reduce, translate, strtol(argv[1], NULL, 10), 1, argv[3], strtol(argv[4], NULL, 10)); + demo(epochs); auto prog_end = std::chrono::high_resolution_clock::now(); - std::cout << "Time: " << std::chrono::duration_cast<std::chrono::nanoseconds>(prog_end-prog_begin).count() / pow(10,9) << "\n"; + return std::chrono::duration_cast<std::chrono::nanoseconds>(prog_end-prog_begin).count(); +} + + +PYBIND11_MODULE(mrbpnn, m) { + m.doc() = "pybind11 example plugin"; // optional module docstring + + m.def("benchmark", &benchmark, "A function which times the BPNN", py::arg("epochs")); + py::class_<Network>(m, "Network") + .def(py::init<char*, int, int, int, int, int, float>()) + .def("feedforward", &Network::feedforward) + .def("backpropagate", &Network::backpropagate) + .def("list_net", &Network::list_net) + .def("cost", &Network::cost) + .def("accuracy", &Network::accuracy) + .def("update_layer", &Network::update_layer, py::arg("vals"), py::arg("len"), py::arg("index")) + .def("next_batch", &Network::next_batch, py::arg("path")) + .def("train", &Network::train, py::arg("epochs")); } diff --git a/readme.md b/readme.md @@ -1,4 +1,3 @@ - # ML in Parallel ## About @@ -28,7 +27,17 @@ g++ mr_bpnn_2.cpp bpnn.cpp mapreduce.a -O2 -o bpnn -std=c++11 -w Compare these demonstrations with a sample Keras demo by running `python kerasdemo.py` ## Usage -As of now "ML in Parallel" is not fit for usage inside code. -However: -- Initial prototype code is being cleaned up so as to make it more usable. -- Python bindings with `pybind11` are in development for improved usage. +As of now "ML in Parallel" is not fully fit for usage inside code. + +### Python Bindings +This feature is largely experimental but is the preferred way to demo as of now. + +1. Install both the C++ end of pybind11 and the python end. +2. Build with `make` or the much uglier alternative: +``` +c++ -w -O2 -Wall -shared -std=c++11 -undefined dynamic_lookup `python3 -m pybind11 --includes` mr_bpnn_2.cpp bpnn.cpp mapreduce.a -o mrbpnn`python3-config --extension-suffix` +``` +3. Copy the `mrbpnn.cpython-37m-darwin.so` file into your personal project directory. +4. Import `mrbpnn` from your Python code and use it. +5. Profit. +