У меня есть проблема, которую мне нужно решить. Мне нужно реализовать два метода, прямое и обратное распространение в c ++ для нейронной сети, которая распознает объекты на изображениях. Весь проект находится в трех файлах: ns_test. cpp, backprop.h и backprop. cpp. Я новичок в нейронной сети, и я действительно не знаю, с чего начать. Функция активации, которую мне нужно использовать, это сигмовидная функция.
ns_test. cpp:
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include "backprop.h"
void train(NN* nn)
{
int n = 1000;
double ** trainingSet = new double * [n];
for ( int i = 0; i < n; i++ ) {
trainingSet[i] = new double[nn->n[0] + nn->n[nn->l - 1]];
bool classA = i % 2;
for ( int j = 0; j < nn->n[0]; j++ ) {
if ( classA ) {
trainingSet[i][j] = 0.1 * ( double )rand() / ( RAND_MAX ) + 0.6;
} else {
trainingSet[i][j] = 0.1 * ( double )rand() / ( RAND_MAX ) + 0.2;
}
}
trainingSet[i][nn->n[0]] = ( classA )? 1.0 : 0.0;
trainingSet[i][nn->n[0] + 1] = ( classA )? 0.0 : 1.0;
}
double error = 1.0;
int i = 0;
while(error > 0.001)
{
setInput( nn, trainingSet[i%n] );
feedforward( nn );
error = backpropagation( nn, &trainingSet[i%n][nn->n[0]] );
i++;
printf( "\rerr=%0.3f", error );
}
printf( " (%d iterations)\n", i );
for ( int i = 0; i < n; i++ ) {
delete [] trainingSet[i];
}
delete [] trainingSet;
}
void test(NN* nn, int num_samples = 10)
{
double* in = new double[nn->n[0]];
int num_err = 0;
for(int n = 0; n < num_samples; n++)
{
bool classA = rand() % 2;
for ( int j = 0; j < nn->n[0]; j++ )
{
if ( classA )
{
in[j] = 0.1 * ( double )rand() / ( RAND_MAX ) + 0.6;
} else
{
in[j] = 0.1 * ( double )rand() / ( RAND_MAX ) + 0.2;
}
}
printf("predicted: %d\n", !classA);
setInput( nn, in, true );
feedforward( nn );
int output = getOutput( nn, true );
if(output == classA) num_err++;
printf( "\n" );
}
double err = (double)num_err / num_samples;
printf("test error: %.2f\n", err);
}
int main(int argc, char** argv)
{
NN * nn = createNN(2, 4, 2);
train(nn);
getchar();
test(nn, 100);
getchar();
releaseNN( nn );
return 0;
}
backprop.h:
#pragma once
struct NN {
int * n; // numbers of neurons
int l; // numbers of layers
double *** w; // weights
double * in; // input vector
double * out; // output vector
double ** y; // output vector of layers
double ** d; // neuron errors
};
NN * createNN( int n, int h, int o );
void releaseNN( NN *& nn );
void feedforward( NN * nn );
double backpropagation( NN * nn, double * t );
void setInput( NN * nn, double * in, bool verbose = false );
int getOutput( NN * nn, bool verbose = false );
backprop. cpp:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <vector>
#include "backprop.h"
#define LAMBDA 1.0
#define ETA 0.1
#define SQR( x ) ( ( x ) * ( x ) )
void randomize( double * p, int n )
{
for ( int i = 0; i < n; i++ ) {
p[i] = ( double )rand() / ( RAND_MAX );
}
}
NN * createNN( int n, int h, int o )
{
srand(time(NULL));
NN * nn = new NN;
nn->n = new int[3];
nn->n[0] = n;
nn->n[1] = h;
nn->n[2] = o;
nn->l = 3;
nn->w = new double ** [nn->l - 1];
for ( int k = 0; k < nn->l - 1; k++ )
{
nn->w[k] = new double * [nn->n[k + 1]];
for ( int j = 0; j < nn->n[k + 1]; j++ )
{
nn->w[k][j] = new double[nn->n[k]];
randomize( nn->w[k][j], nn->n[k]);
// BIAS
//nn->w[k][j] = new double[nn->n[k] + 1];
//randomize( nn->w[k][j], nn->n[k] + 1 );
}
}
nn->y = new double * [nn->l];
for ( int k = 0; k < nn->l; k++ ) {
nn->y[k] = new double[nn->n[k]];
memset( nn->y[k], 0, sizeof( double ) * nn->n[k] );
}
nn->in = nn->y[0];
nn->out = nn->y[nn->l - 1];
nn->d = new double * [nn->l];
for ( int k = 0; k < nn->l; k++ ) {
nn->d[k] = new double[nn->n[k]];
memset( nn->d[k], 0, sizeof( double ) * nn->n[k] );
}
return nn;
}
void releaseNN( NN *& nn )
{
for ( int k = 0; k < nn->l - 1; k++ ) {
for ( int j = 0; j < nn->n[k + 1]; j++ ) {
delete [] nn->w[k][j];
}
delete [] nn->w[k];
}
delete [] nn->w;
for ( int k = 0; k < nn->l; k++ ) {
delete [] nn->y[k];
}
delete [] nn->y;
for ( int k = 0; k < nn->l; k++ ) {
delete [] nn->d[k];
}
delete [] nn->d;
delete [] nn->n;
delete nn;
nn = NULL;
}
void feedforward( NN * nn )
{
//TODO
}
double backpropagation( NN * nn, double * t )
{
double error = 0.0;
//TODO
return error;
}
void setInput( NN * nn, double * in, bool verbose )
{
memcpy( nn->in, in, sizeof( double ) * nn->n[0] );
if ( verbose ) {
printf( "input=(" );
for ( int i = 0; i < nn->n[0]; i++ ) {
printf( "%0.3f", nn->in[i] );
if ( i < nn->n[0] - 1 ) {
printf( ", " );
}
}
printf( ")\n" );
}
}
int getOutput( NN * nn, bool verbose )
{
double max = 0.0;
int max_i = 0;
if(verbose) printf( " output=" );
for ( int i = 0; i < nn->n[nn->l - 1]; i++ )
{
if(verbose) printf( "%0.3f ", nn->out[i] );
if(nn->out[i] > max) {
max = nn->out[i];
max_i = i;
}
}
if(verbose) printf( " -> %d\n" , max_i);
if(nn->out[0] > nn->out[1] && nn->out[0] - nn->out[1] < 0.1) return 2;
return max_i;
}