⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bpnet.txt

📁 和好的算法
💻 TXT
📖 第 1 页 / 共 2 页
字号:
  前段时间毕业设计中写的一段代码,三层BP神经网络用于自适应,用Levenberg-Maquardt法进行训练。

 

#define EPSILON 1E-6

//3层的神经网络结构
typedef struct tag_bpnnt 
...{
    int in_n;           //输入层神经元数
    int hidd_n;         //隐层神经元数
    int out_n;            //输出层神经元
    double *in_unit;    //输入层神经元
    double *hidd_unit;    //隐层神经元
    double *out_unit;    //输出层神经元
    
    double *hidd_delta; //隐层误差
    double *out_delta;  //输出层误差
    double *hidd_dfda;
    double *out_dfda;
    double *target;        //目标向量
    double **in_w;        //输入层权值
    double **hidd_w;    //隐层权值
    
    //前一次结果(用于迭代)
    double **prev_in_w;
    double **prev_hidd_w;
    
} BPNN_t;

//分配1d内存
double *bpnn_malloc1d(int n);

//分配2d内存
double **bpnn_malloc2d(int m, int n);

//销毁2d内存
void bpnn_mfree2d(double **pmem, int m);

//计算sigmoid函数
double sigmoid(double x);

//建立神经网络
BPNN_t* bpnn_create(int nIn, int nHidden, int nOut);

//销毁网络
void bpnn_destroy(BPNN_t *pNet);

//初始化权值
void bpnn_init_weight(double **w, int m, int n, int flag);

//前向计算本层输出
void bpnn_layerforward(double *layer1, double *layer2, double **conn, int n1, int n2);

//计算输出层反传误差
void bpnn_out_error(double *delta, double *dfda, double *target, double *output, int nj, double *err);

//计算隐层反传误差
void bpnn_hidd_error(double *delta_h, double *delta_o, double *dfda_h, double *dfda_o, 
                     int nh, int nout, double **w_ho, double *h_unit, double *err);

//计算整个网络输出
void bpnn_nnforward(BPNN_t *pNet);

//最速下降法训练一次
double bpnn_train_steepest(BPNN_t *pNet, double eta, double **indata, double **targetdata, int np);


//Levenberg-Marquardt训练
double bpnn_train_lm(BPNN_t *pNet, double **indata, double **targetdata, int np, double *lamda);

//gauss-jordan消元法解线性方程组
void gauss_jordan(double *a, double *b, int n);
 

 

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

#include "bpnn.h"

//交换
#define SWAP(x,y) if((x)!=(y)) 
            ...{    x = x+y; 
                y = x-y; 
                 x = x-y; }

//设置单位矩阵
static void SetEye(double *mat, int n);

//分配1d内存
double* bpnn_malloc1d(int n)
...{
    double *pout;
    pout = (double*)malloc(n*sizeof(double));
    return pout;
}

//分配2d内存
//m为行数(组数), n为列数(每组个数)
double** bpnn_malloc2d(int m, int n)
...{
    double **pout;
    int i;
    
    pout = (double**)malloc(m * sizeof(double*));
    for(i=0; i<m; i++)
    ...{
        pout[i] = (double*)malloc(n*sizeof(double));
    }
    return pout;
}

//销毁2d内存
void bpnn_mfree2d(double **pmem, int m)
...{
    int i;
    for(i=0; i<m; i++)
    ...{
        free(pmem[i]);
    }
    free(pmem);
    pmem = NULL;
}


/**//////////////////////////////////////////////////////////////////////
// 初始化权值
//    参数
//        flag --  1 随机初始化   0  全部清0
//      m -- 上一层神经元数目
//      n -- 下一层神经元数目
/**/////////////////////////////////////////////////////////////////////
void bpnn_init_weight(double **w, int m, int n, int flag)
...{
    int i,j;
    
    srand((unsigned int)time(NULL));
    if(flag)  //随机生成
    ...{
        for(i=0; i<m+1; i++)
        for(j=0; j<n+1; j++)
        ...{
            //-1.0 ~ 1.0的随机值
            w[i][j] = (double)(rand()%2000) / 1000.0 - 1;
        }

    } 
    else   //全部清0
    ...{ 
        for(i=0; i<m+1; i++)
        for(j=0; j<n+1; j++)
        ...{
            w[i][j] = 0.0;
        }
    }

}

//计算sigmoid函数
double sigmoid(double x)
...{
    return 1.0 / (1.0+exp(-x));
}

