ANN实现


ANN核心数据结构:

typedef struct 
{
    
int input_n;                  /* number of input units */
    
int hidden_n;                 /* number of hidden units */
    
int output_n;                 /* number of output units */
    
double *input_units;          /* the input units */
    
double *hidden_units;         /* the hidden units */
    
double *output_units;         /* the output units */
    
double *hidden_delta;         /* storage for hidden unit error */
    
double *output_delta;         /* storage for output unit error */
    
double *target;               /* storage for target vector */
    
double **input_weights;       /* weights from input to hidden layer */
    
double **hidden_weights;      /* weights from hidden to output layer */
    
/*** The next two are for momentum ***/
    
double **input_prev_weights;  /* previous change on input to hidden wgt */
    
double **hidden_prev_weights; /* previous change on hidden to output wgt */
} BPNN;

整个神经网络可以分成三层:输入层,隐藏层,输出层,通过加权线性变换,层与层之间的传递,最终得到输入层的实数值。

BPNN *bpnn_internal_create(int n_in, int n_hidden,int n_out;)
{
//创建人工网络,参数分别指定输入层,隐藏层和输出层大小
    BPNN *newnet;
    newnet 
= (BPNN *) malloc (sizeof (BPNN));
    
if (newnet == NULL)
    {
        printf(
"BPNN_CREATE: Couldn't allocate neural network/n");
        
return (NULL);
    }
    newnet
->input_n = n_in;//输入层
    newnet->hidden_n = n_hidden;//隐藏层
    newnet->output_n = n_out;//输出层
    newnet->input_units = alloc_1d_dbl(n_in + 1);
    newnet
->hidden_units = alloc_1d_dbl(n_hidden + 1);
    newnet
->output_units = alloc_1d_dbl(n_out + 1);
    newnet
->hidden_delta = alloc_1d_dbl(n_hidden + 1);
    newnet
->output_delta = alloc_1d_dbl(n_out + 1);
    newnet
->target = alloc_1d_dbl(n_out + 1);//目标向量
    newnet->input_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1);//输入层到隐藏层的权值
    newnet->hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1);//隐藏层到输出层的权值
    newnet->input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1);
    newnet
->hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1);
    
return (newnet);
}

下面代码段是ANN运行的核心部分:

if (train_n > 0)
{
//提供了训练集
    printf("Creating new network '%s'/n", netname);
    iimg 
= trainlist->list[0];//指向训练集第一张图片
    imgsize = ROWS(iimg) * COLS(iimg);
    
/* bthom ===========================
    make a net with:
    imgsize inputs, 4 hiden units, and 1 output unit
    
*/
    
//输入层为图片大小,隐藏层为,输出层为
    net = bpnn_create(imgsize, 41);
}

