BP神经网络(LM算法训练)--C代码

本文介绍了使用Levenberg-Maquardt法训练三层BP神经网络的C代码,适用于毕业设计中的自适应任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      前段时间毕业设计中写的一段代码,三层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));
}


/
LM算法,全称为Levenberg-Marquard算法,它可用于解决非线性最小二乘问题,多用于曲线拟合等场合。 LM算法的实现并不算难,它的关键是用模型函数 f 对待估参数向量 p 在其邻域内做线性近似,忽略掉二阶以上的导数项,从而转化为线性最小二乘问题,它具有收敛速度快等优点。LM算法属于一种“信赖域法”——所谓的信赖域法,此处稍微解释一下:在最优化算法中,都是要求一个函数的极小值,每一步迭代中,都要求目标函数值是下降的,而信赖域法,顾名思义,就是从初始点开始,先假设一个可以信赖的最大位移 s ,然后在以当前点为中心,以 s 为半径的区域内,通过寻找目标函数的一个近似函数(二次的)的最优点,来求解得到真正的位移。在得到了位移之后,再计算目标函数值,如果其使目标函数值的下降满足了一定条件,那么就说明这个位移是可靠的,则继续按此规则迭代计算下去;如果其不能使目标函数值的下降满足一定的条件,则应减小信赖域的范围,再重新求解。 事实上,你从所有可以找到的资料里看到的LM算法的说明,都可以找到类似于“如果目标函数值增大,则调整某系数再继续求解;如果目标函数值减小,则调整某系数再继续求解”的迭代过程,这种过程与上面所说的信赖域法是非常相似的,所以说LM算法是一种信赖域法。
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值