/**//////////////////////////////////////////////////////////////////////
// 建立神经网络
//    参数
//        nIn      -- 输入层神经元数
//        nHidden  -- 隐层神经元数
//        nOut     -- 输出层神经元数
/**//////////////////////////////////////////////////////////////////////
BPNN_t* bpnn_create(int nIn, int nHidden, int nOut)
...{
    BPNN_t *pNet;
    pNet = (BPNN_t*)malloc(sizeof(BPNN_t)) ;
    
    pNet->in_n = nIn;
    pNet->hidd_n = nHidden;
    pNet->out_n = nOut;

    pNet->in_unit = bpnn_malloc1d(nIn+1);   //增加1保存阀值分量b
    pNet->hidd_unit = bpnn_malloc1d(nHidden+1);  
    pNet->out_unit = bpnn_malloc1d(nOut+1);
    pNet->hidd_delta = bpnn_malloc1d(nHidden+1);
    pNet->out_delta = bpnn_malloc1d(nOut+1);
    pNet->hidd_dfda = bpnn_malloc1d(nHidden+1);
    pNet->out_dfda = bpnn_malloc1d(nOut+1);
    pNet->target = bpnn_malloc1d(nOut+1);
    
    pNet->in_unit[0] = 1.0;    //阀值分量
    pNet->hidd_unit[0] = 1.0;  

    //网络权重
    pNet->in_w = bpnn_malloc2d(nIn+1, nHidden+1);
    pNet->hidd_w = bpnn_malloc2d(nHidden+1, nOut+1);
    pNet->prev_in_w = bpnn_malloc2d(nIn+1, nHidden+1);
    pNet->prev_hidd_w = bpnn_malloc2d(nHidden+1, nOut+1);    

    //初始化权值
    bpnn_init_weight(pNet->in_w, nIn, nHidden, 1);
    bpnn_init_weight(pNet->hidd_w, nHidden, nOut, 1);
    bpnn_init_weight(pNet->prev_in_w, nIn, nHidden, 0);
    bpnn_init_weight(pNet->prev_hidd_w, nHidden, nOut, 0);

    return pNet;
}

//销毁网络
void bpnn_destroy(BPNN_t *pNet)
...{
    int i;
    int n1; 
    int n2; 
    n1 = pNet->in_n;
    n2 = pNet->hidd_n;
    
    free(pNet->in_unit);
    free(pNet->hidd_unit);
    free(pNet->out_unit);
    free(pNet->hidd_delta);
    free(pNet->out_delta);
    free(pNet->hidd_dfda);
    free(pNet->out_dfda);
    free(pNet->target);

    for(i=0; i<n1+1; i++)
    ...{
        free(pNet->prev_in_w[i]);
        free(pNet->in_w[i]);
    }
    free(pNet->prev_in_w);
    free(pNet->in_w);

    for(i=0; i<n2+1; i++)
    ...{
        free(pNet->prev_hidd_w[i]);
        free(pNet->hidd_w[i]);
    }
    free(pNet->prev_hidd_w);
    free(pNet->hidd_w);
    free(pNet);

}

/**//////////////////////////////////////////////////////////////////////
// 前向计算本层的输出
//    参数
//        layer1   -- 上一层神经元数组
//        layer2  -- 该层神经元数组
//        conn     -- 上层连接权值
//      n1       -- 上层神经元个数
//        n2       -- 本层神经元个数
//    返回
//      更新layer1, layer2
/**//////////////////////////////////////////////////////////////////////
void bpnn_layerforward(double *layer1, double *layer2, double **conn, int n1, int n2)
...{
    double sum;
    int j, k;

    layer1[0] = 1.0;   //以第0个代表阀值分量
    for(j=1; j<n2+1; j++)
    ...{
        sum = 0.0;
        for(k=0; k<n1+1; k++)
            ...{ sum += conn[k][j] * layer1[k]; }
        
        layer2[j] = sigmoid(sum);
    }
}

/**//////////////////////////////////////////////////////////////////////
// 计算输出层反传误差(单个样本)
//    参数
//        delta   -- 反传误差向量
//        target  -- 目标值
//        output  -- 网络输出值
//      nj      -- 输出层神经元数
//        err     -- 总误差
//    返回
//      更新err,delta
/**//////////////////////////////////////////////////////////////////////
void bpnn_out_error(double *delta, double *dfda, double *target, double *output, int nj, double *err)
...{
    int j;
    double errsum = 0.0;
    
    for(j=0; j<nj+1; j++)
    ...{
        //求反传误差
        delta[j] = output[j] * (1-output[j]) * (target[j] - output[j]);
        dfda[j] = output[j] * (1-output[j]);
        errsum += fabs(delta[j]);
    }
    *err = errsum;
    
}

