📄 backprop.cpp
字号:
/* ****************************************************************** * backprop.cpp ****************************************************************** *///#include "stdafx.h"#include <stdio.h>#include "backprop.h"#include <math.h>#include <stdlib.h>
#include <time.h>#define ABS(x) (((x) > 0.0) ? (x) : (-(x)))/* 宏定义:快速拷贝 */#define fastcopy(to,from,len)\{\ register char *_to,*_from;\ register int _i,_l;\ _to = (char *)(to);\ _from = (char *)(from);\ _l = (len);\ for (_i = 0; _i < _l; _i++) *_to++ = *_from++;\}/*** 返回0-1的双精度随机数 ***/float drnd(){ return ((float) rand() / (float) BIGRND);}/*** 返回-1.0到1.0之间的双精度随机数 ***/float dpn1(){ return (((float)drnd() * (float)2.0) - (float)1.0);}/*** 作用函数,目前是S型函数 ***/float squash(float x){ return ((float)1.0 / ((float)1.0 + (float)exp(-x)));}/*** 申请1维双精度实数数组 ***/float *alloc_1d_dbl(int n){ float *new1; new1 = (float *) malloc ((unsigned) (n * sizeof (float))); if (new1 == NULL)
{ printf("ALLOC_1D_DBL: Couldn't allocate array of doubles\n"); return (NULL); } return (new1);}/*** 申请2维双精度实数数组 ***/float **alloc_2d_dbl(int m, int n){ int i; float **new1; new1 = (float **) malloc ((unsigned) (m * sizeof (float *))); if (new1 == NULL)
{ printf("ALLOC_2D_DBL: Couldn't allocate array of dbl ptrs\n"); return (NULL); } for (i = 0; i < m; i++)
{ new1[i] = alloc_1d_dbl(n); } return (new1);}/*** 随机初始化权值 ***/void bpnn_randomize_weights(float **w, int m, int n){ int i, j; for (i = 0; i <= m; i++)
{ for (j = 0; j <= n; j++)
{ w[i][j] = dpn1(); } }}/*** 0初始化权值 ***/void bpnn_zero_weights(float **w, int m, int n){ int i, j; for (i = 0; i <= m; i++)
{ for (j = 0; j <= n; j++)
{ w[i][j] = 0.0; } }}/*** 设置随机数种子 ***/void bpnn_initialize(int seed){ printf("Random number generator seed: %d\n", seed); srand(seed);}
/*** 创建BP网络 ***/BPNN *bpnn_internal_create(int n_in, int n_hidden, int n_out){ BPNN *newnet; newnet = (BPNN *) malloc (sizeof (BPNN)); if (newnet == NULL)
{ printf("BPNN_CREATE: Couldn't allocate neural network\n"); return (NULL); } newnet->input_n = n_in; newnet->hidden_n = n_hidden; newnet->output_n = n_out; newnet->input_units = alloc_1d_dbl(n_in + 1); newnet->hidden_units = alloc_1d_dbl(n_hidden + 1); newnet->output_units = alloc_1d_dbl(n_out + 1); newnet->hidden_delta = alloc_1d_dbl(n_hidden + 1); newnet->output_delta = alloc_1d_dbl(n_out + 1); newnet->target = alloc_1d_dbl(n_out + 1); newnet->input_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1); newnet->hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); newnet->input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1); newnet->hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); return (newnet);}/* 释放BP网络所占地内存空间 */void bpnn_free(BPNN *net){ int n1, n2, i; n1 = net->input_n; n2 = net->hidden_n; free((char *) net->input_units); free((char *) net->hidden_units); free((char *) net->output_units); free((char *) net->hidden_delta); free((char *) net->output_delta); free((char *) net->target); for (i = 0; i <= n1; i++)
{ free((char *) net->input_weights[i]); free((char *) net->input_prev_weights[i]); }
free((char *) net->input_weights); free((char *) net->input_prev_weights); for (i = 0; i <= n2; i++)
{ free((char *) net->hidden_weights[i]); free((char *) net->hidden_prev_weights[i]); }
free((char *) net->hidden_weights); free((char *) net->hidden_prev_weights); free((char *) net);}/*** 创建一个BP网络,并初始化权值***/BPNN *bpnn_create(int n_in, int n_hidden, int n_out){ BPNN *newnet; newnet = bpnn_internal_create(n_in, n_hidden, n_out);#ifdef INITZERO bpnn_zero_weights(newnet->input_weights, n_in, n_hidden);#else bpnn_randomize_weights(newnet->input_weights, n_in, n_hidden);#endif bpnn_randomize_weights(newnet->hidden_weights, n_hidden, n_out); bpnn_zero_weights(newnet->input_prev_weights, n_in, n_hidden); bpnn_zero_weights(newnet->hidden_prev_weights, n_hidden, n_out); return (newnet);}void bpnn_layerforward(float *l1, float *l2, float **conn, int n1, int n2){ float sum; int j, k; /*** 设置阈值 ***/ l1[0] = 1.0; /*** 对于第二层的每个神经元 ***/ for (j = 1; j <= n2; j++)
{ /*** 计算输入的加权总和 ***/ sum = 0.0; for (k = 0; k <= n1; k++)
{ sum += conn[k][j] * l1[k]; } l2[j] = squash(sum); }}/* 输出误差 */void bpnn_output_error(float *delta, float *target, float *output, int nj, float *err){ int j; float o, t, errsum; errsum = 0.0; for (j = 1; j <= nj; j++)
{ o = output[j]; t = target[j]; delta[j] = o * ((float)1.0 - o) * (t - o);
errsum += (float)0.5 * (t - o) * (t - o); //add by lzg //errsum += ABS(delta[j]); } *err = errsum;}/* 隐含层误差 */void bpnn_hidden_error(float* delta_h, int nh, float *delta_o, int no,
float **who, float *hidden, float *err){ int j, k; float h, sum, errsum; errsum = 0.0; for (j = 1; j <= nh; j++)
{ h = hidden[j]; sum = 0.0; for (k = 1; k <= no; k++)
{ sum += delta_o[k] * who[j][k]; } delta_h[j] = h * ((float)1.0 - h) * sum; errsum += ABS(delta_h[j]); } *err = errsum;}/* 调整权值 */void bpnn_adjust_weights(float *delta, int ndelta, float *ly, int nly,
float** w, float **oldw, float eta, float momentum){ float new_dw; int k, j; ly[0] = 1.0; for (j = 1; j <= ndelta; j++)
{ for (k = 0; k <= nly; k++)
{ new_dw = ((eta * delta[j] * ly[k]) + (momentum * oldw[k][j])); w[k][j] += new_dw; oldw[k][j] = new_dw; } }}/* 进行前向运算 */void bpnn_feedforward(BPNN* net){ int in, hid, out; in = net->input_n; hid = net->hidden_n; out = net->output_n; /*** Feed forward input activations. ***/ bpnn_layerforward(net->input_units, net->hidden_units, net->input_weights, in, hid); bpnn_layerforward(net->hidden_units, net->output_units, net->hidden_weights, hid, out);}/* 训练BP网络 */void bpnn_train(BPNN *net, float eta, float momentum, float *eo, float *eh){ int in, hid, out; float out_err, hid_err; in = net->input_n; hid = net->hidden_n; out = net->output_n; /*** 前向输入激活 ***/ bpnn_layerforward(net->input_units, net->hidden_units, net->input_weights, in, hid); bpnn_layerforward(net->hidden_units, net->output_units, net->hidden_weights, hid, out); /*** 计算隐含层和输出层误差 ***/ bpnn_output_error(net->output_delta, net->target, net->output_units, out, &out_err); bpnn_hidden_error(net->hidden_delta, hid, net->output_delta, out,
net->hidden_weights, net->hidden_units, &hid_err); *eo = out_err; *eh = hid_err; /*** 调整输入层和隐含层权值 ***/ bpnn_adjust_weights(net->output_delta, out, net->hidden_units, hid,
net->hidden_weights, net->hidden_prev_weights, eta, momentum); bpnn_adjust_weights(net->hidden_delta, hid, net->input_units, in,
net->input_weights, net->input_prev_weights, eta, momentum);}/* 保存BP网络 */void bpnn_save(BPNN *net, char *filename){ int n1, n2, n3, i, j, memcnt; float dvalue, **w; char *mem; FILE *fd; if ((fd = fopen(filename, "w")) == NULL)
{ printf("BPNN_SAVE: Cannot create '%s'\n", filename); return; } n1 = net->input_n;
n2 = net->hidden_n;
n3 = net->output_n;
printf("Saving %dx%dx%d network to '%s'\n", n1, n2, n3, filename); fflush(stdout); fwrite((char *) &n1, sizeof(int), 1, fd); fwrite((char *) &n2, sizeof(int), 1, fd); fwrite((char *) &n3, sizeof(int), 1, fd);
printf("%d %d %d\n",n1,n2,n3);
memcnt = 0; w = net->input_weights; mem = (char *) malloc ((unsigned) ((n1+1) * (n2+1) * sizeof(float)));
for (i = 0; i <= n1; i++)
{ for (j = 0; j <= n2; j++)
{ dvalue = w[i][j]; fastcopy(&mem[memcnt], &dvalue, sizeof(float)); memcnt += sizeof(float);
printf("%f\n",w[i][j]); } } fwrite(mem, (n1+1) * (n2+1) * sizeof(float), 1, fd); free(mem); memcnt = 0; w = net->hidden_weights; mem = (char *) malloc ((unsigned) ((n2+1) * (n3+1) * sizeof(float)));
for (i = 0; i <= n2; i++)
{ for (j = 0; j <= n3; j++)
{ dvalue = w[i][j]; fastcopy(&mem[memcnt], &dvalue, sizeof(float)); memcnt += sizeof(float);
printf("%f\n",w[i][j]); } } fwrite(mem, (n2+1) * (n3+1) * sizeof(float), 1, fd); free(mem); fclose(fd); return;}/* 从文件中读取BP网络 */BPNN *bpnn_read(char *filename){ char *mem; BPNN *new1; int n1, n2, n3, i, j, memcnt; FILE *fd; if ((fd = fopen(filename, "r")) == NULL)
{ return (NULL); } printf("Reading '%s'\n", filename);
fflush(stdout); fread((char *) &n1, sizeof(int), 1, fd); fread((char *) &n2, sizeof(int), 1, fd); fread((char *) &n3, sizeof(int), 1, fd); new1 = bpnn_internal_create(n1, n2, n3); printf("'%s' contains a %dx%dx%d network\n", filename, n1, n2, n3); printf("Reading input weights...");
fflush(stdout); memcnt = 0; mem = (char *) malloc ((unsigned) ((n1+1) * (n2+1) * sizeof(float))); fread( mem, (n1+1) * (n2+1) * sizeof(float), 1, fd); for (i = 0; i <= n1; i++)
{ for (j = 0; j <= n2; j++)
{ fastcopy(&(new1->input_weights[i][j]), &mem[memcnt], sizeof(float)); memcnt += sizeof(float); } } free(mem); printf("Done\nReading hidden weights...");
fflush(stdout); memcnt = 0; mem = (char *) malloc ((unsigned) ((n2+1) * (n3+1) * sizeof(float))); fread( mem, (n2+1) * (n3+1) * sizeof(float), 1, fd); for (i = 0; i <= n2; i++)
{ for (j = 0; j <= n3; j++)
{ fastcopy(&(new1->hidden_weights[i][j]), &mem[memcnt], sizeof(float)); memcnt += sizeof(float); } } free(mem); fclose(fd); printf("Done\n");
fflush(stdout); bpnn_zero_weights(new1->input_prev_weights, n1, n2); bpnn_zero_weights(new1->hidden_prev_weights, n2, n3); return (new1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -