Skip to content

Commit

Permalink
changes made from review, added tests and all passed but only when ed…
Browse files Browse the repository at this point in the history
…ge weights are allowed to train
  • Loading branch information
jared-m-murphy committed May 15, 2024
1 parent dc8ad57 commit 73e1f2a
Show file tree
Hide file tree
Showing 19 changed files with 1,062 additions and 26 deletions.
2 changes: 1 addition & 1 deletion examm/examm.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) {
// method
WeightType weight_initialize = weight_rules->get_weight_initialize_method();
WeightType weight_inheritance = weight_rules->get_weight_inheritance_method();
if ((weight_inheritance == weight_initialize) && (weight_inheritance != WeightType::GP)) {
if (weight_inheritance == weight_initialize && weight_inheritance != WeightType::GP) {
Log::debug(
"weight inheritance at crossover method is %s, setting weights to %s randomly \n",
WEIGHT_TYPES_STRING[weight_inheritance].c_str(), WEIGHT_TYPES_STRING[weight_inheritance].c_str()
Expand Down
6 changes: 1 addition & 5 deletions multithreaded/examm_mt.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,7 @@ int main(int argc, char** argv) {
WeightRules* weight_rules = new WeightRules();
weight_rules->initialize_from_args(arguments);

string seed_genome_type;
RNN_Genome* seed_genome;
get_argument(arguments, "--seed_genome_type", false, seed_genome_type);

seed_genome = get_seed_genome(arguments, time_series_sets, weight_rules);
RNN_Genome* seed_genome = get_seed_genome(arguments, time_series_sets, weight_rules);

examm = generate_examm_from_arguments(arguments, time_series_sets, weight_rules, seed_genome);

Expand Down
11 changes: 11 additions & 0 deletions rnn/generate_nn.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ RNN_Genome* create_memory_cell_nn(
#define create_inverse(...) create_memory_cell_nn<INVERSE_Node>(__VA_ARGS__)
#define create_multiply(...) create_memory_cell_nn<MULTIPLY_Node>(__VA_ARGS__)

// GP nodes
// WARNING: All gp node gradient tests will fail unless the conditions for d_weight
// to be set to zero in edge and recurrent edge backwards pass are turned off
#define create_sin_gp(...) create_memory_cell_nn<SIN_Node_GP>(__VA_ARGS__)
#define create_sum_gp(...) create_memory_cell_nn<SUM_Node_GP>(__VA_ARGS__)
#define create_cos_gp(...) create_memory_cell_nn<COS_Node_GP>(__VA_ARGS__)
#define create_tanh_gp(...) create_memory_cell_nn<TANH_Node_GP>(__VA_ARGS__)
#define create_sigmoid_gp(...) create_memory_cell_nn<SIGMOID_Node_GP>(__VA_ARGS__)
#define create_inverse_gp(...) create_memory_cell_nn<INVERSE_Node_GP>(__VA_ARGS__)
#define create_multiply_gp(...) create_memory_cell_nn<MULTIPLY_Node_GP>(__VA_ARGS__)

DNASNode* create_dnas_node(int32_t& innovation_counter, double depth, const vector<int32_t>& node_types);

RNN_Genome* create_dnas_nn(
Expand Down
6 changes: 2 additions & 4 deletions rnn/multiply_node_gp.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,8 @@ void MULTIPLY_Node_GP::try_update_deltas(int32_t time) {
num *= d_input[time];

// most likely gradient got huge, so clip it
if (num == NAN || num == -numeric_limits<double>::infinity()) {
num = -1000.0;
} else if (num == NAN || num == numeric_limits<double>::infinity()) {
num = 1000.0;
if (!isfinite(num)) {
num = copysign(1, num) * 1000;
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions rnn/rnn_edge.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ void RNN_Edge::propagate_backward(int32_t time) {
delta = output_node->d_input[time];
}

// WARNING: With this feature all gradient tests for these node types naturally fail.
// This condition must be eliminated for tests to pass.
if (output_node->node_type == OUTPUT_NODE_GP || output_node->node_type == SIN_NODE_GP
|| output_node->node_type == COS_NODE_GP || output_node->node_type == TANH_NODE_GP
|| output_node->node_type == SIGMOID_NODE_GP || output_node->node_type == SUM_NODE_GP
Expand Down Expand Up @@ -214,6 +216,8 @@ void RNN_Edge::propagate_backward(int32_t time, bool training, double dropout_pr
}
}

// WARNING: With this feature all gradient tests for these node types naturally fail.
// This condition must be eliminated for tests to pass.
if (output_node->node_type == OUTPUT_NODE_GP || output_node->node_type == SIN_NODE_GP
|| output_node->node_type == COS_NODE_GP || output_node->node_type == TANH_NODE_GP
|| output_node->node_type == SIGMOID_NODE_GP || output_node->node_type == SUM_NODE_GP
Expand Down
9 changes: 6 additions & 3 deletions rnn/rnn_genome.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3283,7 +3283,8 @@ RNN_Node_Interface* RNN_Genome::read_node_from_stream(istream& bin_istream) {
node = new MGU_Node(innovation_number, layer_type, depth);
} else if (node_type == UGRNN_NODE) {
node = new UGRNN_Node(innovation_number, layer_type, depth);
} else if (node_type == SIMPLE_NODE || node_type == JORDAN_NODE || node_type == ELMAN_NODE || node_type == OUTPUT_NODE_GP || node_type == INPUT_NODE_GP) {
} else if (node_type == SIMPLE_NODE || node_type == JORDAN_NODE || node_type == ELMAN_NODE
|| node_type == OUTPUT_NODE_GP || node_type == INPUT_NODE_GP) {
if (layer_type == HIDDEN_LAYER) {
node = new RNN_Node(innovation_number, layer_type, depth, node_type);
} else {
Expand Down Expand Up @@ -4215,7 +4216,8 @@ void RNN_Genome::write_equations(ostream& outstream) {
current_output_equation += "tanh(" + input_equation;
} else if (output_node->node_type == SIGMOID_NODE || output_node->node_type == SIGMOID_NODE_GP) {
current_output_equation += "sigmoid(" + input_equation;
} else if (output_node->node_type == SUM_NODE || output_node->node_type == SUM_NODE_GP || output_node->node_type == OUTPUT_NODE_GP) {
} else if (output_node->node_type == SUM_NODE || output_node->node_type == SUM_NODE_GP
|| output_node->node_type == OUTPUT_NODE_GP) {
current_output_equation += input_equation;
} else if (output_node->node_type == MULTIPLY_NODE || output_node->node_type == MULTIPLY_NODE_GP) {
current_output_equation += input_equation;
Expand Down Expand Up @@ -4331,7 +4333,8 @@ void RNN_Genome::write_equations(ostream& outstream) {
current_output_equation += "tanh(" + input_equation;
} else if (output_node->node_type == SIGMOID_NODE || output_node->node_type == SIGMOID_NODE_GP) {
current_output_equation += "sigmoid(" + input_equation;
} else if (output_node->node_type == SUM_NODE || output_node->node_type == SUM_NODE_GP || output_node->node_type == OUTPUT_NODE_GP) {
} else if (output_node->node_type == SUM_NODE || output_node->node_type == SUM_NODE_GP
|| output_node->node_type == OUTPUT_NODE_GP) {
current_output_equation += input_equation;
} else if (output_node->node_type == MULTIPLY_NODE || output_node->node_type == MULTIPLY_NODE_GP) {
current_output_equation += input_equation;
Expand Down
4 changes: 4 additions & 0 deletions rnn/rnn_recurrent_edge.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ void RNN_Recurrent_Edge::propagate_backward(int32_t time) {
if (time - recurrent_depth >= 0) {
// Log::trace("propagating backward on recurrent edge %d from time %d to time %d from node %d to node %d\n",
// innovation_number, time, time - recurrent_depth, output_innovation_number, input_innovation_number);

// WARNING: With this feature all gradient tests for these node types naturally fail.
// This condition must be eliminated for tests to pass.
if (output_node->node_type == OUTPUT_NODE_GP || output_node->node_type == SIN_NODE_GP
|| output_node->node_type == COS_NODE_GP || output_node->node_type == TANH_NODE_GP
|| output_node->node_type == SIGMOID_NODE_GP || output_node->node_type == SUM_NODE_GP
Expand All @@ -229,6 +232,7 @@ void RNN_Recurrent_Edge::propagate_backward(int32_t time) {
} else {
d_weight += delta * input_node->output_values[time - recurrent_depth];
}

deltas[time] = delta * weight;
input_node->output_fired(time - recurrent_depth, deltas[time]);
}
Expand Down
4 changes: 2 additions & 2 deletions rnn/tanh_node_gp.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ using std::vector;
#include "tanh_node_gp.hxx"

TANH_Node_GP::TANH_Node_GP(int32_t _innovation_number, int32_t _layer_type, double _depth)
: RNN_Node(_innovation_number, _layer_type, _depth, SIN_NODE_GP) {
Log::debug("created node: %d, layer type: %d, node type: SIN_NODE_GP\n", innovation_number, layer_type);
: RNN_Node(_innovation_number, _layer_type, _depth, TANH_NODE_GP) {
Log::debug("created node: %d, layer type: %d, node type: TANH_NODE_GP\n", innovation_number, layer_type);
}

TANH_Node_GP::~TANH_Node_GP() {
Expand Down
22 changes: 22 additions & 0 deletions rnn_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,25 @@ target_link_libraries(test_get_equations examm_strategy exact_common exact_time_
add_executable(test_node_to_binary test_node_to_binary.cxx gradient_test.cxx)
target_link_libraries(test_node_to_binary examm_strategy exact_common exact_time_series exact_weights examm_nn ${MYSQL_LIBRARIES} pthread)

add_executable(test_sin_gp_gradients test_sin_gp_gradients.cxx gradient_test.cxx)
target_link_libraries(test_sin_gp_gradients examm_strategy exact_common exact_time_series exact_weights examm_nn ${MYSQL_LIBRARIES} pthread)

add_executable(test_sum_gp_gradients test_sum_gp_gradients.cxx gradient_test.cxx)
target_link_libraries(test_sum_gp_gradients examm_strategy exact_common exact_time_series exact_weights examm_nn ${MYSQL_LIBRARIES} pthread)

add_executable(test_cos_gp_gradients test_cos_gp_gradients.cxx gradient_test.cxx)
target_link_libraries(test_cos_gp_gradients examm_strategy exact_common exact_time_series exact_weights examm_nn ${MYSQL_LIBRARIES} pthread)

add_executable(test_tanh_gp_gradients test_tanh_gp_gradients.cxx gradient_test.cxx)
target_link_libraries(test_tanh_gp_gradients examm_strategy exact_common exact_time_series exact_weights examm_nn ${MYSQL_LIBRARIES} pthread)

add_executable(test_sigmoid_gp_gradients test_sigmoid_gp_gradients.cxx gradient_test.cxx)
target_link_libraries(test_sigmoid_gp_gradients examm_strategy exact_common exact_time_series exact_weights examm_nn ${MYSQL_LIBRARIES} pthread)

add_executable(test_inverse_gp_gradients test_inverse_gp_gradients.cxx gradient_test.cxx)
target_link_libraries(test_inverse_gp_gradients examm_strategy exact_common exact_time_series exact_weights examm_nn ${MYSQL_LIBRARIES} pthread)

add_executable(test_multiply_gp_gradients test_multiply_gp_gradients.cxx gradient_test.cxx)
target_link_libraries(test_multiply_gp_gradients examm_strategy exact_common exact_time_series exact_weights examm_nn ${MYSQL_LIBRARIES} pthread)


136 changes: 136 additions & 0 deletions rnn_tests/test_cos_gp_gradients.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include <chrono>
#include <fstream>
using std::getline;
using std::ifstream;

#include <random>
using std::minstd_rand0;
using std::uniform_real_distribution;

#include <string>
using std::string;

#include <vector>
using std::vector;

#include "common/arguments.hxx"
#include "common/log.hxx"
#include "gradient_test.hxx"
#include "rnn/cos_node_gp.hxx"
#include "rnn/generate_nn.hxx"
#include "rnn/rnn_edge.hxx"
#include "rnn/rnn_genome.hxx"
#include "rnn/rnn_node.hxx"
#include "rnn/rnn_node_interface.hxx"
#include "time_series/time_series.hxx"
#include "weights/weight_rules.hxx"

int main(int argc, char** argv) {
vector<string> arguments = vector<string>(argv, argv + argc);

Log::initialize(arguments);
Log::set_id("main");

initialize_generator();

RNN_Genome* genome;

Log::info("TESTING COS_GP\n");

vector<vector<double> > inputs;
vector<vector<double> > outputs;

int input_length = 10;
get_argument(arguments, "--input_length", true, input_length);

WeightRules* weight_rules = new WeightRules();
weight_rules->initialize_from_args(arguments);

for (int32_t max_recurrent_depth = 1; max_recurrent_depth <= 5; max_recurrent_depth++) {
Log::info("testing with max recurrent depth: %d\n", max_recurrent_depth);

inputs.resize(1);
outputs.resize(1);

generate_random_vector(input_length, inputs[0]);
generate_random_vector(input_length, outputs[0]);

vector<string> inputs1{"input 1"};
vector<string> outputs1{"output 1"};

// Test 1 input, 1 output, no hidden
genome = create_cos_gp(inputs1, 0, 0, outputs1, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 1 Input, 1 Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs1, 1, 1, outputs1, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 1 Input, 1x1 Hidden, 1 Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs1, 1, 2, outputs1, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 1 Input, 1x2 Hidden, 1 Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs1, 2, 2, outputs1, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 1 Input, 2x2 Hidden, 1 Output", genome, inputs, outputs);
delete genome;

vector<string> inputs2{"input 1", "input 2"};
vector<string> outputs2{"output 1", "output 2"};

// //Test 2 inputs, 2 outputs, no hidden
genome = create_cos_gp(inputs2, 0, 0, outputs2, max_recurrent_depth, weight_rules);

inputs.resize(2);
outputs.resize(2);
generate_random_vector(input_length, inputs[0]);
generate_random_vector(input_length, outputs[0]);
generate_random_vector(input_length, inputs[1]);
generate_random_vector(input_length, outputs[1]);

gradient_test("COS_GP: 2 Input, 2 Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs2, 2, 2, outputs2, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 2 Input, 2x2 Hidden, 2 Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs2, 2, 3, outputs2, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 2 Input, 2x3 Hidden, 2 Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs2, 3, 3, outputs2, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 2 Input, 3x3 Hidden, 2 Output", genome, inputs, outputs);
delete genome;

vector<string> inputs3{"input 1", "input 2", "input 3"};
vector<string> outputs3{"output 1", "output 2", "input 3"};

// Test 3 inputs, 3 outputs, no hidden
genome = create_cos_gp(inputs3, 0, 0, outputs3, max_recurrent_depth, weight_rules);

inputs.resize(3);
outputs.resize(3);
generate_random_vector(input_length, inputs[0]);
generate_random_vector(input_length, outputs[0]);
generate_random_vector(input_length, inputs[1]);
generate_random_vector(input_length, outputs[1]);
generate_random_vector(input_length, inputs[2]);
generate_random_vector(input_length, outputs[2]);

gradient_test("COS_GP: Three Input, Three Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs3, 3, 3, outputs3, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 3 Input, 3x3 Hidden, 3 Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs3, 3, 4, outputs3, max_recurrent_depth, weight_rules);
gradient_test("COS_GP: 3 Input, 3x4 Hidden, 3 Output", genome, inputs, outputs);
delete genome;

genome = create_cos_gp(inputs3, 4, 4, outputs3, max_recurrent_depth, weight_rules);
gradient_test("COS_gp: 3 Input, 4x4 Hidden, 3 Output", genome, inputs, outputs);
delete genome;
}
}
Loading

0 comments on commit 73e1f2a

Please sign in to comment.