/**//////////////////////////////////////////////////////////////////////
// 计算隐层反传误差(单个样本)
//    参数
//        delta_h  -- 隐层反传误差向量
//        delta_o  -- 输出层反传误差
//        dfda_h
//        dfda_h
//        nh         -- 隐层神经元数目
//      nout     -- 输出层神经元数
//        w_ho     -- 隐层到输出层连接权值
//        h_unit     -- 隐层神经元数组
//        err         -- 总误差
//    返回
//      更新err,delta_h
/**//////////////////////////////////////////////////////////////////////
void bpnn_hidd_error(double *delta_h, double *delta_o, double *dfda_h, double *dfda_o, 
                     int nh, int nout, double **w_ho, double *h_unit, double *err)
...{
    int j,k;
    double hidd, sum, sum2, errsum;
    
    errsum = 0.0;
    for(j=0; j<nh+1; j++)
    ...{
        hidd = h_unit[j];
        sum = 0.0;
        sum2 = 0.0;
        for(k=1; k<nout+1; k++)
        ...{
            sum += delta_o[k] * w_ho[j][k];
            sum2 += dfda_o[k] * w_ho[j][k];
        }
        delta_h[j] = hidd * (1-hidd) * sum;
        dfda_h[j] = hidd * (1-hidd) * sum2;
        errsum += fabs(delta_h[j]);
    }
    *err = errsum;

}

//计算整个网络输出
void bpnn_nnforward(BPNN_t *pNet)
...{
    int nIn, nHidd, nOut;
    nIn = pNet->in_n;
    nHidd = pNet->hidd_n;
    nOut = pNet->out_n;
    
    //计算输入层--隐层
    bpnn_layerforward(pNet->in_unit, pNet->hidd_unit, pNet->in_w, nIn, nHidd);
    //计算隐层--输出层
    bpnn_layerforward(pNet->hidd_unit, pNet->out_unit, pNet->hidd_w, nHidd, nOut);
}

/**//////////////////////////////////////////////////////////////////////
// 最速下降法的BP网络单次训练(全部样本)
//    参数
//        pNet       -- 已初始化的神经网络
//        eta        -- 最速下降步长
//        indata       -- 输入的样本数组
//        targetdata -- 输出期望
//      np           -- 样本个数
//    返回
//        返回更新后的平方误差
//      更新pNet
/**//////////////////////////////////////////////////////////////////////
double bpnn_train_steepest(BPNN_t *pNet, double eta, double **indata, double **targetdata, int np)
...{
    int p,i,j,k;
    int nIn, nHidd, nOut;
    double errout, errh;
    double esqrsum, esqr;
    double **pGradIn, **pGradH;
    
    nIn = pNet->in_n;
    nHidd = pNet->hidd_n;
    nOut = pNet->out_n;

    pGradIn = bpnn_malloc2d(nIn+1, nHidd+1);
    pGradH = bpnn_malloc2d(nHidd+1, nOut+1);

    //累加梯度清0
    for(j=0; j<=nIn; j++)
    for(k=0; k<=nHidd; k++)
    ...{
        pGradIn[j][k] = 0.0;
    }
    for(j=0; j<=nHidd; j++)
    for(k=0; k<=nOut; k++)
    ...{
        pGradH[j][k] = 0.0;
    }

    for(p=0; p<np; p++)
    ...{
        //输入数据
        pNet->in_unit[0] = 0.0;  //无偏移
        for(i=1; i<=nIn; i++)
            pNet->in_unit[i] = indata[p][i-1];
        for(i=1; i<=nOut; i++)
            pNet->target[i] = targetdata[p][i-1];
    
        bpnn_nnforward(pNet);
        bpnn_out_error(pNet->out_delta, pNet->out_dfda, pNet->target, pNet->out_unit, nOut, &errout);
        bpnn_hidd_error(pNet->hidd_delta, pNet->out_delta, pNet->hidd_dfda, pNet->out_dfda,
                nHidd, nOut, pNet->hidd_w, pNet->hidd_unit,&errh);
            

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -