From 7537f0217784c9f1783ab0889aae25f8e41e0874 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Thu, 15 Mar 2018 19:36:40 +0100 Subject: [PATCH] uczenie i testowanie --- common.h | 2 +- decider.cpp | 4 ++-- decider.h | 29 ++++++++++++++++++------ matrix.h | 31 ++++++++++++++++++++----- network.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++---- tester.cpp | 37 ++++++++++++++++++++---------- trainer.h | 35 ++++++++++++++++++----------- wtf.cpp | 3 +-- 8 files changed, 160 insertions(+), 46 deletions(-) diff --git a/common.h b/common.h index a01be47..66aa729 100644 --- a/common.h +++ b/common.h @@ -1,4 +1,4 @@ #include "network.h" #include "decider.h" -using current_decider = neural_decider<24, 16, 16, 32, 16>; +using current_decider = neural_decider<24, 12, 12, 32, 16>; diff --git a/decider.cpp b/decider.cpp index 4b5e54b..0bc41e5 100644 --- a/decider.cpp +++ b/decider.cpp @@ -11,9 +11,9 @@ void macd_decider::process(double price) signal.add(ema(macd.begin(), macd.begin() + 9)); } -void macd_decider::reset() +void macd_decider::reset(double price) { - prices = buffer(limit, .0); + prices = buffer(limit, price); signal = buffer(limit, .0); macd = buffer(limit, .0); } diff --git a/decider.h b/decider.h index f0528fb..e490096 100644 --- a/decider.h +++ b/decider.h @@ -6,6 +6,10 @@ #include #include +template +T sign(const T& value) { + return value < 0 ? -1 : (value > 0 ? value : 0); +} class decider { public: @@ -13,7 +17,7 @@ public: unsigned start_stock; virtual int decide(double price, double money, unsigned stock) = 0; - virtual void reset() = 0; + virtual void reset(double price) = 0; virtual ~decider() { } }; @@ -31,7 +35,7 @@ public: macd_decider(std::size_t limit = 1000); virtual void process(double price); - virtual void reset(); + virtual void reset(double price); }; template @@ -56,9 +60,10 @@ public: double buy = result.get(0, 0); double sell = result.get(1, 0); - double amount = (buy - sell - .5)/1.5; + double amount = buy - sell; + amount -= sign(amount) * .5; - return abs(buy - sell) <= .5 ? 0 : amount * start_stock / 10; + return abs(buy - sell) <= .5 ? 0 : amount * start_stock; } std::ostream& save(std::ostream& stream) { @@ -71,9 +76,9 @@ public: network.load(stream); } - virtual void reset() override + virtual void reset(double price) override { - macd_decider::reset(); + macd_decider::reset(price); } virtual ~neural_decider() { } @@ -88,6 +93,17 @@ public: return result; } + + self_t mutate(typename network_t::normalizer_t mutator) + { + self_t result; + + result.network = network.mutate(mutator); + result.start_money = start_money; + result.start_stock = start_stock; + + return result; + } private: typename network_t::input prepare(double money, unsigned stock) { @@ -118,7 +134,6 @@ private: tech = normalize(tech); auto concated = concat(prices, tech); - return concat(concated, state); } }; diff --git a/matrix.h b/matrix.h index 2afbeab..8b1a9d1 100644 --- a/matrix.h +++ b/matrix.h @@ -3,6 +3,7 @@ #include #include +#include #include template @@ -162,26 +163,45 @@ class matrix std::ostream& save(std::ostream& stream) { + char start[2] = { char(0xDE), char(0xAD) }; + char end[2] = { char(0xBE), char(0xEF) }; + T temp; + stream.write(start, 2); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; j++) { temp = get(i, j); - stream.write(reinterpret_cast(&temp), sizeof(T)); + stream.write((char*)(&temp), sizeof(T)); } } + stream.write(end, 2); return stream; } void load(std::istream& stream) { + char buf[2]; + + stream.read(buf, 2); + if (buf[0] != char(0xDE) || buf[1] != char(0xAD)) { + std::cerr << "Bledny prefix" << std::endl; + return; + } + T temp; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; j++) { - stream.read(reinterpret_cast(&temp), sizeof(T)); + stream.read((char*)(&temp), sizeof(T)); set(i, j, temp); } } + + stream.read(buf, 2); + if (buf[0] != char(0xBE) || buf[1] != char(0xEF)) { + std::cerr << "Bledny suffix" << std::endl; + return; + } } }; @@ -206,7 +226,7 @@ vector concat(const vector &a, const vector &b) for (int i = 0; i < n; i++) result.set(i, 0, a.get(i, 0)); for (int i = 0; i < m; i++) - result.set(i+n, 0, a.get(i, 0)); + result.set(i+n, 0, b.get(i, 0)); // YOU LIITLE FUCKING BASTARD return result; } @@ -218,10 +238,11 @@ vector normalize(const vector &vec) for (int i = 0; i < n; i++) { T temp = vec.get(i, 0); - accumulator += temp * temp; + accumulator += abs(temp); } - accumulator = sqrt(accumulator); + accumulator /= n; + std::function normalizer = [accumulator](const T& item) { return item / accumulator; }; return map(vec, normalizer); } diff --git a/network.h b/network.h index e59c4c0..6bb22f8 100644 --- a/network.h +++ b/network.h @@ -9,6 +9,7 @@ template struct layer { using filler_t = std::function; using combiner_t = std::function; + using mutator_t = std::function; matrix weights; vector bias; @@ -45,6 +46,21 @@ struct layer { return combine(rhs, combiner, combiner); } + layer mutate(mutator_t weight_mutator, mutator_t bias_mutator) + { + layer result; + + result.weights = ::map(weights, weight_mutator); + result.bias = ::map(bias, bias_mutator); + + return result; + } + + layer mutate(const layer &rhs, mutator_t mutator) + { + return mutate(mutator, mutator); + } + std::ostream& save(std::ostream& stream) { weights.save(stream); bias.save(stream); @@ -86,6 +102,7 @@ public: using filler_t = typename layer::filler_t; using combiner_t = typename layer::combiner_t; using normalizer_t = std::function; + using mutator_t = std::function; template using layer_type = typename layer_types::type; @@ -114,7 +131,8 @@ public: current.fill(filler); } - self combine(self& rhs, combiner_t weight_combiner, combiner_t bias_combiner) { + self combine(self& rhs, combiner_t weight_combiner, combiner_t bias_combiner) + { self result(normalizer); result.template get<0>() = get<0>().combine(rhs.template get<0>(), weight_combiner, bias_combiner); @@ -126,6 +144,22 @@ public: return combine(rhs, combiner, combiner); } + self mutate(mutator_t weight_mutator, mutator_t bias_mutator) + { + self result(normalizer); + result.template get<0>() = get<0>().mutate( + weight_mutator, + bias_mutator + ); + + return result; + } + + self mutate(mutator_t mutator) + { + return mutate(mutator, mutator); + } + std::ostream& save(std::ostream& stream) { current.save(stream); @@ -184,10 +218,15 @@ public: subnetwork.fill(weights, bias); } - self combine(self& rhs, typename base::combiner_t weight_combiner, typename base::combiner_t bias_combiner) { - self result(normalizer); + self combine(self& rhs, typename base::combiner_t weight_combiner, typename base::combiner_t bias_combiner) + { + self result((this->normalizer)); - result.template get<0>() = get<0>().combine(rhs.template get<0>(), weight_combiner, bias_combiner); + result.template get<0>() = get<0>().combine( + rhs.template get<0>(), + weight_combiner, + bias_combiner + ); result.subnetwork = subnetwork.combine(rhs.subnetwork, weight_combiner, bias_combiner); return result; @@ -198,6 +237,24 @@ public: return combine(rhs, combiner, combiner); } + self mutate(typename base::mutator_t weight_mutator, typename base::mutator_t bias_mutator) + { + self result((this->normalizer)); + + result.template get<0>() = get<0>().mutate( + weight_mutator, + bias_mutator + ); + result.subnetwork = subnetwork.mutate(weight_mutator, bias_mutator); + + return result; + } + + self mutate(typename base::mutator_t mutator) + { + return mutate(mutator, mutator); + } + std::ostream& save(std::ostream& stream) { base::save(stream); diff --git a/tester.cpp b/tester.cpp index 76ab05b..3fcce97 100644 --- a/tester.cpp +++ b/tester.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include "helpers.h" @@ -19,12 +20,15 @@ int main(int argc, const char* argv[]) args(1) >> network; args(2) >> input; - double money; - unsigned stock; + double money, start_money; + unsigned stock, start_stock; args({"s", "stock"}, 1000) >> stock; args({"m", "money"}, 1000.) >> money; + start_money = money; + start_stock = stock; + std::function normalizer = [](const double& result) -> double { return erf(result); }; current_decider decider(normalizer); @@ -37,7 +41,11 @@ int main(int argc, const char* argv[]) decider.start_money = money; decider.start_stock = stock; std::cout << "x,price,decsion,money,stock" << std::endl; - for (int i = 0; input_file >> price; i++) { + input_file >> price; + decider.reset(price); + + int i = 0; + do { auto decision = decider.decide(price, money, stock); auto current = price * stock + money; auto max_credit = std::max(current * 0.05, -1e4); @@ -51,15 +59,20 @@ int main(int argc, const char* argv[]) money -= price * decision; stock += decision; - /* std::cout */ - /* << i << "," */ - /* << price << "," */ - /* << decision << "," */ - /* << money << "," */ - /* << stock */ - /* << std::endl; */ - } - std::cout << "Koniec: " << money + stock*price; + std::cout + << ++i << "," + << price << "," + << decision << "," + << money << "," + << stock + << std::endl; + + + } while(input_file >> price); + std::cout << "Koniec: " + << money + stock*price << std::showpos << "(" + << (money + stock*price) / (start_money + start_stock*price) + << ")"; /* decider.network.save(std::cout); */ } diff --git a/trainer.h b/trainer.h index e3753b1..bcf7c97 100644 --- a/trainer.h +++ b/trainer.h @@ -36,12 +36,10 @@ public: std::function>, const dataset&, double, unsigned)> q; trainer(double money, unsigned stock, std::size_t n, std::function factory) - : factory(factory), id(0), generation(1), money(money), stock(stock), n(n), - q([](std::shared_ptr> x, const dataset& input, double money, unsigned stock) { - return money + input.back() * stock; - }), - random_engine(std::time(0)) + : factory(factory), id(0), generation(1), money(money), stock(stock), n(n), random_engine(std::time(0)) { + this->q = [=](std::shared_ptr> x, const dataset& input, double money, unsigned stock) { + return (money + stock * input.back()) / (this->money + this->stock * input.front()); }; add(n); } @@ -82,7 +80,7 @@ public: { trainee->decider.start_money = money; trainee->decider.start_stock = stock; - trainee->decider.reset(); + trainee->decider.reset(input.front()); double money = this->money; unsigned stock = this->stock; @@ -181,28 +179,39 @@ public: std::uniform_real_distribution ratio(0.0, 1.0); auto combiner = [=](const double& a, const double& b){ - auto mutation = (rand() % 2 ? -1 : 1) * exponential(random_engine); - if (exponential(random_engine) < 1) { auto r = ratio(random_engine); - return r * a + (1 - r) * b + mutation; + return r * a + (1 - r) * b; } - return (rand() % 2 ? a : b) + mutation; + return rand() % 2 ? a : b; }; + auto mutator = [=](const double& a) { + auto mutation = (rand() % 2 ? -1 : 1) * exponential(random_engine); + return a + mutation; + }; + + std::size_t to_combine = diff * 0.4, to_mutate = diff * 0.4; + unsigned first, second; - for (int i = 0; i < diff - 4; i++) { + for (int i = 0; i < to_combine; i++) { first = distribution(random_engine); do { second = distribution(random_engine); } while (first == second); - auto combined = trainees[first]->decider.combine(trainees[second]->decider, combiner); + auto combined = trainees[first]->decider.combine(trainees[second]->decider, combiner).mutate(mutator); std::cout << "Łączenie #" << trainees[first]->id << " z #" << trainees[second]->id << " dało #" << (id+1) << std::endl; add(combined); } - add(4); // some random things + for (int i = 0; i < to_mutate; i++) { + first = distribution(random_engine); + std::cout << "Mutowanie #" << trainees[first]->id << " w #" << id+1 << std::endl; + add(trainees[first]->decider.mutate(mutator)); + } + + add(diff - to_combine - to_mutate); // some random things generation++; } diff --git a/wtf.cpp b/wtf.cpp index b0a9622..88c0140 100644 --- a/wtf.cpp +++ b/wtf.cpp @@ -14,8 +14,7 @@ #include "network.h" #include "decider.h" #include "trainer.h" - -using current_decider = neural_decider<24, 16, 16, 32, 16>; +#include "common.h" int main(int argc, char* argv[]) {