Skip to content
Snippets Groups Projects
net_test_3.cpp 6.57 KiB
Newer Older
  • Learn to ignore specific revisions
  • Michal Kravcenko's avatar
    Michal Kravcenko committed
    /**
     * Example of a set of neural networks sharing some edge weights
    
     * The system of equations associated with the net in this example is not regular
     * minimizes the function: [(2y+0.5)^2 + (2x+y+0.25)^2] / 2 + [(4.5x + 0.37)^2] / 1
    
     * minimum [0.010024714] at (x, y) = (-333/4370, -9593/43700) = (-0.076201373, -0.219519451)
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
    //
    // Created by martin on 7/16/18.
    //
    
    #include <vector>
    
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
    
    David Vojtek's avatar
    David Vojtek committed
    void optimize_via_particle_swarm( l4n::NeuralNetwork &net, l4n::ErrorFunction &ef ){
    
        /* TRAINING METHOD SETUP */
        std::vector<double> domain_bounds(2 * (net.get_n_weights() + net.get_n_biases()));
    
        for(size_t i = 0; i < domain_bounds.size() / 2; ++i){
            domain_bounds[2 * i] = -10;
            domain_bounds[2 * i + 1] = 10;
        }
    
        double c1 = 1.7;
        double c2 = 1.7;
        double w = 0.7;
        size_t n_particles = 50;
        size_t iter_max = 1000;
    
        /* if the maximal velocity from the previous step is less than 'gamma' times the current maximal velocity, then one
         * terminating criterion is met */
        double gamma = 0.5;
    
        /* if 'delta' times 'n' particles are in the centroid neighborhood given by the radius 'epsilon', then the second
         * terminating criterion is met ('n' is the total number of particles) */
        double epsilon = 0.02;
        double delta = 0.7;
    
        l4n::ParticleSwarm swarm_01(
                &domain_bounds,
                c1,
                c2,
                w,
                gamma,
                epsilon,
                delta,
                n_particles,
                iter_max
        );
        swarm_01.optimize( ef );
    
        std::vector<double> *parameters = swarm_01.get_parameters();
        net.copy_parameter_space(parameters);
    
        std::cout << "Run finished! Error of the network[Particle swarm]: " << ef.eval( nullptr ) << std::endl;
        std::cout << "***********************************************************************************************************************" <<std::endl;
    }
    
    void optimize_via_gradient_descent( l4n::NeuralNetwork &net, l4n::ErrorFunction &ef ){
    
        l4n::GradientDescent gd( 1e-6, 1000 );
    
        gd.optimize( ef );
    
        std::vector<double> *parameters = gd.get_parameters();
        net.copy_parameter_space(parameters);
    
        /* ERROR CALCULATION */
        std::cout << "Run finished! Error of the network[Gradient descent]: " << ef.eval( nullptr )<< std::endl;
        std::cout << "***********************************************************************************************************************" <<std::endl;
    }
    
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    int main() {
    
        std::cout << "Running lib4neuro example   3: Use of the particle swarm method to train a set of networks sharing some edge weights" << std::endl;
        std::cout << "********************************************************************************************************************" <<std::endl;
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* TRAIN DATA DEFINITION */
        std::vector<std::pair<std::vector<double>, std::vector<double>>> data_vec_01, data_vec_02;
        std::vector<double> inp, out;
    
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        data_vec_01.emplace_back(std::make_pair(inp, out));
    
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        data_vec_01.emplace_back(std::make_pair(inp, out));
    
    
    David Vojtek's avatar
    David Vojtek committed
        l4n::DataSet ds_01(&data_vec_01);
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
    
        inp = {1.25};
        out = {0.63};
        data_vec_02.emplace_back(std::make_pair(inp, out));
    
    David Vojtek's avatar
    David Vojtek committed
        l4n::DataSet ds_02(&data_vec_02);
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* NETWORK DEFINITION */
    
    David Vojtek's avatar
    David Vojtek committed
        l4n::NeuralNetwork net;
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* Input neurons */
    
    David Vojtek's avatar
    David Vojtek committed
        l4n::NeuronLinear *i1 = new l4n::NeuronLinear();  //f(x) = x
        l4n::NeuronLinear *i2 = new l4n::NeuronLinear();  //f(x) = x
    
    David Vojtek's avatar
    David Vojtek committed
        l4n::NeuronLinear *i3 = new l4n::NeuronLinear( ); //f(x) = x
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* Output neurons */
    
    David Vojtek's avatar
    David Vojtek committed
        l4n::NeuronLinear *o1 = new l4n::NeuronLinear( );  //f(x) = x
        l4n::NeuronLinear *o2 = new l4n::NeuronLinear( );  //f(x) = x
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
    
    
        /* Adding neurons to the nets */
    
    David Vojtek's avatar
    David Vojtek committed
        size_t idx1 = net.add_neuron(i1, l4n::BIAS_TYPE::NO_BIAS);
        size_t idx2 = net.add_neuron(i2, l4n::BIAS_TYPE::NO_BIAS);
        size_t idx3 = net.add_neuron(o1, l4n::BIAS_TYPE::NEXT_BIAS);
        size_t idx4 = net.add_neuron(i3, l4n::BIAS_TYPE::NEXT_BIAS);
        size_t idx5 = net.add_neuron(o2, l4n::BIAS_TYPE::NEXT_BIAS);
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        /* Adding connections */
    
    David Vojtek's avatar
    David Vojtek committed
        net.add_connection_simple(idx1, idx3, l4n::SIMPLE_CONNECTION_TYPE::NEXT_WEIGHT); // weight index 0
        net.add_connection_simple(idx2, idx3, l4n::SIMPLE_CONNECTION_TYPE::NEXT_WEIGHT); // weight index 1
        net.add_connection_simple(idx4, idx5, l4n::SIMPLE_CONNECTION_TYPE::EXISTING_WEIGHT, 0); // AGAIN weight index 0 - same weight!
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        net.randomize_weights();
    
        /* specification of the input/output neurons */
        std::vector<size_t> net_input_neurons_indices(3);
        std::vector<size_t> net_output_neurons_indices(2);
        net_input_neurons_indices[0] = idx1;
        net_input_neurons_indices[1] = idx2;
        net_input_neurons_indices[2] = idx4;
    
        net_output_neurons_indices[0] = idx3;
        net_output_neurons_indices[1] = idx5;
    
        net.specify_input_neurons(net_input_neurons_indices);
        net.specify_output_neurons(net_output_neurons_indices);
    
    
        /* CONSTRUCTION OF SUBNETWORKS */
    
        //TODO subnetworks retain the number of weights, could be optimized to include only the used weights
    
    David Vojtek's avatar
    David Vojtek committed
        //TODO this example is not working properly, subnet method is not implemented
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        std::vector<size_t> subnet_01_input_neurons, subnet_01_output_neurons;
        std::vector<size_t> subnet_02_input_neurons, subnet_02_output_neurons;
    
        subnet_01_input_neurons.push_back(idx1);
        subnet_01_input_neurons.push_back(idx2);
        subnet_01_output_neurons.push_back(idx3);
    
    David Vojtek's avatar
    David Vojtek committed
        l4n::NeuralNetwork *subnet_01 = net.get_subnet( subnet_01_input_neurons, subnet_01_output_neurons );
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        subnet_02_input_neurons.push_back(idx4);
        subnet_02_output_neurons.push_back(idx5);
    
    David Vojtek's avatar
    David Vojtek committed
        l4n::NeuralNetwork *subnet_02 = net.get_subnet( subnet_02_input_neurons, subnet_02_output_neurons );
    
        if(subnet_01 && subnet_02){
            /* COMPLEX ERROR FUNCTION SPECIFICATION */
    
    David Vojtek's avatar
    David Vojtek committed
            l4n::MSE mse_01(subnet_01, &ds_01);
            l4n::MSE mse_02(subnet_02, &ds_02);
    
    David Vojtek's avatar
    David Vojtek committed
            l4n::ErrorSum mse_sum;
    
            mse_sum.add_error_function( &mse_01 );
            mse_sum.add_error_function( &mse_02 );
    
    David Vojtek's avatar
    David Vojtek committed
            /* PARTICLE SWARM LEARNING */
            net.randomize_weights();
            optimize_via_particle_swarm( net, mse_sum );
    
    David Vojtek's avatar
    David Vojtek committed
            /* GRADIENT DESCENT LEARNING */
            net.randomize_weights();
            optimize_via_gradient_descent( net, mse_sum );
    
        }
        else{
            std::cout << "We apologize, this example is unfinished as we are in the process of developing methods for efficient subnetwork definition" << std::endl;
        }
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        return 0;
    }