Neuronová sieť

Programovacie jazyky, rady, poradňa...
Viper
Medium Expert
Medium Expert
Používateľov profilový obrázok
Príspevky: 137
Registrovaný: 14 mar 2012, 13:19

Neuronová sieť

Príspevok od používateľa Viper »

Ahojte,
začal som pracovať s neuronovymi sietami a vyskytol sa problem:
Moja app je okno, v ktorom behajú tanky, kt. zbierajú miny.
Neuronová sieť je veľmi jednoduchá vstupujú do nej 4 inputy: x a y najbližšej míny a tam kde sa tank pozerá to dostanem takto:

Kód: Vybrať všetko

    double lookAtX =((-sin(currentRotation  ) * (- speed)));
    double lookAtY =((cos(currentRotation) * (-speed)));
a dostanem 2 outputy: rýchlosť pravého a ľavého pásu tanku tak že

Kód: Vybrať všetko

 double cRotation = output[0] - output[1];
odpočítam rýchlosti.
a potom k aktuálnej rotácii pripočítam tu novú.
A novú pozíciu dostanem takto:

Kód: Vybrať všetko

      mItem->setX(mItem->x()+(-sin(currentRotation / 60 ) * (-speed)));
      mItem->setY(mItem->y()+(cos(currentRotation / 60) * (-speed)));
Vôbec neviem preco tam mám /60 ale ak to tam nemám tak sa tank inam pozerá a inam ide.

Program funguje ale tank stálle chodí do kruhu aj pri 100 generácii netočí sa na mieste ale robí veľke alebo mnesšie kruhy.
Ako vidim debug tak žiadny tank nemení znamienko rotácie buď ide stále do + až po 360 alebo ide stále do minusu až do -360 keď sa dostanú na +/- 360 tak ich hodím späť na 0.

Pls help
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8222
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Neuronová sieť

Príspevok od používateľa harrison314 »

Z toho opisu sa neda velmi pomoct.
a) mas tu neuronovu siet natrnovanu?
b) neuronove siete nemaju generacie, generacie maju evolucne algoritmy

Len mi to pride tak, ze toto neni uloha pre neuronovu siet.
Viper
Medium Expert
Medium Expert
Používateľov profilový obrázok
Príspevky: 137
Registrovaný: 14 mar 2012, 13:19

Re: Neuronová sieť

Príspevok od používateľa Viper »

ano mam geneticky algoritmus, ktory vytvori novu eru. A ta siet funguje tak ze 2000 ciklov tanky zbieraju a potom sa spusti geneticky algoritmus, ktory vytvori novu generaciu. Pomocou rulety vyberie 2 chromozomy, ktore nazbierali najviac a vytvori 2 nove z vybranych pomocou crossover(jednoducho par dlzok si vezme z 1. chromozomu a ostatok z 2. chromozomu)
toto je neuronova siet

Kód: Vybrať všetko

#include "neuralnetwork.h"

Neuron::Neuron(int NumberInputs) :mNumberInputs(NumberInputs + 1)
{
    for(int i = 0; i < NumberInputs+1; i++)
    {
        float randFloat = (-1 + (float)rand()/((float)RAND_MAX/(1-(-1)))) - (-1 + (float)rand()/((float)RAND_MAX/(1-(-1))));
        mWeights.push_back(randFloat);

    }
}


NeuronLayer::NeuronLayer(int NumberNeurons, int InputsPerNeuron) : mNumberNeurons(NumberNeurons)
{
    for(int i = 0; i < NumberNeurons; i++)
    {
        mNeurons.push_back(Neuron(InputsPerNeuron));
    }
}

NeuralNetwork::NeuralNetwork(QObject *parent) :
    QObject(parent),
    mNumberHiddenLayers(2),
    mNumberNeuronsPerLayer(6)
{
    createNetwork();
}

void NeuralNetwork::createNetwork()
{
    layers.push_back(NeuronLayer(mNumberNeuronsPerLayer, 4));
    for (int i = 0; i < mNumberHiddenLayers-1; ++i)
    {
        layers.push_back(NeuronLayer(mNumberNeuronsPerLayer, mNumberNeuronsPerLayer));
    }
    layers.push_back(NeuronLayer(2, mNumberNeuronsPerLayer));
}

vector<double> NeuralNetwork::Weights()
{
    vector<double> weights;
    for(int i = 0; i < mNumberHiddenLayers + 1; i++)
    {
        for (int j = 0; j < layers[i].mNumberNeurons; j++)
        {
            for (int k = 0; k < layers[i].mNeurons[j].mNumberInputs; ++k)
            {
                weights.push_back(layers[i].mNeurons[j].mWeights[k]);
            }
        }
    }
    return weights;
}

