⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 learning.c

📁 模糊逻辑工具箱 模糊逻辑工具箱 模糊逻辑工具箱 模糊逻辑工具箱 模糊逻辑工具箱
💻 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 + -