Chinaunix首页 | 论坛 | 博客
  • 博客访问: 84006
  • 博文数量: 32
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-09 18:44
文章分类
文章存档

2014年(32)

我的朋友

分类:

2014-09-25 22:54:15

原文地址:BP网(C语言实现) 作者:RealAMD

神经网络程序之三:BP网

#include
#include
#include
#include
#include "utility.h"

#define NUM_IN     6 //输入层神经元数量I
#define NUM_MID    5 //中间层神经元数量J
#define NUM_OUT    4 //输出层神经元数量K
#define NUM_PATTERN 3 //输入的模式数量
#define CONSTANT 0.15  //η常量
#define MAX_COUNT 10000 //最大学习次数

double input_in[NUM_PATTERN][NUM_IN]; //输入层的输入值
double input_mid[NUM_MID]; //中间层的输入值
double output_mid[NUM_MID]; //中间层的输出值
double input_out[NUM_OUT]; //输出层的输入值
double output_out[NUM_OUT]; //输出层的输出值

double V[NUM_MID][NUM_IN]; //中间层神经元与输入层神经元的权值
double W[NUM_OUT][NUM_MID]; //输出层神经元与中间层神经元的权值

double v[NUM_MID];   //中间层阈值
double w[NUM_OUT];   //输出层阈值

double d[NUM_PATTERN][NUM_OUT];  //输出层的教师信号

double error_out[NUM_OUT];  //输出层各单元的一般化误差
double error_mid[NUM_MID];  //中间层各单元的一般化误差

int dirty[NUM_PATTERN];   //如果模式i未被访问过,则dirty[i] == TRUE

char *Filename = "1.PTN"; //学习模式文件
char *Filename1 = "1.TSIG"; //教师信号文件
char *Filename2 = "1.RESULT"; //结果文件   


void process();    //主计算过程
int trainpattern(int pattern); //训练模式
void initialize();   //初始化函数
void init_weight();   //初始化权重、阈值
void load_patternfile(); //从文件加载学习模式
void load_techersig();  //从文件加载教师信号

void compute_midinput(int pattern); //计算中间层输入值
void compute_midoutput(); //计算中间层输出值
void compute_outinput(); //计算输出层输入值
void compute_outoutput(); //计算输出层输出值
void compute_outerror(int pattern); //计算输出层各单元的一般化误差
void compute_miderror(); //计算中间层各单元的一般化误差
void adjust_mid_out();  //调整中间层至输出层之间的连接权值及输出层各单元的阈值
void adjust_in_mid(int pattern); //调整输入层至中间层之间的连接权值,及中间层各单元的阈值
double Func(double net); //f() sigmoid函数

void print_all();   //打印所有数组

/********************************************************
                     程序入口
*********************************************************/
int main(int argc, char **args)
{
 if(argc == 3){
  Filename = args[1];
  Filename1 = args[2];
 }
 initialize();
 process();
 print_all();
 return(1);
}

/********************************************************
                     初始化
*********************************************************/
void initialize()
{
 init_weight();
 //print_all();
 load_patternfile();
 load_techersig();
 setalldirty(NUM_PATTERN, dirty);
}

/********************************************************
                     从文件加载学习模式
*********************************************************/
void init_weight()
{
 int i, j, k;
 printf("\n开始初始化权值、阈值...");
 //初始化中间层神经元与输入层神经元的权值
 for(j = 0;j < NUM_MID;j++)
  for(i = 0;i < NUM_IN;i++)
   V[j][i] = gen_random();
 //初始化输出层神经元与中间层神经元的权值
 for(k = 0;k < NUM_OUT;k++)
  for(j = 0;j < NUM_MID;j++)
   W[k][j] = gen_random();
 //初始化中间层阈值
 for(j = 0;j < NUM_MID;j++)
  v[j] = gen_random();
 //初始化输出层阈值
 for(k = 0;k < NUM_OUT;k++)
  w[k] = gen_random();
 printf("\n初始化权值、阈值完毕...");
}

/********************************************************
                     从文件加载学习模式
*********************************************************/
void load_patternfile()
{
 FILE *PATTERNFILE;
 double temp;
 int i, j;
 printf("\n开始加载学习模式...");
 PATTERNFILE = fopen(Filename, "r");
 if(PATTERNFILE == NULL){
  printf("\n不能打开学习模式文件:%s\n", Filename);
  exit(0);
 }
 for(i = 0;i < NUM_PATTERN;i++){
  for(j = 0;j < NUM_IN;j++){
   fscanf(PATTERNFILE, PREMISE, &temp);
   input_in[i][j] = temp;
  }
 }
 fclose(PATTERNFILE);
 printf("\n加载学习模式完毕...");
}

/********************************************************
                     从文件加载教师信号
*********************************************************/
void load_techersig()
{
 FILE *TSIGFILE;
 double temp;
 int i, j;
 printf("\n开始加载教师信号...");
 TSIGFILE = fopen(Filename1, "r");
 if(TSIGFILE == NULL){
  printf("\n不能打开学习教师信号文件:%s\n", Filename1);
  exit(0);
 }
 for(i = 0;i < NUM_PATTERN;i++){
  for(j = 0;j < NUM_OUT;j++){
   fscanf(TSIGFILE, PREMISE, &temp);
   d[i][j] = temp;
  }
 }
 fclose(TSIGFILE);
 printf("\n加载教师信号完毕...");
}
/********************************************************
                     主计算过程
*********************************************************/
void process()
{
 int counter = 0; //学习次数计数器
 int rand_pattern, ChngCount = 0;
 printf("\n进行第1次学习\n");
 while(counter < MAX_COUNT){
  rand_pattern = random(NUM_PATTERN);
  dirty[rand_pattern] = FALSE;
  trainpattern(rand_pattern);
  if(isallclean(NUM_PATTERN, dirty)){
   setalldirty(NUM_PATTERN, dirty);
   counter++;
   printf("\n进行第%d次学习\n", counter);
  }
 }
}
/********************************************************
                     训练模式
*********************************************************/
int trainpattern(int pattern)
{
 compute_midinput(pattern);
 compute_midoutput();
 compute_outinput();
 compute_outoutput();
 compute_outerror(pattern);
 compute_miderror();
 adjust_mid_out();
 adjust_in_mid(pattern);
 if(dirty[pattern] == TRUE)
  return TRUE;
 else
  return FALSE;
}

/********************************************************
                     计算中间层输入值
*********************************************************/
void compute_midinput(int pattern)
{
 int i, j;
 for(j = 0;j < NUM_MID;j++){
  input_mid[j] = 0;
  for(i = 0;i < NUM_IN;i++){
   input_mid[j] += V[j][i]*input_in[pattern][i];
  }
  input_mid[j] -= v[j];
 }
}

/********************************************************
                     计算中间层输出值
*********************************************************/
void compute_midoutput()
{
 int j;
 for(j = 0;j < NUM_MID;j++)
  output_mid[j] = Func(input_mid[j]);
}

/********************************************************
                     计算输出层输入值
*********************************************************/
void compute_outinput()
{
 int j, k;
 for(k = 0;k < NUM_OUT;k++){
  input_out[k] = 0;
  for(j = 0;j < NUM_MID;j++){
   input_out[j] += W[k][j]*output_mid[j];
  }
  input_out[k] -= w[k];
 }
}

/********************************************************
                     计算输出层输出值
*********************************************************/
void compute_outoutput()
{
 int k;
 for(k = 0;k < NUM_OUT;k++)
  output_out[k] = Func(input_out[k]);
}

/********************************************************
               计算输出层各单元的一般化误差
*********************************************************/
void compute_outerror(int pattern)
{
 int k;
 for(k = 0;k < NUM_OUT;k++){
  error_out[k] = (d[pattern][k] - output_out[k])*output_out[k]*(1 - output_out[k]);
 }
}
/********************************************************
               计算中间层各单元的一般化误差
*********************************************************/
void compute_miderror()
{
 int j, k;
 for(j = 0;j < NUM_MID;j++){
  error_mid[j] = 0;
  for(k = 0;k < NUM_OUT;k++)
   error_mid[j] += error_out[k]*W[k][j];
  error_mid[j] = error_mid[j]*output_mid[j]*(1 - output_mid[j]);
 }
}
/********************************************************
   调整中间层至输出层之间的连接权值及输出层各单元的阈值
*********************************************************/
void adjust_mid_out()
{
 int j, k;
 for(k = 0;k < NUM_OUT;k++){
  for(j = 0;j < NUM_MID;j++)
   W[k][j] += CONSTANT*error_out[k]*output_mid[j];
  w[k] -= CONSTANT*error_out[k];
 }
}
/********************************************************
   调整输入层至中间层之间的连接权值,及中间层各单元的阈值
*********************************************************/
void adjust_in_mid(int pattern)
{
 int i, j;
 for(j = 0;j < NUM_MID;j++){
  for(i = 0;i < NUM_IN;i++)
   V[j][i] += CONSTANT*error_mid[j]*input_in[pattern][i];
  v[j] -= CONSTANT*error_mid[j];
 }
}

/********************************************************
                     f()函数
*********************************************************/
double Func(double net)
{
 return 1/(1 + exp(-net));
}
/********************************************************
                     打印所有数组
*********************************************************/
void print_all()
{
 FILE *RESULTFILE = fopen(Filename2, "w");
 if(RESULTFILE == NULL){
  printf("不能打开结果文件: %s", Filename2);
  exit(0);
 }
 printf("\n打印学习模式");
 fprintf(RESULTFILE, "\n打印学习模式");
 print_two(RESULTFILE, (double **)input_in, NUM_PATTERN, NUM_IN);
 printf("\n打印中间层神经元与输入层神经元的权值");
 fprintf(RESULTFILE, "\n打印中间层神经元与输入层神经元的权值");
 print_two(RESULTFILE, (double **)V, NUM_MID, NUM_IN);
 printf("\n打印输出层神经元与中间层神经元的权值");
 fprintf(RESULTFILE, "\n打印输出层神经元与中间层神经元的权值");
 print_two(RESULTFILE, (double **)W, NUM_OUT, NUM_MID);
 printf("\n打印中间层阈值");
 fprintf(RESULTFILE, "\n打印中间层阈值");
 print_one(RESULTFILE, v, NUM_MID);
 printf("\n打印输出层阈值");
 fprintf(RESULTFILE, "\n打印输出层阈值");
 print_one(RESULTFILE, w, NUM_OUT);
 printf("\n打印期望输出值");
 fprintf(RESULTFILE, "\n打印期望输出值");
 print_one(RESULTFILE, d[0], NUM_OUT);
 printf("\n打印最终输出值");
 fprintf(RESULTFILE, "\n打印最终输出值");
 print_one(RESULTFILE, output_out, NUM_OUT);
 fclose(RESULTFILE);
}

阅读(463) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~