diff --git a/src/Network/ACSFNeuralNetwork.cpp b/src/Network/ACSFNeuralNetwork.cpp index 07cae17ebb143cd26fa0d331462bb733bc098fae..87fa47590e2fb0f83bac3e00186efb4c40fdfbf7 100644 --- a/src/Network/ACSFNeuralNetwork.cpp +++ b/src/Network/ACSFNeuralNetwork.cpp @@ -12,48 +12,59 @@ lib4neuro::ACSFNeuralNetwork::ACSFNeuralNetwork(std::unordered_map<ELEMENT_SYMBO std::unordered_map<ELEMENT_SYMBOL, std::vector<NEURON_TYPE>> type_hidden_neurons) { /* Construct the neural network */ std::vector<size_t> inputs; - std::vector<size_t> subnet_outputs; - size_t neuron_idx; - std::unordered_map<ELEMENT_SYMBOL, std::vector<size_t>> subnet_idxs; - std::unordered_map<ELEMENT_SYMBOL, std::vector<size_t>> subnet_neuron_idxs; - std::unordered_map<ELEMENT_SYMBOL, std::vector<size_t>> subnet_connection_idxs; + std::unordered_map<ELEMENT_SYMBOL, size_t> subnet_neuron_shifts; + std::unordered_map<ELEMENT_SYMBOL, size_t> subnet_connection_shifts; + std::unordered_map<ELEMENT_SYMBOL, bool> subnet_constructed; + size_t last_neuron_bias_idx = 0; + size_t last_connection_weight_idx = 0; + + std::shared_ptr<Neuron> output_neuron = std::make_shared<NeuronLinear>(); + size_t last_neuron_idx = this->add_neuron(output_neuron, BIAS_TYPE::NO_BIAS); + std::vector<size_t> outputs = {last_neuron_idx}; + for(size_t i = 0; i < elements_list.size(); i++) { std::vector<size_t> previous_layer; std::vector<size_t> new_layer; + size_t first_input_neuron_index = last_neuron_idx + 1; + /* Create input neurons for sub-net */ std::shared_ptr<NeuronLinear> inp_n; for(size_t j = 0; j < elements[elements_list.at(i)]->getSymmetryFunctions().size(); j++) { inp_n = std::make_shared<NeuronLinear>(); - neuron_idx = this->add_neuron(inp_n, BIAS_TYPE::NO_BIAS); - previous_layer.emplace_back(neuron_idx); - inputs.emplace_back(neuron_idx); + last_neuron_idx = this->add_neuron(inp_n, BIAS_TYPE::NO_BIAS); + previous_layer.emplace_back(last_neuron_idx); + inputs.emplace_back(last_neuron_idx); } /* Add an additional input neuron for charge, if provided */ if(with_charge) { inp_n = std::make_shared<NeuronLinear>(); - neuron_idx = this->add_neuron(inp_n, BIAS_TYPE::NO_BIAS); - previous_layer.emplace_back(neuron_idx); - inputs.emplace_back(neuron_idx); + last_neuron_idx = this->add_neuron(inp_n, BIAS_TYPE::NO_BIAS); + previous_layer.emplace_back(last_neuron_idx); + inputs.emplace_back(last_neuron_idx); } /* Create subnet for the current element */ bool new_subnet = false; - if(subnet_neuron_idxs.find(elements_list.at(i)) == subnet_neuron_idxs.end()) { + if(subnet_constructed.find(elements_list.at(i)) == subnet_constructed.end()) { new_subnet = true; - subnet_neuron_idxs[elements_list.at(i)] = std::vector<size_t>(); - subnet_connection_idxs[elements_list.at(i)] = std::vector<size_t>(); + subnet_constructed[elements_list.at(i)] = true; + subnet_neuron_shifts[elements_list.at(i)] = last_neuron_bias_idx; + subnet_connection_shifts[elements_list.at(i)] = last_connection_weight_idx; } + + // std::cout << "Particle " << i << ", input neuron indices: " << first_input_neuron_index << " - " << last_neuron_idx << std::endl; /* Create hidden layers in sub-net */ std::vector<unsigned int> n_neurons = n_hidden_neurons[elements_list.at(i)]; std::vector<NEURON_TYPE> types = type_hidden_neurons[elements_list.at(i)]; - size_t local_neuron_idx = 0; - size_t local_connection_idx = 0; + + size_t local_neuron_idx = subnet_neuron_shifts[elements_list.at(i)]; + size_t local_connection_idx = subnet_connection_shifts[elements_list.at(i)]; for(size_t j = 0; j < n_neurons.size(); j++) { /* Iterate over hidden layers */ /* Create hidden neurons */ @@ -79,28 +90,31 @@ lib4neuro::ACSFNeuralNetwork::ACSFNeuralNetwork(std::unordered_map<ELEMENT_SYMBO } if(new_subnet) { - neuron_idx = this->add_neuron(hid_n, + last_neuron_idx = this->add_neuron(hid_n, BIAS_TYPE::NEXT_BIAS); - subnet_neuron_idxs[elements_list.at(i)].emplace_back(neuron_idx); + // std::cout << " new subnet, neuron index: " << last_neuron_idx << ", neuron bias: " << last_neuron_bias_idx << std::endl; + last_neuron_bias_idx++; } else { - std::cout << subnet_neuron_idxs[elements_list.at(i)].at(0)+local_neuron_idx << std::endl; - neuron_idx = this->add_neuron(hid_n, + last_neuron_idx = this->add_neuron(hid_n, BIAS_TYPE::EXISTING_BIAS, local_neuron_idx); + // std::cout << " old subnet, neuron index: " << last_neuron_idx << ", neuron bias: " << local_neuron_idx << std::endl; } local_neuron_idx++; - new_layer.emplace_back(neuron_idx); + new_layer.emplace_back(last_neuron_idx); /* Connect hidden neuron to the previous layer */ for(auto prev_n : previous_layer) { if(new_subnet) { - subnet_connection_idxs[elements_list.at(i)].emplace_back(this->add_connection_simple(prev_n, - neuron_idx, - SIMPLE_CONNECTION_TYPE::NEXT_WEIGHT)); - + this->add_connection_simple(prev_n, + last_neuron_idx, + SIMPLE_CONNECTION_TYPE::NEXT_WEIGHT); + // std::cout << " new subnet, connection weight bias: " << last_connection_weight_idx << std::endl; + last_connection_weight_idx++; } else { this->add_connection_simple(prev_n, - neuron_idx, - SIMPLE_CONNECTION_TYPE::EXISTING_WEIGHT, subnet_connection_idxs[elements_list.at(i)].at(0)+local_connection_idx); + last_neuron_idx, + SIMPLE_CONNECTION_TYPE::EXISTING_WEIGHT, local_connection_idx); + // std::cout << " old subnet, connection weight bias: " << local_connection_idx << std::endl; } local_connection_idx++; } @@ -148,23 +162,13 @@ lib4neuro::ACSFNeuralNetwork::ACSFNeuralNetwork(std::unordered_map<ELEMENT_SYMBO // } /* Create output neurons for sub-net */ - std::shared_ptr<NeuronLinear> sub_out_n = std::make_shared<NeuronLinear>(); - neuron_idx = this->add_neuron(sub_out_n, BIAS_TYPE::NO_BIAS); - subnet_outputs.emplace_back(neuron_idx); for(auto prev_n : previous_layer) { - this->add_connection_simple(prev_n, neuron_idx); + this->add_connection_constant(prev_n, outputs[ 0 ], 1.0); } + } - /* Specify network inputs */ + /* Specify network inputs and outputs */ this->specify_input_neurons(inputs); - - /* Create final output layer */ - std::shared_ptr<NeuronLinear> final_out_n = std::make_shared<NeuronLinear>(); - neuron_idx = this->add_neuron(final_out_n, BIAS_TYPE::NO_BIAS); - for(auto subnet_output : subnet_outputs) { - this->add_connection_constant(subnet_output, neuron_idx, 1); - } - std::vector<size_t> outputs = {neuron_idx}; this->specify_output_neurons(outputs); } diff --git a/src/examples/acsf2.cpp b/src/examples/acsf2.cpp index f896a108e8fa8212022e7c59e0ee4bb9b5a04e69..4782805279ce74fc2c8f8f02cb50f3459e400962 100644 --- a/src/examples/acsf2.cpp +++ b/src/examples/acsf2.cpp @@ -133,7 +133,7 @@ int main() { elements[l4n::ELEMENT_SYMBOL::He] = &helium; /* Read data */ - l4n::XYZReader reader("/home/martin/lib4neuro/data/HE21+T1.xyz"); + l4n::XYZReader reader("../../data/HE21+T1.xyz"); reader.read(); std::cout << "Finished reading data" << std::endl; @@ -142,10 +142,10 @@ int main() { /* Create a neural network */ std::unordered_map<l4n::ELEMENT_SYMBOL, std::vector<unsigned int>> n_hidden_neurons; - n_hidden_neurons[l4n::ELEMENT_SYMBOL::He] = {2}; + n_hidden_neurons[l4n::ELEMENT_SYMBOL::He] = {2, 1}; std::unordered_map<l4n::ELEMENT_SYMBOL, std::vector<l4n::NEURON_TYPE>> type_hidden_neurons; - type_hidden_neurons[l4n::ELEMENT_SYMBOL::He] = {l4n::NEURON_TYPE::LOGISTIC}; + type_hidden_neurons[l4n::ELEMENT_SYMBOL::He] = {l4n::NEURON_TYPE::LOGISTIC, l4n::NEURON_TYPE::LINEAR}; l4n::ACSFNeuralNetwork net(elements, *reader.get_element_list(), reader.contains_charge(), n_hidden_neurons, type_hidden_neurons); // l4n::NeuralNetwork net;