uczenie i testowanie

This commit is contained in:
Kacper Donat 2018-03-15 19:36:40 +01:00
parent 72fb76e8c2
commit 7537f02177
8 changed files with 160 additions and 46 deletions

View File

@ -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>;

View File

@ -11,9 +11,9 @@ void macd_decider::process(double price)
signal.add(ema<double>(macd.begin(), macd.begin() + 9));
}
void macd_decider::reset()
void macd_decider::reset(double price)
{
prices = buffer<double>(limit, .0);
prices = buffer<double>(limit, price);
signal = buffer<double>(limit, .0);
macd = buffer<double>(limit, .0);
}

View File

@ -6,6 +6,10 @@
#include <iterator>
#include <iostream>
template <typename T>
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 <int p, int m, int s, int ...layers>
@ -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);
}
};

View File

@ -3,6 +3,7 @@
#include <iostream>
#include <vector>
#include <exception>
#include <functional>
template <typename T, int m, int n>
@ -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<char*>(&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<char*>(&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<T, m+n> concat(const vector<T, n> &a, const vector<T, m> &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<T, n> normalize(const vector<T, n> &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<T(const T&)> normalizer = [accumulator](const T& item) { return item / accumulator; };
return map(vec, normalizer);
}

View File

@ -9,6 +9,7 @@ template <typename T, int in, int out>
struct layer {
using filler_t = std::function<T(const int&, const int&)>;
using combiner_t = std::function<T(const T&, const T&)>;
using mutator_t = std::function<T(const T&)>;
matrix<T, out, in> weights;
vector<T, out> bias;
@ -45,6 +46,21 @@ struct layer {
return combine(rhs, combiner, combiner);
}
layer<T, in, out> mutate(mutator_t weight_mutator, mutator_t bias_mutator)
{
layer<T, in, out> result;
result.weights = ::map(weights, weight_mutator);
result.bias = ::map(bias, bias_mutator);
return result;
}
layer<T, in, out> mutate(const layer<T, in, out> &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<T, in, out>::filler_t;
using combiner_t = typename layer<T, in, out>::combiner_t;
using normalizer_t = std::function<T(const T&)>;
using mutator_t = std::function<T(const T&)>;
template <std::size_t N> using layer_type = typename layer_types<N, T, in, out>::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);

View File

@ -1,5 +1,6 @@
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <algorithm>
#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<double(const double&)> 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); */
}

View File

@ -36,12 +36,10 @@ public:
std::function<double(std::shared_ptr<trained<T>>, const dataset&, double, unsigned)> q;
trainer(double money, unsigned stock, std::size_t n, std::function<T()> factory)
: factory(factory), id(0), generation(1), money(money), stock(stock), n(n),
q([](std::shared_ptr<trained<T>> 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<trained<T>> 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<double> 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++;
}

View File

@ -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[])
{