Skip to content
Snippets Groups Projects
net_test_2.cpp 5.67 KiB
Newer Older
  • Learn to ignore specific revisions
  • Michal Kravcenko's avatar
    Michal Kravcenko committed
     * Example of a neural network with reused edge weights
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    // Created by Michal on 7/17/18.
    
        std::cout << "Running lib4neuro example   2: Basic use of the particle swarm method to train a network with five linear neurons and repeating edge weights" << std::endl;
        std::cout << "********************************************************************************************************************************************" <<std::endl;
        std::cout << "The code attempts to find an approximate solution to the system of equations below:" << std::endl;
        std::cout << " 0 * w1 + 1 * w2 = 0.50 + b1" << std::endl;
        std::cout << " 1 * w1 + 0.5*w2 = 0.75 + b1" << std::endl;
        std::cout << "(1.25 + b2) * w2 = 0.63 + b3" << std::endl;
        std::cout << "***********************************************************************************************************************" <<std::endl;
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        std::vector<std::pair<std::vector<double>, std::vector<double>>> data_vec;
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        inp = {0, 1, 0};
        out = {0.5, 0};
        data_vec.emplace_back(std::make_pair(inp, out));
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        inp = {1, 0.5, 0};
        out = {0.75, 0};
        data_vec.emplace_back(std::make_pair(inp, out));
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        inp = {0, 0, 1.25};
        out = {0, 0.63};
        data_vec.emplace_back(std::make_pair(inp, out));
    
        l4n::NeuronLinear *i1 = new l4n::NeuronLinear( );  //f(x) = x
        l4n::NeuronLinear *i2 = new l4n::NeuronLinear( );  //f(x) = x
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        double b = 1;//bias
    
        l4n::NeuronLinear *i3 = new l4n::NeuronLinear( );  //f(x) = x
    
        l4n::NeuronLinear *o1 = new l4n::NeuronLinear( );  //f(x) = x
        l4n::NeuronLinear *o2 = new l4n::NeuronLinear( );  //f(x) = x
    
        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);
    
        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!
    
        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);
    
        /* COMPLEX ERROR FUNCTION SPECIFICATION */
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
    //    double weights[2] = {-0.18012411, -0.17793740};
    //    double weights[2] = {1, 1};
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    //    printf("evaluation of error at point (%f, %f) => %f\n", weights[0], weights[1], mse.eval(weights));
    
        //must encapsulate each of the partial error functions
    
        std::vector<double> domain_bounds = {-10.0, 10.0, -10.0, 10.0,-10.0, 10.0, -10.0, 10.0,-10.0, 10.0, -10.0, 10.0,-10.0, 10.0, -10.0, 10.0,-10.0, 10.0, -10.0, 10.0,-10.0, 10.0, -10.0, 10.0,-10.0, 10.0, -10.0, 10.0};
        ParticleSwarm swarm_01(&mse, &domain_bounds);
    
        /* 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.9;
        swarm_01.optimize(gamma, epsilon, delta);
    
        std::vector<double> *parameters = swarm_01.get_solution();
        net.copy_parameter_space(parameters);
    
        printf("w1 = %10.7f\n", parameters->at( 0 ));
        printf("w2 = %10.7f\n", parameters->at( 1 ));
        printf("b1 = %10.7f\n", parameters->at( 2 ));
        printf("b2 = %10.7f\n", parameters->at( 3 ));
        printf("b3 = %10.7f\n", parameters->at( 4 ));
        std::cout << "***********************************************************************************************************************" <<std::endl;
    
        /* ERROR CALCULATION */
        double error = 0.0;
        inp = {0, 1, 0};
        net.eval_single( inp, out );
        error += (0.5 - out[0]) * (0.5 - out[0]) + (0.0 - out[1]) * (0.0 - out[1]);
        printf("x = (%4.2f, %4.2f, %4.2f), expected output: (%4.2f, %4.2f), real output: (%10.7f, %10.7f)\n", inp[0], inp[1], inp[2], 0.5, 0.0, out[0], out[1]);
    
        inp = {1, 0.5, 0};
        net.eval_single( inp, out );
        error += (0.75 - out[0]) * (0.75 - out[0]) + (0.0 - out[1]) * (0.0 - out[1]);
        printf("x = (%4.2f, %4.2f, %4.2f), expected output: (%4.2f, %4.2f), real output: (%10.7f, %10.7f)\n", inp[0], inp[1], inp[2], 0.75, 0.0, out[0], out[1]);
    
        inp = {0, 0, 1.25};
        net.eval_single( inp, out );
        error += (0.0 - out[0]) * (0.0 - out[0]) + (0.63 - out[1]) * (0.63 - out[1]);
        printf("x = (%4.2f, %4.2f, %4.2f), expected output: (%4.2f, %4.2f), real output: (%10.7f, %10.7f)\n", inp[0], inp[1], inp[2], 0.0, 0.63, out[0], out[1]);
    
        std::cout << "Run finished! Error of the network: " << error / 3.0 << std::endl;