• 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);
        }
    }
  • 相关阅读:
    牛客网Java刷题知识点之方法覆盖(方法重写)和方法重载的区别
    牛客网Java刷题知识点之自动拆装箱
    安装Phoenix时./sqlline.py执行报错File "./sqlline.py", line 27, in <module> import argparse ImportError: No module named argparse解决办法(图文详解)
    Apache-kylin-2.0.0-bin-hbase1x.tar.gz的下载与安装(图文详解)
    Apache Kylin的架构特性
    Apache Kylin Cube 的存储
    Apache Kylin Cube 的构建过程
    Apache Kylin的核心概念
    中央网络安全和信息化领导小组办公室
    中国智慧城市建设投资联盟
  • 原文地址:https://www.cnblogs.com/cl1024cl/p/6205275.html
Copyright © 2020-2023  润新知