人工神经网络之反向传播算法

简介:
都说《机器学习》是学计算机的人必须要看的一本书,确实不是浪得虚名。看了一章人工神经网络(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, 4, 1);
}

// 训练
/************** 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.3, 0.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)

{//性能评估

      double delta;

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

      *err = (0.5 * delta * delta);

      /*** If the target unit is on... ***/

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

      {

           /*** If the output 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 the output 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);
    }
}
复制代码



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/10/18/1314181.html,如需转载请自行联系原作者
目录
相关文章
|
6月前
|
传感器 机器学习/深度学习 算法
【UASNs、AUV】无人机自主水下传感网络中遗传算法的路径规划问题研究(Matlab代码实现)
【UASNs、AUV】无人机自主水下传感网络中遗传算法的路径规划问题研究(Matlab代码实现)
177 0
|
5月前
|
存储 机器学习/深度学习 监控
网络管理监控软件的 C# 区间树性能阈值查询算法
针对网络管理监控软件的高效区间查询需求,本文提出基于区间树的优化方案。传统线性遍历效率低,10万条数据查询超800ms,难以满足实时性要求。区间树以平衡二叉搜索树结构,结合节点最大值剪枝策略,将查询复杂度从O(N)降至O(logN+K),显著提升性能。通过C#实现,支持按指标类型分组建树、增量插入与多维度联合查询,在10万记录下查询耗时仅约2.8ms,内存占用降低35%。测试表明,该方案有效解决高负载场景下的响应延迟问题,助力管理员快速定位异常设备,提升运维效率与系统稳定性。
286 4
|
5月前
|
机器学习/深度学习 算法
采用蚁群算法对BP神经网络进行优化
使用蚁群算法来优化BP神经网络的权重和偏置,克服传统BP算法容易陷入局部极小值、收敛速度慢、对初始权重敏感等问题。
447 5
|
6月前
|
存储 算法 安全
即时通讯安全篇(三):一文读懂常用加解密算法与网络通讯安全
作为开发者,也会经常遇到用户对数据安全的需求,当我们碰到了这些需求后如何解决,如何何种方式保证数据安全,哪种方式最有效,这些问题经常困惑着我们。52im社区本次着重整理了常见的通讯安全问题和加解密算法知识与即时通讯/IM开发同行们一起分享和学习。
457 9
|
6月前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
414 2
|
5月前
|
机器学习/深度学习 人工智能 算法
【基于TTNRBO优化DBN回归预测】基于瞬态三角牛顿-拉夫逊优化算法(TTNRBO)优化深度信念网络(DBN)数据回归预测研究(Matlab代码实现)
【基于TTNRBO优化DBN回归预测】基于瞬态三角牛顿-拉夫逊优化算法(TTNRBO)优化深度信念网络(DBN)数据回归预测研究(Matlab代码实现)
242 0
|
6月前
|
算法 数据挖掘 区块链
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
178 2
|
6月前
|
机器学习/深度学习 算法 调度
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
493 0
|
5月前
|
机器学习/深度学习 数据采集 存储
概率神经网络的分类预测--基于PNN的变压器故障诊断(Matlab代码实现)
概率神经网络的分类预测--基于PNN的变压器故障诊断(Matlab代码实现)
841 0
|
6月前
|
机器学习/深度学习 并行计算 算法
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
154 8

热门文章

最新文章