void NeuralNetwork::PutWeights(vector<double> weights)
{
    int currentWeight = 0;
    for(int i = 0; i < mNumberHiddenLayers + 1; i++)
    {
        for (int j = 0; j < layers[i].mNumberNeurons; j++)
        {
            for (int k = 0; k < layers[i].mNeurons[j].mNumberInputs; ++k)
            {
                layers[i].mNeurons[j].mWeights[k] = weights[currentWeight++];
            }
        }
    }
}

int NeuralNetwork::GetNumberWeights()
{
    int weights = 0;
    for(int i = 0; i < mNumberHiddenLayers + 1; i++)
    {
        for (int j = 0; j < layers[i].mNumberNeurons; j++)
        {
            for (int k = 0; k < layers[i].mNeurons[j].mNumberInputs; ++k)
            {
                weights++;
            }
        }
    }
    return weights;
}

vector<double> NeuralNetwork::update(vector<double> inputs)
{
    vector<double> output;
    int cWeight = 0;
    for(int i = 0; i < mNumberHiddenLayers + 1; i++)
    {
        if(i > 0)
        {
            inputs = output;
        }
        output.clear();
        cWeight = 0;
        for (int j = 0; j < layers[i].mNumberNeurons; j++)
        {
            double netinput = 0;
            int numInputs = layers[i].mNeurons[j].mNumberInputs;
            for (int k = 0; k < numInputs; k++)
            {
                netinput += layers[i].mNeurons[j].mWeights[k] * inputs[cWeight++];
            }
            netinput += layers[i].mNeurons[j].mWeights[numInputs-1] * -1;
            output.push_back(Sigmoid(netinput,1));
            cWeight = 0;
        }
    }
    return output;
}

double NeuralNetwork::Sigmoid(double netinput, double response)
{
    return (1 / (1 + exp(-netinput/response)));
}

a toto geneticky algoritmus

Kód: Vybrať všetko

#include "genetic.h"

Genetic::Genetic(int popSize, int weights, QObject *parent) :
    QObject(parent),
    mPopSize(popSize),
    chromoLenght(weights),
    mutationRate(0.1),
    CrossoverRate(0.7)
{
    for(int i = 0; i < popSize; i++)
    {
        population.push_back(Genome());
        for (int j = 0; j < chromoLenght; j++)
        {
            float randFloat = (-1 + (float)rand()/((float)RAND_MAX/(1-(-1)))) - (-1 + (float)rand()/((float)RAND_MAX/(1-(-1))));
            population[i].mWeights.push_back(randFloat);
        }
    }
}

vector<Genome> Genetic::Epoch(vector<Genome> &oldPop)
{
    population = oldPop;
    Reset();
    sort(population.begin(), population.end());
    vector<Genome> newPop;
    GrabNBest(4, newPop);

    while (newPop.size() < mPopSize)
    {
        Genome mum = getChromoRoullete();
        Genome dad = getChromoRoullete();
        vector<double> baby1 ,baby2;
        crossover(dad.mWeights, mum.mWeights, baby1, baby2);

        Mutate(baby1);
        Mutate(baby2);

        newPop.push_back(Genome(baby1, 0));
        newPop.push_back(Genome(baby2, 0));
    }
    population = newPop;
    return population;
}

void Genetic::Reset()
{
    totalFitenss = 0;
}

void Genetic::crossover(vector<double> &dad, vector<double> &mum, vector<double> &baby1, vector<double> &baby2)
{
      float randFloat = -1 + (float)rand()/((float)RAND_MAX/(1-(-1)));
      if(randFloat > CrossoverRate || mum == dad)
      {
          baby1 = mum;
          baby2 = dad;
          return;
      }

      int cp = rand() % (chromoLenght -1);
      for (int i = 0; i < cp; i++)
      {
          baby1.push_back(mum[i]);
          baby2.push_back(dad[i]);
      }
      for(int i = cp; i < mum.size(); i++)
      {
          baby1.push_back(dad[i]);
          baby2.push_back(mum[i]);
      }
      return;
}

void Genetic::Mutate(vector<double> &chromo)
{
    for (int i = 0; i < chromo.size(); i++)
    {
        float randFloat = -1 + (float)rand()/((float)RAND_MAX/(1-(-1)));
        if(randFloat < mutationRate)
        {
                    float randomClamped = (-1 + (float)rand()/((float)RAND_MAX/(1-(-1)))) - (-1 + (float)rand()/((float)RAND_MAX/(1-(-1))));
                    chromo[i] += randomClamped * 0.3;
        }
    }
}

