uczenie i testowanie
This commit is contained in:
parent
72fb76e8c2
commit
7537f02177
2
common.h
2
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>;
|
||||
|
@ -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);
|
||||
}
|
||||
|
29
decider.h
29
decider.h
@ -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);
|
||||
}
|
||||
};
|
||||
|
31
matrix.h
31
matrix.h
@ -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);
|
||||
}
|
||||
|
65
network.h
65
network.h
@ -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);
|
||||
|
37
tester.cpp
37
tester.cpp
@ -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); */
|
||||
}
|
||||
|
||||
|
35
trainer.h
35
trainer.h
@ -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++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user