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