Genome Genetic::getChromoRoullete()
{
     float randFloat = -1 + (float)rand()/((float)RAND_MAX/(1-(-1)));
     double slice = (double)(randFloat * totalFitenss);
     Genome Chosen;

     double FitnessSoFar = 0;
     for (int i = 0; i < mPopSize; i++)
     {
         FitnessSoFar += population[i].mFitness;
         if(FitnessSoFar >= slice)
         {
             Chosen = population[i];
             break;
         }
     }
     return Chosen;
}

void Genetic::GrabNBest(int numBest, vector<Genome> pop)
{
    // 4 and 1 copy
    while(numBest--)
    {
        for (int i = 0; i < 1; ++i)
        {
            pop.push_back(population[(mPopSize - 1) - numBest]);
        }
    }

}
 
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8222
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Neuronová sieť

Príspevok od používateľa harrison314 »

Viper napísal:ano mam geneticky algoritmus, ktory vytvori novu eru. A ta siet funguje tak ze 2000 ciklov tanky zbieraju a potom sa spusti geneticky algoritmus, ktory vytvori novu generaciu. Pomocou rulety vyberie 2 chromozomy, ktore nazbierali najviac a vytvori 2 nove z vybranych pomocou crossover(jednoducho par dlzok si vezme z 1. chromozomu a ostatok z 2. chromozomu)
toto je neuronova siet
Nechapem co chces dosihanut, ani preco to robis tak divne.
Viper
Medium Expert
Medium Expert
Používateľov profilový obrázok
Príspevky: 137
Registrovaný: 14 mar 2012, 13:19

Re: Neuronová sieť

Príspevok od používateľa Viper »

chcem dosiahnut to aby ked tank bude vstrede obrazovky a jedna mina bude trochu nad nim ale viac v pravo a druha bude v lavo uplne hore tak najskor zatoci za tov napravo a potom sa otoci a pojde za tou 2. Len chcem aby NN ovladala tank.
A robim to preto lebo som cital tutorial o NN a bol tam uvedeny takyto program tak som si to chcel skusit.
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8222
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Neuronová sieť

Príspevok od používateľa harrison314 »

Tak vyhod evolucne algoritmy.
natrenuj neuronvu siet (nie 3 prikladmy)

Imho: Evolucny algoritmus, ti dokaze to aby tank zozral vsetky miny v co najkratcom case.
Viper
Medium Expert
Medium Expert
Používateľov profilový obrázok
Príspevky: 137
Registrovaný: 14 mar 2012, 13:19

Re: Neuronová sieť

Príspevok od používateľa Viper »

ok skúsim dik ale aj tak by ma zaujímalo ako je možne, ze jemu to tam funguje parádne.
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8222
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Neuronová sieť

Príspevok od používateľa harrison314 »

Tam toho moze byt vela, nevhodne trenovanie, zle nastavene parametre,...
Viper
Medium Expert
Medium Expert
Používateľov profilový obrázok
Príspevky: 137
Registrovaný: 14 mar 2012, 13:19

Re: Neuronová sieť

Príspevok od používateľa Viper »

Je to nejaká dobrá duša, kt. by mi pozrela kód mám problém sieť funguje ale problém bude v trenovani jednoducho vzdy dostanem rovnaký output

Kód: Vybrať všetko

#include "neuralnetwork.h"
#include <QDebug>

NeuralNetwork::NeuralNetwork(vector<int> &topology, QObject *parent) :
    QObject(parent)
{

    int numLayer = topology.size();
    for(int i = 0; i < numLayer; ++i)
    {
        m_Layers.push_back(Layer());
        int numOutputs = (i == topology.size() - 1 ? 0 : topology[i + 1]);

        for(int numNeuron = 0; numNeuron <= topology[i]; ++numNeuron)
        {
            m_Layers.back().push_back(Neuron(numOutputs, numNeuron));
            qDebug() << "New neuron";
        }
        m_Layers.back().back().setOutput(1.0);
    }
    vector<double> inputs;
    vector<double> outputs;
    vector<double> targets;

    for(int i = 0; i < 4000000; ++i)
    {
        inputs.clear();
        outputs.clear();
        targets.clear();
        int a = rand() % 2;
        int b = rand() % 2;
        int target = a^b;
        targets.push_back(target);
        inputs.push_back(a);
        inputs.push_back(b);
        outputs = update(inputs);
        qDebug() << "inputs: " << a << " " << b;
        qDebug() << "output " << outputs[0];
        qDebug() << "target:" << target;
        backProp(targets);
        qDebug() << "error: " << m_error;
    }

}

vector<double> NeuralNetwork::update(vector<double> &inputs)
{
    m_Layers[0][0].setOutput(inputs[0]);
    m_Layers[0][1].setOutput(inputs[1]);
    for(int layerNum = 1; layerNum < m_Layers.size(); ++layerNum)
    {
        Layer &prevLayer = m_Layers[layerNum-1];
        for (int neuronNum = 0; neuronNum < m_Layers[layerNum].size() - 1; ++neuronNum)
        {
            m_Layers[layerNum][neuronNum].update(prevLayer);
        }
    }

    vector<double> output;// = m_Layers.back()[0].Output();
    for(int i = 0; i < m_Layers.back().size() - 1; i++)
    {
        output.push_back(m_Layers.back()[i].Output());
    }
    return output;
}

void NeuralNetwork::backProp(vector<double> &target)
{
    Layer &outputLayer = m_Layers.back();
    m_error = 0.0;

    for (int n = 0; n < outputLayer.size() - 1; ++n) {
        double delta = target[n] - outputLayer[n].Output();
        m_error += delta * delta;
    }
    m_error /= outputLayer.size() - 1;
    m_error = sqrt(m_error); // RMS

    m_recentAverageError =
            (m_recentAverageError * 100 + m_error)
            / (100 + 1.0);

    for (int n = 0; n < outputLayer.size() - 1; ++n) {
        outputLayer[n].callOutputGradients(target[n]);
    }


    for (int layerNum = m_Layers.size() - 2; layerNum > 0; --layerNum) {
        Layer &hiddenLayer = m_Layers[layerNum];
        Layer &nextLayer = m_Layers[layerNum + 1];

        for (int n = 0; n < hiddenLayer.size(); ++n) {
            hiddenLayer[n].calcHiddenGradients(nextLayer);
        }
    }

    for (int layerNum = m_Layers.size() - 1; layerNum > 0; --layerNum) {
        Layer &layer = m_Layers[layerNum];
        Layer &prevLayer = m_Layers[layerNum - 1];

        for (int n = 0; n < layer.size() - 1; ++n) {
            layer[n].updateInputWeights(prevLayer);
        }
    }



}

Kód: Vybrať všetko

#include "neuron.h"
#include <QDebug>

Neuron::Neuron(int numOutputs, int index) :
    m_index(index)
{
    m_Output = 0;
    m_gradient = 0.0;
    for(int c = 0; c < numOutputs; ++c)
    {
        m_Weight.push_back(Connection());
        m_Weight.back().weight = randomWeight();
    }

}

vector<Connection> Neuron::Weight()
{
    return m_Weight;
}

void Neuron::update(Layer &prevLayer)
{
    double sum = 0.0;
    for(unsigned int neuron = 0; neuron < prevLayer.size(); ++neuron)
    {
        vector<Connection> weights = prevLayer[neuron].Weight();
        sum += prevLayer[neuron].Output() *
                weights[m_index].weight;
    }

    m_Output = transferFunction(sum);
}

double Neuron::Output()
{
    return m_Output;
}

void Neuron::setOutput(double output)
{
    m_Output = output;
}

double Neuron::randomWeight()
{
    return rand() / double(RAND_MAX);
}

void Neuron::callOutputGradients(double target)
{
    double delta = target - m_Output;
    m_gradient = delta * transferFunctionDerivative(m_Output);
}

void Neuron::calcHiddenGradients(Layer &nextLayer)
{
    double dow = sumDOW(nextLayer);
    m_gradient = dow * transferFunctionDerivative(m_Output);
}

void Neuron::updateInputWeights(Layer &prevLayer)
{
    for(int i = 0; i < prevLayer.size(); i++)
    {
        Neuron &neuron = prevLayer[i];
        double oldDeltaWeight = neuron.Weight()[m_index].deltaWeight;
        double newDeltaWeight = (
                    ( 0.15*
                    neuron.Output()*
                    m_gradient) +
                    (0.5 *
                    oldDeltaWeight)
                    );

        vector<Connection> weights = neuron.Weight();
        weights[m_index].deltaWeight = newDeltaWeight;
        weights[m_index].weight += newDeltaWeight;

    }
}

double Neuron::transferFunction(double x)
{
    return tanh(x);
}

double Neuron::transferFunctionDerivative(double x)
{
    return 1.0 - x * x;
}

double Neuron::sumDOW(Layer &nextLayer)
{
    double sum = 0.0;
    for(int i = 0; i < nextLayer.size() -1; ++i)
    {
        sum += m_Weight[i].weight * nextLayer[i].m_gradient;
    }
    return sum;
}
Dik
Napísať odpoveď