📄 bppaper.c
字号:
/* ffann-seq.c copyright (c) 2001 Nathan DeBardeleben and William Jones,
* all rights reserved
*
* Written by Nathan DeBardeleben and William Jones
* Parallel Architecture Research Laboratory (PARL)
* 352 Engineering Innovation Building
* Clemson University, Clemson SC
* March 2001
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
*
* Contact: Nathan DeBardeleben ndebard@parl.clemson.edu
* William Jones wjones@parl.clemson.edu
*/
/* Feed Forward Neural Network training
*
* arguments:
* input parameter file: a file containing the network architecture
* as well as the training set inputs
* # iterations: the number of iterations to run the simulation
* learning rate (rho): the larger the number, the more quickly the net will
* try and learn (be careful of overlearning!) (good values range from
* 0.75 to as low as 0.005 all depending on the steepness of the error
* space
* back propagation algorithm:
* 0: normal BP
* 1: modified BP for faster convergence
* checkpoint: set to either 0 (no) or >0 (yes) if you want the
* simulation to write the weights periodically to a weight file. This
* can be reloaded into the simulation when run again to continue a
* simulation where it last left off. The value input here, N, will
* cause the simulation to write out every N iterations.
* weights file (optional): if it is desired to load weights in from a saved
* weights file then supply the filename here. Note that the file must
* be for the same architecture as this simulation.
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define LINEAR 0
#define SIGMOID 1
unsigned char MASSINPUTS[8][8]= {
{1,0,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0},
{0,0,0,1,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,1},
};
unsigned char MASSTARGETS[8][8]={
{1,0,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0},
{0,0,0,1,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,1},
};
void readParamFile(char *filename, int *num_inputs, int *num_outputs,int *training_set_size, int *num_layers, int **arch, int **bias);
void printParams(int num_inputs, int num_outputs, int training_set_size,int num_layers, int *arch, int *bias);
void setupInputs(float ***unitinputs, int num_layers, int *arch, int *bias);
void zeroDeltaWeights(float ***deltaweights, int num_layers, int *arch, int *bias);
float runUnit(float *inputs, float *weights, int numInputs, int squasher);
void print2D(float **mat, int dim1, int dim2);
void printWeights(float ***weights, int numLayers, int *arch, int *bias);
float NthDerivative(int squasher, int deriv, float value);
float SigmoidAlpha = 1.0;
float RandomEqualREAL(float Low, float High)
{
return ((float) rand() / RAND_MAX) * (High-Low) + Low;
}
int main(int argc, char **argv)
{
FILE *file;
int iterations, checkpoint, num_inputs, num_outputs, training_set_size,num_layers, i, j, k, h, p, x, lastlayer;
/* arch: 各层结点数*/
int *arch, *bias;
unsigned char **squasher, **inputs, **targets;
char infilename[80];
float rho, floatin, TSS, thisError, out, sum, delta;
float **outputs, **deltas;
float ***weights, ***unitinputs, ***deltaweights, ***tempweights;
long int totalbytes = 0;
int checkpointOn = 0;
int BPALG = 0;
printf("SEQUENTIAL IMPLEMENTATION:\n");
if(argc < 6) {
fprintf(stderr, "Usage: %s [input parameter file] "
"[# iterations] [learning rate (rho)] [BPALG (0=normal, 1=modified)]"
"[checkpoint every # iterations] <weights file>\n", argv[0]);
exit(1);
}
iterations = atoi(argv[2]);
rho = atof(argv[3]);
BPALG = atoi(argv[4]);
checkpoint = atoi(argv[5]);
printf("BPALG = %d\n", BPALG);
readParamFile(argv[1], &num_inputs, &num_outputs, &training_set_size,&num_layers, &arch, &bias);
printParams(num_inputs, num_outputs, training_set_size,num_layers, arch, bias);
/*初始化输入输出层*/
printf("Initializing input and output layers... ... \n");
inputs = (unsigned char**)malloc(training_set_size*sizeof(unsigned char*));
targets = (unsigned char**)malloc(training_set_size*sizeof(unsigned char*));
for(i=0; i<training_set_size; i++) {
totalbytes += 2*num_inputs*sizeof(unsigned char);
inputs[i] = (unsigned char*)malloc(num_inputs*sizeof(unsigned char));
targets[i] = (unsigned char*)malloc(num_outputs*sizeof(unsigned char));
for(j=0; j<num_inputs; j++)
inputs[i][j] = MASSINPUTS[i][j];
for(j=0; j<num_outputs; j++)
targets[i][j] = MASSTARGETS[i][j];
printf("INPUTS:\t");
for(j=0; j<num_inputs; j++)
printf("\t%d", inputs[i][j]);
printf("\nTARGETS:");
for(j=0; j<num_outputs; j++)
printf("\t%d", targets[i][j]);
printf("\n");
/*用于脸部识别功能的输入输出层初始化*/
/* this code below is for face recognition */
/*
sprintf(infilename, "faces.NN/face_%d.NN", i+1);
file = fopen(infilename, "r");
if(!file) {
perror("fopen");
exit(1);
}
printf("\tOpened file: %s\n", infilename);
fread(inputs[i], sizeof(unsigned char), num_inputs, file);
fread(targets[i], sizeof(unsigned char), num_inputs, file);
for(k=0; k<num_outputs; k++)
printf("%d ", targets[i][k]);
printf("\n");
fclose(file);
*/
}
/*初始化输入输出层结束*/
/*初始化各层权值*/
/*分配各层权值内存空间*/
weights = (float***)malloc(num_layers*sizeof(float**));//当前权值
tempweights = (float***)malloc(num_layers*sizeof(float**));//临时权值
deltaweights = (float***)malloc(num_layers*sizeof(float**));//上次迭代权值
unitinputs = (float***)malloc(num_layers*sizeof(float**));//每层的输入值
for(i=0; i<num_layers; i++) {
weights[i] = (float**)malloc(arch[i]*sizeof(float*));
tempweights[i] = (float**)malloc(arch[i]*sizeof(float*));
deltaweights[i] = (float**)malloc(arch[i]*sizeof(float*));
unitinputs[i] = (float**)malloc(arch[i]*sizeof(float*));
for(j=0; j<arch[i]; j++) {
/* every layer but the first has weights of size of the previous
* layer */
if(i != 0) {
weights[i][j] = (float*)malloc((arch[i-1]+bias[i])*sizeof(float));
tempweights[i][j] = (float*)malloc((arch[i-1]+bias[i])*sizeof(float));
deltaweights[i][j] = (float*)malloc((arch[i-1]+bias[i])*sizeof(float));
unitinputs[i][j] = (float*)malloc((arch[i-1]+bias[i])*sizeof(float));
}
/* for simplicity later, pretend input units have weights of 1 */
else {
weights[i][j] = (float*)malloc((1+bias[i])*sizeof(float));
tempweights[i][j] = (float*)malloc((1+bias[i])*sizeof(float));
deltaweights[i][j] = (float*)malloc((arch[i-1]+bias[i])*sizeof(float));
unitinputs[i][j] = (float*)malloc((1+bias[i])*sizeof(float));
}
}
}
/*分配权值空间结束*/
/*对各层当前权值赋值,采用两种赋值方式:1.随机数赋值;2.从文件读取*/
/* if the user is not reading in weights from a file . . . */
printf("Initializing weight parameters... ... \n");
if(argc <= 6) {
/* fill up the weight matrix with random gaussian values */
//srand((unsigned int)time(NULL));
for(i=0; i<num_layers; i++) {
for(j=0; j<arch[i]; j++) {
if(i != 0)
lastlayer = arch[i-1];
else
lastlayer = 1;
for(k=0; k<(lastlayer+bias[i]); k++) {
if(i != 0)
weights[i][j][k] = RandomEqualREAL(0.0, 1.0);
else
weights[i][j][k] = 1.0;
}
}
}
}
/* they want to read weights in from a checkpoint file, do so now */
else {
printf("reading weights from '%s' file\n", argv[6]);
file = fopen(argv[6], "r");
if(!file) {
perror("fopen");
exit(1);
}
for(j=0; j<num_layers; j++) {
for(k=0; k<arch[j]; k++) {
if(j != 0) lastlayer = arch[j-1];
else lastlayer = 0;
for(h=0; h<(lastlayer+bias[j]); h++) {
fscanf(file, "%f\t", &floatin);
printf("floatin = %f\n", floatin);
weights[j][k][h] = floatin;
}
if(lastlayer + bias[j] > 0)
fscanf(file, "\n");
}
}
fclose(file);
}
printf("Initializing weight parameters end. \n");
/*赋值结束*/
/*初始化各层权值结束*/
/* alloc the matrices for deltas and outputs from each unit */
outputs = (float**)malloc(num_layers*sizeof(float*));//各层输出向量
deltas = (float**)malloc(num_layers*sizeof(float*));//??
squasher = (unsigned char**)malloc(num_layers*sizeof(unsigned char*));//用来判断采用计算输出向量的方式,
//参看代码最后NthDerivative方法。
for(i=0; i<num_layers; i++) {
outputs[i] = (float*)malloc(arch[i]*sizeof(float));
deltas[i] = (float*)malloc(arch[i]*sizeof(float));
squasher[i] = (unsigned char*)malloc(arch[i]*sizeof(unsigned char));
}
/* set up the squasher matrix */
printf("seting up the squasher matrix... ... \n");
for(i=0; i<num_layers; i++) {
if(i == 0)
k = LINEAR;
else
k = SIGMOID;
for(j=0; j<arch[i]; j++)
squasher[i][j] = (unsigned char)k;
}
/*初始化各层单元输入值和上次迭代矩阵*/
printf("Initializing unitinputs and deltaweights... ... \n");
setupInputs(unitinputs, num_layers, arch, bias);
zeroDeltaWeights(deltaweights, num_layers, arch, bias);
/************************************************************************/
/* BEGIN: main loop */
/************************************************************************/
printf("main loop starting... ... \n");
for(i=0; i<iterations; i++) {
printf("ITERATION %d\n", i);
TSS = 0.0;
for(k=1; k<num_layers; k++) {
for(h=0; h<arch[k]; h++) {
for(p=0; p<arch[k-1]+bias[k]; p++)
deltaweights[k][h][p] = 0.0;
}
}
for(j=0; j<training_set_size; j++) {
thisError = 0.0;
/* write the net inputs to the first layer unit inputs */
/*将网络输入值写入第一层的单元输入*/
for(k=0; k<arch[0]; k++)
unitinputs[0][k][0] = inputs[j][k];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -