📄 learning.c
字号:
/* Copyright (c) 1994-98 by The MathWorks, Inc. */
/* $Revision: 1.8 $ $Date: 1997/12/01 21:45:36 $ $Author: moler $ */
/* forward pass from node 'from' to node 'to' */
/* the input vector should have been dispatched */
static void
#ifdef __STDC__
anfisForward(FIS *fis, int from, int to)
#else
anfisForward(fis, from, to)
FIS *fis;
int from;
int to;
#endif
{
int i;
if (from < fis->in_n || to >= fis->node_n)
fisError("Node index out of bound!");
/* forward calculation */
for (i = from; i <= to ; i++)
fis->node[i]->value =
(*fis->node[i]->nodeFcn)(fis, i, "forward", -1);
/*
PRINT(from);
PRINT(to);
anfisPrintData(fis);
*/
}
/* backward pass from node 'from' to node 'to' */
/* the de_do field of output nodes should have been set */
static void
#ifdef __STDC__
anfisBackward(FIS *fis, int from, int to)
#else
anfisBackward(fis, from, to)
FIS *fis;
int from;
int to;
#endif
{
int i;
if (from < fis->in_n || to >= fis->node_n)
fisError("Node index out of bound!");
/* backward calculation */
for (i = from; i >= to; i--) {
double de_do, do_do;
FAN *p, *q;
int k;
de_do = 0;
for (p = fis->node[i]->fanout; p != NULL; p = p->next) {
/* O_i is the k-th fanin of O_{p->index} --> find k */
for (k = 0, q = fis->node[p->index]->fanin;
q->index != i; q = q->next, k++);
if (k >= fis->node[p->index]->fanin_n)
fisError("Cannot find k in anfisBackward!");
do_do = (*fis->node[p->index]->nodeFcn)
(fis, p->index, "backward", k);
/*
printf("do%d_do%d = %lf\n", p->index, i, do_do);
*/
de_do += fis->node[p->index]->de_do*do_do;
}
/* update fis->node[i]->de_do */
fis->node[i]->de_do = de_do;
}
}
/* update de_dp of parameterized node from 'from' to 'to'. */
static void
#ifdef __STDC__
anfisUpdateDE_DP(FIS *fis, int from, int to)
#else
anfisUpdateDE_DP(fis, from, to)
FIS *fis;
int from;
int to;
#endif
{
int i, j;
for (i = from; i <= to; i++)
for (j = 0; j < fis->node[i]->para_n; j++) {
fis->node[i]->do_dp[j] = (*fis->node[i]->nodeFcn)
(fis, i, "parameter", j);
fis->node[i]->de_dp[j] +=
fis->node[i]->de_do*fis->node[i]->do_dp[j];
}
}
/* This is good for both on-line and off-line */
/* update parameters of nodes from 'from' to 'to' */
static void
#ifdef __STDC__
anfisUpdateParameter(FIS *fis, int from, int to, double error)
#else
anfisUpdateParameter(fis, from, to, error)
FIS *fis;
int from;
int to;
double error;
#endif
{
int i, j;
double length = 0;
double total_firing_strength;
/* find the length of gradient vector */
for (i = from; i <= to; i++)
for (j = 0; j < fis->node[i]->para_n; j++)
length += pow(fis->node[i]->de_dp[j], 2.0);
length = sqrt(length);
if (length == 0) {
/*
printf("gradient vector length == 0!\n");
*/
return;
}
/*
printf("length = %lf\n", length);
fisPrintArray(fis->de_dp, fis->para_n);
fisPrintArray(fis->do_dp, fis->para_n);
fisPrintArray(fis->para, fis->para_n);
*/
/* update parameters */
for (i = from; i <= to; i++)
for (j = 0; j < fis->node[i]->para_n; j++)
/*=====kliu fis->node[i]->para[j] -=
fis->ss*fis->node[i]->de_dp[j]/length;
=============*/
fis->node[i]->para[j] -=
fis->ss*fis->node[i]->de_dp[j] * error/length;
}
/* clear de_do */
/* do_dp is overwritten every time, so it needs not to be cleared */
static void
#ifdef __STDC__
anfisClearDerivative(FIS *fis)
#else
anfisClearDerivative(fis)
FIS *fis;
#endif
{
int i;
for (i = 0; i < fis->para_n; i++)
fis->de_dp[i] = 0;
}
/* compute training error */
static double
#ifdef __STDC__
anfisComputeTrainingError(FIS *fis)
#else
anfisComputeTrainingError(fis)
FIS *fis;
#endif
{
int j, k;
double squared_error = 0;
for (j = 0; j < fis->trn_data_n; j++) {
/* dispatch inputs */
for (k = 0; k < fis->in_n; k++)
fis->node[k]->value = fis->trn_data[j][k];
/* forward calculation */
anfisForward(fis, fis->in_n, fis->node_n-1);
/* calculate error measure */
squared_error += pow(
fis->trn_data[j][fis->in_n] -
fis->node[fis->node_n-1]->value, 2.0);
}
return(sqrt(squared_error/fis->trn_data_n));
}
/* compute checking error */
static double
#ifdef __STDC__
anfisComputeCheckingError(FIS *fis)
#else
anfisComputeCheckingError(fis)
FIS *fis;
#endif
{
int j, k;
double squared_error = 0;
for (j = 0; j < fis->chk_data_n; j++) {
/* dispatch inputs */
for (k = 0; k < fis->in_n; k++)
fis->node[k]->value = fis->chk_data[j][k];
/* forward calculation */
anfisForward(fis, fis->in_n, fis->node_n-1);
/* calculate error measure */
squared_error += pow(
fis->chk_data[j][fis->in_n] -
fis->node[fis->node_n-1]->value, 2.0);
}
return(sqrt(squared_error/fis->chk_data_n));
}
/* a single epoch with index i, using GD only */
static void
#ifdef __STDC__
anfisOneEpoch0(FIS *fis, int i)
#else
anfisOneEpoch0(fis, i)
FIS *fis;
int i;
#endif
{
int j, k, ii;
double squared_error;
double error;
double total_firing_strength;
anfisClearDerivative(fis);
squared_error = 0;
for (j = 0; j < fis->trn_data_n; j++) {
/* dispatch inputs */
for (k = 0; k < fis->in_n; k++)
fis->node[k]->value = fis->trn_data[j][k];
/* forward calculation from layer 1 to layer 6 */
anfisForward(fis, fis->in_n, fis->node_n-1);
/* calculate error measure */
squared_error += pow(
fis->trn_data[j][fis->in_n] -
fis->node[fis->node_n-1]->value, 2.0);
/* dispatch de_do at outputs */
fis->node[fis->node_n-1]->de_do =
-2*(fis->trn_data[j][fis->in_n] -
fis->node[fis->node_n-1]->value);
/*=== fis->node[fis->node_n-1]->de_do = 1;
====*/
/* backward calculation */
anfisBackward(fis, fis->node_n-2, fis->in_n);
/* update de_dp */
anfisUpdateDE_DP(fis, fis->in_n, fis->node_n-1);
/* error =-2*( fis->trn_data[j][fis->in_n] - fis->node[fis->node_n-1]->value);
*/ /* print data for debugging */
/*
anfisPrintData(fis);
*/
}
/* error already calculated in de_do */
anfisUpdateParameter(fis, fis->in_n, fis->node_n-1, 1);
fis->trn_error[i] = sqrt(squared_error/fis->trn_data_n);
if (fis->chk_data_n != 0)
fis->chk_error[i] = anfisComputeCheckingError(fis);
}
/* a single epoch with index i, using both GD and LSE */
static void
#ifdef __STDC__
anfisOneEpoch1(FIS *fis, int i, double lamda)
#else
anfisOneEpoch1(fis, i)
FIS *fis;
int i;
double lamda;
#endif
{
int j, k;
double squared_error;
double error;
anfisClearDerivative(fis);
squared_error = 0;
anfisKalman(fis, 1, lamda); /* reset matrices used in kalman */
for (j = 0; j < fis->trn_data_n; j++) {
/* dispatch inputs */
for (k = 0; k < fis->in_n; k++)
fis->node[k]->value = fis->trn_data[j][k];
/* forward calculation from layer 1 to layer 3 */
anfisForward(fis, fis->in_n, fis->layer[4]->index-1);
/* store node outputs from layer 0 to 3 */
for (k = 0; k < fis->layer[4]->index; k++)
fis->tmp_node_output[j][k]=fis->node[k]->value;
anfisGetKalmanDataPair(fis, j);
anfisKalman(fis, 0, 0); /* normal operation */
}
anfisPutKalmanParameter(fis);
for (j = 0; j < fis->trn_data_n; j++) {
/* restore node outputs from layer 0 to 3 */
for (k = 0; k < fis->layer[4]->index; k++)
fis->node[k]->value=fis->tmp_node_output[j][k];
/* forward pass from layer 4 to 6 */
anfisForward(fis, fis->layer[4]->index, fis->node_n-1);
/* calculate error measure */
squared_error += pow(
fis->trn_data[j][fis->in_n] -
fis->node[fis->node_n-1]->value, 2.0);
/* dispatch de_do at outputs */
fis->node[fis->node_n-1]->de_do =
-2*(fis->trn_data[j][fis->in_n] -
fis->node[fis->node_n-1]->value);
/*=========== fis->node[fis->node_n-1]->de_do = 1; ===========*/
/* backward calculation */
anfisBackward(fis, fis->node_n-2, fis->in_n);
/* update de_dp of layer 1*/
anfisUpdateDE_DP(fis, fis->in_n,fis->layer[2]->index-1);
/* error =-.5*( fis->trn_data[j][fis->in_n] - fis->node[fis->node_n-1]->value);
*/
/* print data for debugging */
/*
anfisPrintData(fis);
*/
}
/*error already calculated */
anfisUpdateParameter(fis, fis->in_n, fis->layer[2]->index-1, 1);
fis->trn_error[i] = sqrt(squared_error/fis->trn_data_n);
if (fis->chk_data_n != 0)
fis->chk_error[i] = anfisComputeCheckingError(fis);
}
/* a single epoch with index i, using LM method */
static void
#ifdef __STDC__
anfisOneEpoch2(FIS *fis, int i, double lamda)
#else
anfisOneEpoch2(fis, i, lamda)
FIS *fis;
int i;
double lamda;
#endif
{
int j, k, ii;
double squared_error;
double total_firing_strength=0;
anfisClearDerivative(fis);
squared_error = 0;
anfisKalman(fis, 1, lamda); /* reset matrices used in kalman */
for (j = 0; j < fis->trn_data_n; j++) {
/* dispatch inputs */
for (k = 0; k < fis->in_n; k++)
fis->node[k]->value = fis->trn_data[j][k];
/* forward calculation from layer 1 to layer 7 */
anfisForward(fis, fis->in_n, fis->node_n-1);
/* calculate error measure */
squared_error += pow(
fis->trn_data[j][fis->in_n] -
fis->node[fis->node_n-1]->value, 2.0);
/* dispatch de_do at outputs */
/* use dy_do instead of de_do=====================*/
fis->node[fis->node_n-1]->de_do = 1;
/*============test end===================*
/* backward calculation */
anfisBackward(fis, fis->node_n-2, fis->in_n);
anfisUpdateDE_DP(fis, fis->in_n,fis->node_n-1);
anfisGetKalmanDataPair2(fis, j);
anfisKalman(fis, 0, 0); /* normal operation */
}
/*======= anfisPutKalmanParameter2(fis); ===========*/
if (i>0)
fis->trn_error[i-1] = sqrt(squared_error/fis->trn_data_n);
if (fis->chk_data_n != 0)
fis->chk_error[i] = anfisComputeCheckingError(fis);
}
/* main loop for learning */
static void
#ifdef __STDC__
anfisLearning(FIS *fis)
#else
anfisLearning(fis)
FIS *fis;
#endif
{
int i, k, j, ii, status, methodflag;
double *currentParam;
double lamda, squared_error, temperror, temp1;
currentParam = (double *)calloc(fis->para_n, sizeof(double));
/* if (fis->display_error)
printf("\nStart training ANFIS ...\n\n");*/
methodflag=fis->method;
if (methodflag == 1)
lamda = 1e6;
else if (methodflag ==2)
lamda = .08;
/*set plot output array*/
for (i = 0; i < fis->epoch_n; i++) {
if (methodflag==0){
/* GD only */
anfisOneEpoch0(fis, i);
}
/* GD + LSE */
if (methodflag==1)
anfisOneEpoch1(fis, i, lamda);
/* LM */
if (methodflag==2){
anfisOneEpoch2(fis, i, lamda);
if (i>0){
printf("\n anfis last err [%d-1]: %f \n",i, fis->trn_error[i-1]);
temperror=fis->trn_error[i-1];
}
else
temperror=10;
/* anfisPutKalmanParameter2(fis); */
/* check error to see direction */
if (i>=0){
k = 0;
for (ii=fis->in_n; ii<fis->node_n-1; ii++)
for (j = 0; j < fis->node[ii]->para_n; j++)
currentParam[k++] = fis->node[ii]->para[j];
anfisPutKalmanParameter2(fis);
squared_error = 0;
for (j = 0; j < fis->trn_data_n; j++) {
/* dispatch inputs */
for (k = 0; k < fis->in_n; k++)
fis->node[k]->value = fis->trn_data[j][k];
/* forward calculation from layer 1 to layer 7 */
anfisForward(fis, fis->in_n, fis->node_n-1);
/* calculate error measure */
squared_error += pow(
fis->trn_data[j][fis->in_n] -
fis->node[fis->node_n-1]->value, 2.0);
}
temp1 = sqrt(squared_error/fis->trn_data_n);
printf("lamda %f err [i-1]: %f err [i]: %f\n",lamda, temperror, temp1);
if (temperror < temp1) {
lamda=lamda*.8;
/* restore params */
k = 0;
for (ii=fis->in_n; ii<fis->node_n-1; ii++)
for (j = 0; j < fis->node[ii]->para_n; j++)
fis->node[ii]->para[j] = currentParam[k++];
}
else
lamda=lamda * 1;
}
}
/* update min. training error if necessary */
if (fis->trn_error[i] < fis->min_trn_error) {
fis->min_trn_error = fis->trn_error[i];
/* record best parameters so far */
for (k = 0; k < fis->para_n; k++)
fis->trn_best_para[k] = fis->para[k];
}
/* update min. checking error if necessary */
if (fis->chk_data_n != 0)
if (fis->chk_error[i] < fis->min_chk_error) {
fis->min_chk_error = fis->chk_error[i];
/* record best parameters so far */
for (k = 0; k < fis->para_n; k++)
fis->chk_best_para[k] = fis->para[k];
}
if (fis->display_error & i>0)
if (fis->chk_data_n != 0){
printf("%4d \t %g \t %g\n", i+1,
fis->trn_error[i], fis->chk_error[i]);
}
else{
printf("cycle: %4d \t error: %g\n", i,
fis->trn_error[i-1]);
}
/* stop training if error goal is reached */
if (fis->min_trn_error <= fis->trn_error_goal) {
fis->actual_epoch_n = i+1;
if (fis->display_error)
printf("\nError goal (%g) reached --> ANFIS training completed at epoch %d.\n\n", fis->trn_error_goal, fis->actual_epoch_n);
return;
}
/* update step size */
fis->ss_array[i] = fis->ss; /* record step size */
if (fis->method==1)
anfisUpdateStepSize(fis, i); /* update step size */
}
FREEARRAY(currentParam);
/* if (fis->display_error)
printf("\nDesignated epoch number reached --> ANFIS training completed at epoch %d.\n\n", fis->epoch_n);*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -