#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); } |