// 训练
/*
************* Train it *****************************/
for (epoch = 1; epoch <= epochs; epoch++
{
    printf(
"%d ", epoch);  fflush(stdout);
    sumerr 
= 0.0;
    
for (i = 0; i < train_n; i++
    {
        
/** Set up input units on net with image i **/
        
//为图像i在网络上建立输入单元
        load_input_with_image(trainlist->list[i], net);
        
/** Set up target vector for image i **/
        
//为图像i建立目标向量
        load_target(trainlist->list[i], net);
        
/** Run backprop, learning rate 0.3, momentum 0.3 **/
        
//学习速率.3,冲量.3
        bpnn_train(net, 0.30.3&out_err, &hid_err);
        sumerr 
+= (out_err + hid_err);
    }
    进行性能评估:
        
for (i = 0; i < n; i++
        {
            
/*** Load the image into the input layer. **/
            load_input_with_image(il
->list[i], net);//加载图片到输入层中
            /*** Run the net on this input. **/
            bpnn_feedforward(net);
//在当前输入上运行神经网络
            /*** Set up the target vector for this image. **/
            load_target(il
->list[i], net);//为此图片建立目标向量
            /*** See if it got it right. ***/
            
if (evaluate_performance(net, &val, 0)) 
            {
//判断是否正确识别,
                correct++;
            }
            
else if (list_errors) 
            {
                printf(
"%s - outputs ", NAME(il->list[i]));
                
for (j = 1; j <= net->output_n; j++
                {
                    printf(
"%.3f ", net->output_units[j]);
                }
                putchar(
'/n');
            }
            err 
+= val;
        }
        err 
= err / (double) n;
        
if (!list_errors)
            
/* bthom==================================
            this line prints part of the ouput line
            discussed in section 3.1.2 of homework
            
*/
            printf(
"%g %g ", ((double) correct / (double) n) * 100.0, err);

用到的性能评估函数:

evaluate_performance(BPNN *net,double *err)

{//性能评估

      doubledelta;

      delta =net->target[1] -net->output_units[1];

      *err =(0.5 *delta * delta);

      /*** If thetarget unit is on... ***/

      if (net->target[1]> 0.5)

      {

           /*** If theoutput unit is on, then we correctly recognized me! ***/

           if (net->output_units[1]> 0.5)

           {

                 return(1);

           }

           else

           {

                 return(0);

           }

           /*** Else,the target unit is off... ***/

      }

      else

      {

           /*** If theoutput unit is on, then we mistakenly thought it was me ***/

           if (net->output_units[1]> 0.5)

           {

                 return(0);

                 /***else, we correctly realized that it wasn't me ***/

           }

           else

           {

                 return(1);

           }

      }

}

辅助处理函数区:

load_input_with_image(IMAGE *img, BPNN *net)
{
//输入图像
    double *units;
    
int nr, nc, imgsize, i, j, k;

    nr 
= ROWS(img);// 行大小
    nc = COLS(img);//列大小
    imgsize = nr * nc;;
    
if (imgsize != net->input_n) 
    {
//确保输入单元数目设置为图片大小
        printf("LOAD_INPUT_WITH_IMAGE: This image has %d pixels,/n", imgsize);
        printf(
"   but your net has %d input units.  I give up./n", net->input_n);
        exit (
-1);
    }
    
//取图片的每个像素为输入单元
    units = net->input_units;
    k 
= 1;
    
for (i = 0; i < nr; i++
    {
        
for (j = 0; j < nc; j++)
        {
            units[k] 
= ((double) img_getpixel(img, i, j)) / 255.0;
            k
++;
        }
    }
}

load_target(IMAGE 
*img, BPNN *net)
{
//加载目标值
    int scale;
    
char userid[40], head[40], expression[40], eyes[40], photo[40];
    userid[
0= head[0= expression[0= eyes[0= photo[0= '/0';
    
/*** scan in the image features ***/
    sscanf(NAME(img), 
"%[^_]_%[^_]_%[^_]_%[^_]_%d.%[^_]",
    userid, head, expression, eyes, 
&scale, photo);
    
if (!strcmp(userid, "glickman")) 
    {
        net
->target[1= TARGET_HIGH;  /* it's me, set target to HIGH */
    } 
    
else 
    {
        net
->target[1= TARGET_LOW;   /* not me, set it to LOW */
    }
}

void bpnn_train(BPNN *net, double eta, momentum *eo, momentum *eh)
{
//人工神经网络训练
    int in, hid, out;
    
double out_err, hid_err;
    
in = net->input_n;
    hid 
= net->hidden_n;
    
out = net->output_n;
    
/*** Feed forward input activations. ***/
    bpnn_layerforward(net
->input_units, net->hidden_units,
    net
->input_weights, in, hid);
    bpnn_layerforward(net
->hidden_units, net->output_units,
    net
->hidden_weights, hid, out);
    
/*** Compute error on output and hidden units. ***/
    bpnn_output_error(net
->output_delta, net->target, net->output_units,out&out_err);
    bpnn_hidden_error(net
->hidden_delta, hid, net->output_delta, out,net->hidden_weights, net->hidden_units, &hid_err);
    
*eo = out_err;
    
*eh = hid_err;
    
/*** Adjust input and hidden weights. ***/
    bpnn_adjust_weights(net
->output_delta, out, net->hidden_units, hid,net->hidden_weights, net->hidden_prev_weights, eta, momentum);
    bpnn_adjust_weights(net
->hidden_delta, hid, net->input_units, in,net->input_weights, net->input_prev_weights, eta, momentum);
}

void bpnn_feedforward(BPNN *net)
{
//前向反馈
    int in, hid, out;
    
in = net->input_n;//输入层大小
    hid = net->hidden_n;//隐藏层大小
    out = net->output_n;//输出层大小
    /*** Feed forward input activations. ***/
    bpnn_layerforward(net
->input_units, net->hidden_units,net->input_weights, in, hid);
    bpnn_layerforward(net
->hidden_units, net->output_units,net->hidden_weights, hid, out);
}

void bpnn_adjust_weights(double *delta, double *ly,double **w, double **oldw, double eta, double momentum)
{
//调整权值
    double new_dw;
    
int k, j;
    ly[
0= 1.0;
    
for (j = 1; j <= ndelta; j++
    {
        
for (k = 0; k <= nly; k++
        {
            new_dw 
= ((eta * delta[j] * ly[k]) + (momentum * oldw[k][j]));
            w[k][j] 
+= new_dw;
            oldw[k][j] 
= new_dw;
        }
    }
}
void bpnn_layerforward(double *l1, double *l2, double **conn,int n1,int n2)
{
//层次前向输入
    double sum;
    
int j, k;
    
/*** Set up thresholding unit ***/
    l1[
0= 1.0;
    
//加权线性变换
    /*** For each unit in second layer ***/
    
for (j = 1; j <= n2; j++
    {
        
/*** Compute weighted sum of its inputs ***/
        sum 
= 0.0;
        
for (k = 0; k <= n1; k++)
        {
            sum 
+= conn[k][j] * l1[k];
        }
        l2[j] 
= squash(sum);
    }
}
原文地址:https://www.cnblogs.com/cl1024cl/p/6205275.html