/*****************************************************************************
FILE : $Source: /projects/higgs1/SNNS/CVS/SNNS/kernel/sources/cc_learn.c,v $
SHORTNAME :
SNNS VERSION : 4.2
PURPOSE : Functions of CC
NOTES :
AUTHOR : Michael Schmalzl, modified by Christian Wehrfritz (PCC)
DATE : 5.2.93
CHANGED BY : Michael Schmalzl, Juergen Gatter
RCS VERSION : $Revision: 2.18 $
LAST CHANGE : $Date: 1998/04/20 11:54:44 $
Copyright (c) 1990-1995 SNNS Group, IPVR, Univ. Stuttgart, FRG
Copyright (c) 1996-1998 SNNS Group, WSI, Univ. Tuebingen, FRG
******************************************************************************/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <memory.h>
#ifdef HAVE_VALUES_H
#include <values.h>
#endif
#include "random.h"
#include "kr_typ.h" /* Kernel Types and Constants */
#include "kr_const.h" /* Constant Declarators for SNNS-Kernel */
#include "kr_def.h" /* Default Values */
#include "kernel.h" /* kernel function prototypes */
#include "kr_mac.h" /* Kernel Macros */
#include "kr_ui.h"
#include "cc_type.h"
#include "cc_mac.h"
#include "cc_learn.ph"
#include "cc_glob.h"
#include "kr_newpattern.h"
#include "cc_modify.h"
#include "cc_prune.h"
#include "cc_display.h"
#include "tacoma_learn.h"
/*****************************************************************************
FUNCTION : cc_initVariables
PURPOSE : read some Parameters and global dates.
NOTES :
UPDATE : 30.03.96 <Juergen Gatter>
******************************************************************************/
krui_err cc_initVariables(float* ParameterInArray,
int StartPattern,int EndPattern)
{
int i;
cc_LayerCorrectnessTest(ParameterInArray,StartPattern,EndPattern);
srand48((long)time(NULL));
/* now read the parameters from the window to global variables */
cc_printOnOff = (int)ParameterInArray[8];
cc_backfittingOnOff = (int)ParameterInArray[18];
cc_MaxSpecialUnitNo = (int)ParameterInArray[12];
cc_modification = (int)ParameterInArray[21];
for (i=0;i<5;i++){
cc_Parameter[i]=ParameterInArray[22+i];
}
cc_fastmode=(int)ParameterInArray[27];
cc_fse=((LEARNING_FUNCTION==BACKPROP)? PARAM3 : 0.1);
KernelErrorCode=cc_InitModificationVariables();
ERROR_CHECK;
KernelErrorCode=cc_TestWhetherParametersAreValid();
ERROR_CHECK;
cc_end=FALSE;
cc_cascade=1;
KernelErrorCode = cc_GetTrainFunctions(LEARNING_FUNCTION);
ERROR_CHECK;
if (NoOfHiddenUnits==0)
KernelErrorCode = cc_calculateNetParameters();
ERROR_CHECK;
KernelErrorCode = cc_generateLayerList();
ERROR_CHECK;
if(strcmp(krui_getUpdateFunc(),"CC_Order")){
return(KRERR_CC_ERROR10);
}
if(strcmp(krui_getInitialisationFunc(),"CC_Weights")){
return(KRERR_CC_ERROR11);
}
return KRERR_NO_ERROR;
}
/*****************************************************************************
FUNCTION : cc_calculateCorrelation
PURPOSE : Calculates the correlation of the pool of candidate units and
returns the high score.
NOTES :
UPDATE : 30.3.96 <Juergen Gatter>
******************************************************************************/
float cc_calculateCorrelation(int StartPattern, int EndPattern, int counter)
{
int s,o,n;
double highScore, unchangedhighScore, scoreBuffer;
float bestSpecialUnitScore = -0.1 ,
bestSpecialUnitUnchangedScore=0.0;
struct Unit *SpecialUnitPtr = NULL,*OutputUnitPtr;
int start, end;
cc_getPatternParameter(StartPattern,EndPattern,&start,&end,&n);
ERROR_CHECK;
if(cc_printOnOff) printf("Cycle %d ",counter);
FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
unchangedhighScore = 0.0;
FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
scoreBuffer = (CorBetweenSpecialActAndOutError[s][o] -
(MeanOutputUnitError[o] * SpecialUnitSumAct[s] )) /
SumSqError;
unchangedhighScore += fabs(scoreBuffer);
SIGN_OF_THE_CORRELATION[s][o] = SIGN(scoreBuffer);
}
highScore = cc_modifyHighScore(SpecialUnitPtr,s,unchangedhighScore);
cc_actualizeGroupHighscores(highScore,s,SpecialUnitPtr);
if(highScore> bestSpecialUnitScore){
bestSpecialUnitScore = highScore;
bestSpecialUnitUnchangedScore = unchangedhighScore;
bestSpecialUnitPtr = SpecialUnitPtr;
}
if(cc_printOnOff) printf("S[%d]: %.4f ",s,unchangedhighScore);
}
if(cc_printOnOff) {
printf("Best : %d:%.4f \n",GET_UNIT_NO(bestSpecialUnitPtr),
bestSpecialUnitScore);
}
return(bestSpecialUnitUnchangedScore);
}
/*****************************************************************************
FUNCTION : cc_GetTrainFunctions
PURPOSE : Assigns the trainings functions.
NOTES :
UPDATE : 10.10.95 <Juergen Gatter>
******************************************************************************/
krui_err cc_GetTrainFunctions(int learnFunc)
{
cc_learningFunction = learnFunc;
cc_propagateOutputUnitsBackward = cc_propagateOutput;
cc_propagateSpecialUnitsBackward = cc_propagateSpecial;
switch(learnFunc) {
case BACKPROP:
cc_SpecialUnitUpdate =
cc_OutputUnitUpdate = BackPropOfflinePart;
break;
case BACKPROP_ONLINE:
cc_SpecialUnitUpdate =
cc_OutputUnitUpdate = OnlineBackPropOfflinePart;
cc_propagateOutputUnitsBackward = cc_propagateOutputOnlineCase;
cc_propagateSpecialUnitsBackward = cc_propagateSpecialOnlineCase;
break;
case QUICKPROP:
cc_SpecialUnitUpdate =
cc_OutputUnitUpdate = QuickPropOfflinePart;
break;
case RPROP:
cc_SpecialUnitUpdate =
cc_OutputUnitUpdate = RPropOfflinePart;
break;
default: CC_ERROR(KRERR_CC_ERROR3);
}
return(KRERR_NO_ERROR);
}
/*****************************************************************************
FUNCTION : cc_trainSpecialUnits
PURPOSE : Trains the special units.
NOTES :
UPDATE : 5.2.93
******************************************************************************/
void cc_trainSpecialUnits(int maxNoOfCovarianceUpdateCycles,
float minCovarianceChange,
int specialPatience,int StartPattern,
int EndPattern,float param1, float param2,
float param3,int MaxSpecialUnitNo)
{
struct Unit* UnitPtr;
struct Link* LinkPtr;
int s;
int counter,start,end,n;
float oldHighScore=0.0,newHighScore;
float Error;
cc_printHeadline("Training of the candidates",LENGTH_HEADLINE);
cc_calculateOutputUnitError(StartPattern,EndPattern);
if (SumSqError==0.0){
Error = cc_getErr(StartPattern,EndPattern); /* calc SumSqError */
if (SumSqError==0.0)
return;
}
for (counter=0;counter<maxNoOfCovarianceUpdateCycles;counter++){
cc_calculateSpecialUnitActivation(StartPattern,EndPattern);
newHighScore = cc_calculateCorrelation(StartPattern,EndPattern,counter);
KernelErrorCode = cc_getPatternParameter(StartPattern, EndPattern,
&start, &end, &n);
ERROR_CHECK_WRC;
(*cc_propagateSpecialUnitsBackward)(start, end, n, counter,
param1, param2, param3);
ERROR_CHECK_WRC;
FOR_ALL_SPECIAL_UNITS(UnitPtr,s){
UnitPtr->bias +=
(*cc_SpecialUnitUpdate)(UnitPtr->bias,
&BIAS_PREVIOUS_SLOPE(UnitPtr),
&BIAS_CURRENT_SLOPE(UnitPtr),
&BIAS_LAST_WEIGHT_CHANGE(UnitPtr),
param1,param2,param3);
FOR_ALL_LINKS(UnitPtr,LinkPtr){
LinkPtr->weight +=
(*cc_SpecialUnitUpdate)(LinkPtr->weight,
&LN_PREVIOUS_SLOPE(LinkPtr),
&LN_CURRENT_SLOPE(LinkPtr),
&LN_LAST_WEIGHT_CHANGE(LinkPtr),
param1, param2, param3);
}
}
cc_initActivationArrays();
if ((counter % specialPatience)==0){
if(fabs(newHighScore-oldHighScore) <
minCovarianceChange*oldHighScore)
return;
else
oldHighScore = newHighScore;
}
}
}
/*****************************************************************************
FUNCTION : cc_trainOutputUnits
PURPOSE : Trains the output units.
NOTES :
UPDATE : 5.2.93
******************************************************************************/
void cc_trainOutputUnits(int maxNoOfErrorUpdateCycles, int backfittPatience,
float minErrorChange,
int outPatience,int StartPattern,int EndPattern,
float param1, float param2, float param3,
float **ParameterOutArray,int *NoOfOutParams)
{
int p,pat,sub,counter=0;
float oldNetError=FLOAT_MAX;
int start,end,n;
struct Unit* UnitPtr;
struct Link* LinkPtr;
int s,dummy;
static float OutParameter[1];
cc_printHeadline("Training of the output units",LENGTH_HEADLINE);
*NoOfOutParams = 1;
*ParameterOutArray = OutParameter;
cc_initOutputUnits();
cc_actualNetSaved=FALSE;
/* compute the necessary sub patterns */
KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
if(KernelErrorCode != KRERR_NO_ERROR)
return;
for (counter=0;counter< maxNoOfErrorUpdateCycles;counter++){
cc_getPatternParameter(StartPattern,EndPattern,&start,&end,&n);
for(p=start; p<=end;p++){
cc_getActivationsForActualPattern(p,start,&pat,&sub);
PROPAGATE_THROUGH_OUTPUT_LAYER(UnitPtr,dummy,p);
(*cc_propagateOutputUnitsBackward)(pat,sub,param1,param2,param3);
}
cc_actualNetSaved=TRUE;
FOR_ALL_OUTPUT_UNITS(UnitPtr,s){
UnitPtr->bias +=
(*cc_OutputUnitUpdate)(UnitPtr->bias,
&BIAS_PREVIOUS_SLOPE(UnitPtr),
&BIAS_CURRENT_SLOPE(UnitPtr),
&BIAS_LAST_WEIGHT_CHANGE(UnitPtr),
param1,param2,param3);
FOR_ALL_LINKS(UnitPtr,LinkPtr){
LinkPtr->weight +=
(*cc_OutputUnitUpdate)(LinkPtr->weight,
&LN_PREVIOUS_SLOPE(LinkPtr),
&LN_CURRENT_SLOPE(LinkPtr),
&LN_LAST_WEIGHT_CHANGE(LinkPtr),
param1,param2,param3);
}
}
NET_ERROR(OutParameter)=cc_getErr(StartPattern,EndPattern);
/* otherways, it's not the actual error */
if(cc_printOnOff) printf("Epoch: %d NetError: %f \n",counter+1,
NET_ERROR(OutParameter));
if ((counter % outPatience)==0){
if(fabs(NET_ERROR(OutParameter)-oldNetError) <
minErrorChange * oldNetError)
return;
else
oldNetError=NET_ERROR(OutParameter);
}
}
}
/*****************************************************************************
FUNCTION : cc_calculateOutputUnitError
PURPOSE : Calculates the error of all output units and stores the result
in the array OutputUnitError
NOTES :
UPDATE : 5.2.93
******************************************************************************/
void cc_calculateOutputUnitError(int StartPattern,int EndPattern)
{
register struct Unit *UnitPtr;
register Patterns out_pat;
register TopoPtrArray topo_ptr;
register int o,p;
int start, end,pat,sub,n;
FOR_ALL_OUTPUT_UNITS(UnitPtr,o)
OUTPUT_UNIT_SUM_ERROR[o] = 0.0;
cc_getPatternParameter(StartPattern,EndPattern,&start,&end,&n);
ERROR_CHECK_WRC;
for(p=start; p<=end;p++){
topo_ptr = topo_ptr_array;
cc_getActivationsForActualPattern(p,start,&pat,&sub);
out_pat = kr_getSubPatData(pat,sub,OUTPUT,NULL);
ERROR_CHECK_WRC;
FOR_ALL_OUTPUT_UNITS(UnitPtr,o) {
CALCULATE_ACTIVATION_AND_OUTPUT(UnitPtr,
(*UnitPtr->act_func)(UnitPtr),p);
OUTPUT_UNIT_SUM_ERROR[o] +=
(OutputUnitError[p][o] =
(UnitPtr->Out.output-(*out_pat++))*
((*UnitPtr->act_deriv_func)(UnitPtr)+cc_fse));
}
}
FOR_ALL_OUTPUT_UNITS(UnitPtr,o)
MeanOutputUnitError[o] = (OUTPUT_UNIT_SUM_ERROR[o] / n);
cc_actualNetSaved=TRUE;
}
/*****************************************************************************
FUNCTION : cc_calculateSpecialUnitActivation
PURPOSE : Calculates the covariance between the output units and the
special units and stores the result the array
CorBetweenSpecialActAndOutError.
NOTES :
UPDATE : 5.2.93
******************************************************************************/
void cc_calculateSpecialUnitActivation(int StartPattern, int EndPattern)
{
register struct Unit *specialUnitPtr,*outputUnitPtr;
register int o,s,p;
int pat,sub;
int start,end,n;
cc_getPatternParameter(StartPattern,EndPattern,&start,&end,&n);
ERROR_CHECK_WRC;
for(p=start; p<=end;p++){
cc_getActivationsForActualPattern(p,start,&pat,&sub);
FOR_ALL_SPECIAL_UNITS(specialUnitPtr,s) {
CALCULATE_ACTIVATION_AND_OUTPUT(specialUnitPtr,
(*specialUnitPtr->act_func) (specialUnitPtr),p);
SpecialUnitSumAct[s] +=
SpecialUnitAct[p][s] = specialUnitPtr->Out.output;
FOR_ALL_OUTPUT_UNITS(outputUnitPtr,o) {
CorBetweenSpecialActAndOutError[s][o] +=
SpecialUnitAct[p][s] * OutputUnitError[p][o];
}
}
}
cc_actualNetSaved=TRUE;
}
/*****************************************************************************
FUNCTION : cc_propagateOutput
PURPOSE : Propagates a pattern backward through the net.
NOTES :
UPDATE : 5.2.93
******************************************************************************/
float cc_propagateOutput(int PatternNo, int sub_pat_no, float param1,
float param2, float param3)
{
struct Link *LinkPtr;
struct Site *site_ptr;
struct Unit *OutputUnitPtr;
Patterns out_pat;
float error,devit;
int dummy;
out_pat = kr_getSubPatData(PatternNo,sub_pat_no,OUTPUT,NULL);
ERROR_CHECK;
FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
devit = OutputUnitPtr->Out.output - *(out_pat++);
error = devit *
((*OutputUnitPtr->act_deriv_func)(OutputUnitPtr) + cc_fse);
BIAS_CURRENT_SLOPE(OutputUnitPtr) += error;
if (UNIT_HAS_DIRECT_INPUTS(OutputUnitPtr)) {
FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
}
}else{
FOR_ALL_SITES_AND_LINKS(OutputUnitPtr,site_ptr,LinkPtr) {
LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
}
}
}
return(0); /* not used anymore, since result isn't valid when used */
}
/*****************************************************************************
FUNCTION : cc_propagateOutputOnlineCase
PURPOSE : Propagates a pattern backward through the net.
NOTES :
UPDATE : 5.2.93
******************************************************************************/
float cc_propagateOutputOnlineCase(int PatternNo, int sub_pat_no,
float eta,float mu,float dummy1)
{
struct Link *LinkPtr;
struct Site *site_ptr;
struct Unit *OutputUnitPtr;
Patterns out_pat;
float error,sum_error,devit;
int dummy;
float lastChange;
sum_error = 0.0;
out_pat = kr_getSubPatData(PatternNo,sub_pat_no,OUTPUT,NULL);
ERROR_CHECK;
FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
devit = OutputUnitPtr->Out.output - *(out_pat++);
sum_error += devit * devit;
error = devit *
((*OutputUnitPtr->act_deriv_func)(OutputUnitPtr) + dummy1);
lastChange = BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr);
OutputUnitPtr->bias -=
((BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr) =
error * eta + lastChange * mu));
if (UNIT_HAS_DIRECT_INPUTS(OutputUnitPtr)) {
FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
lastChange = LN_LAST_WEIGHT_CHANGE(LinkPtr);
LinkPtr->weight -=
((LN_LAST_WEIGHT_CHANGE(LinkPtr) =
error*LinkPtr->to->Out.output*eta+lastChange*mu));
}
}else{
FOR_ALL_SITES_AND_LINKS(OutputUnitPtr,site_ptr,LinkPtr) {
lastChange = LN_LAST_WEIGHT_CHANGE(LinkPtr);
LinkPtr->weight -=
((LN_LAST_WEIGHT_CHANGE(LinkPtr) =
error*LinkPtr->to->Out.output*eta+lastChange*mu));
}
}
}
return(sum_error);
}
/*****************************************************************************
FUNCTION : cc_propagateSpecial
PURPOSE : Propagation in Case of Special Units, no BackProp
NOTES :
UPDATE : 30.3.96 <Juergen Gatter>
******************************************************************************/
krui_err cc_propagateSpecial(int start,int end,int n,int counter,
float param1, float param2,float param3)
{
float change=0.0,actPrime;
int s,o,p,pat,sub;
struct Unit *SpecialUnitPtr,*OutputUnitPtr;
struct Link *LinkPtr;
for(p=start; p<=end;p++){
cc_getActivationsForActualPattern(p,start,&pat,&sub);
FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
change = 0.0;
SpecialUnitPtr->act = SpecialUnitAct[p][s];
actPrime = (*SpecialUnitPtr->act_deriv_func)(SpecialUnitPtr);
FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o)
if(UNITS_IN_SAME_GROUP(s,o)){
change -= SIGN_OF_THE_CORRELATION[s][o] *
(OutputUnitError[p][o]-MeanOutputUnitError[o]);
}
change *= actPrime/SumSqError;
BIAS_CURRENT_SLOPE(SpecialUnitPtr) += change;
FOR_ALL_LINKS(SpecialUnitPtr,LinkPtr)
LN_CURRENT_SLOPE(LinkPtr) += change * LinkPtr->to->Out.output;
}
}
cc_actualNetSaved=TRUE;
return(KRERR_NO_ERROR);
}
/*****************************************************************************
FUNCTION : cc_propagateSpecialOnlineCase
PURPOSE : Propagation in Case of Special Units for BackProp
NOTES :
UPDATE : 30.3.96 <Juergen Gatter>
******************************************************************************/
krui_err cc_propagateSpecialOnlineCase(int start,int end,int n,int counter,
float eta, float mu, float dummy)
{
float change=0.0,actPrime;
int s,o,p,pat,sub;
struct Unit *SpecialUnitPtr,*OutputUnitPtr;
struct Link *LinkPtr;
float lastChange;
for(p=start; p<=end;p++){
cc_getActivationsForActualPattern(p,start,&pat,&sub);
FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
change = 0.0;
SpecialUnitPtr->act = SpecialUnitAct[p][s];
actPrime = (*SpecialUnitPtr->act_deriv_func)(SpecialUnitPtr);
FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o)
if(UNITS_IN_SAME_GROUP(s,o)){
change += SIGN_OF_THE_CORRELATION[s][o] *
(OutputUnitError[p][o]-MeanOutputUnitError[o]);
}
change *= actPrime/SumSqError;
lastChange = BIAS_LAST_WEIGHT_CHANGE(SpecialUnitPtr);
SpecialUnitPtr->bias +=
(BIAS_LAST_WEIGHT_CHANGE(SpecialUnitPtr) =
(change * eta + lastChange * mu));
FOR_ALL_LINKS(SpecialUnitPtr,LinkPtr) {
lastChange = LN_LAST_WEIGHT_CHANGE(LinkPtr);
LinkPtr->weight +=
(LN_LAST_WEIGHT_CHANGE(LinkPtr) =
change*LinkPtr->to->Out.output*eta+lastChange*mu);
}
}
}
cc_actualNetSaved=TRUE;
return(KRERR_NO_ERROR);
}
/*****************************************************************************
FUNCTION : LEARN_CC
PURPOSE : The main routine of CC
NOTES :
UPDATE : 5.2.93
******************************************************************************/
krui_err LEARN_CC(int StartPattern, int EndPattern,
float *ParameterInArray, int NoOfInParams,
float **ParameterOutArray, int *NoOfOutParams)
{
NetLearnAlgorithm = CC;
return(LEARN_CasCor(StartPattern,EndPattern,ParameterInArray,NoOfInParams,
ParameterOutArray,NoOfOutParams));
}
/*****************************************************************************
FUNCTION : LEARN_CasCor
PURPOSE : The main learn routine of CC
NOTES :
UPDATE : 5.2.93
******************************************************************************/
krui_err LEARN_CasCor(int StartPattern, int EndPattern,
float *ParameterInArray, int NoOfInParams,
float **ParameterOutArray, int *NoOfOutParams)
{
static int GroupNo;
static float LeTe;
int TempErrorCode; /* Used by the macro ERROR_CHECK_WITH_MEM_DEALLOC */
if(cc_allButtonIsPressed == 1) {
KernelErrorCode = cc_initVariables(ParameterInArray, StartPattern,
EndPattern);
ERROR_CHECK;
}
if(cc_end){
cc_deleteAllSpecialUnits();
return(cc_freeStorage(StartPattern,EndPattern,0));
}
cc_allocateStorage(StartPattern,EndPattern,MAX_SPECIAL_UNIT_NUMBER);
ERROR_CHECK_WITH_MEMORY_DEALLOCATION;
/* it's easier to delete and reconstruct the Units, than to change them */
KernelErrorCode = cc_deleteAllSpecialUnits();
ERROR_CHECK_WITH_MEMORY_DEALLOCATION;
KernelErrorCode = cc_generateSpecialUnits(SPECIAL_FUNCTION_TYPE);
ERROR_CHECK_WITH_MEMORY_DEALLOCATION;
KernelErrorCode = cc_initSpecialUnitLinks();
ERROR_CHECK_WITH_MEMORY_DEALLOCATION;
if(cc_storageFree){ CC_ERROR(KRERR_CC_ERROR2); }
/* If this is the first run, train the output connections */
if (NoOfHiddenUnits<1) {
if((OUT_PATIEN != 0) && (MAX_NO_ERROR_UPDATE_CYCLES != 0)) {
cc_trainOutputUnits(MAX_NO_ERROR_UPDATE_CYCLES, BACKFITT_PATIENCE,
MINIMAL_ERROR_CHANGE, OUT_PATIEN,
StartPattern, EndPattern, PARAM1, PARAM2,
PARAM3, ParameterOutArray, NoOfOutParams);
}
}
/* compute the selection criterion before the new hidden is installed */
if (CC_PRUNE_ONOFF) {
LeTe=cc_getPruningError(PRUNE_FUNC,StartPattern,EndPattern,1);
}
/* train the candidates */
if(cc_test(StartPattern,EndPattern,MAX_PIXEL_ERR) == CONTINUE_LEARNING) {
if((SPEC_PATIENCE != 0) && (MAX_NO_OF_COVAR_UPDATE_CYCLES != 0)) {
cc_trainSpecialUnits(MAX_NO_OF_COVAR_UPDATE_CYCLES,
MIN_COVAR_CHANGE,SPEC_PATIENCE,
StartPattern,EndPattern,
PARAM4,PARAM5,PARAM6,MAX_SPECIAL_UNIT_NUMBER);
}
}else { /* STOP_LEARNING */
cc_end = TRUE;
return(cc_freeStorage(StartPattern,EndPattern,0));
}
cc_actualNetSaved=FALSE;
/* install new hidden unit(s) */
for (GroupNo=0;GroupNo<cc_calculateNoOfNewUnits();GroupNo++){
if((SPEC_PATIENCE != 0) && (MAX_NO_OF_COVAR_UPDATE_CYCLES != 0)) {
KernelErrorCode = cc_generateHiddenUnit(GroupNo);
ERROR_CHECK_WITH_MEMORY_DEALLOCATION;
}
}
/* retrain the output connections */
if((OUT_PATIEN != 0) && (MAX_NO_ERROR_UPDATE_CYCLES != 0)) {
cc_trainOutputUnits(MAX_NO_ERROR_UPDATE_CYCLES, BACKFITT_PATIENCE,
MINIMAL_ERROR_CHANGE, OUT_PATIEN, StartPattern,
EndPattern, PARAM1, PARAM2, PARAM3,
ParameterOutArray,NoOfOutParams);
}
/* prune the new hidden unit and retrain the output connections again */
if (CC_PRUNE_ONOFF) {
cc_pruneNet(StartPattern, EndPattern, PRUNE_FUNC);
if((OUT_PATIEN != 0) && (MAX_NO_ERROR_UPDATE_CYCLES != 0)) {
cc_trainOutputUnits(MAX_NO_ERROR_UPDATE_CYCLES, BACKFITT_PATIENCE,
MINIMAL_ERROR_CHANGE,
OUT_PATIEN,StartPattern,EndPattern,PARAM1,
PARAM2,PARAM3,ParameterOutArray,NoOfOutParams);
}
if (cc_getPruningError(PRUNE_FUNC,StartPattern,EndPattern,2)>LeTe) {
cc_remove_Unit();
}
}
cc_deleteAllSpecialUnits();
cc_allButtonIsPressed = 0;
return(cc_freeStorage(StartPattern,EndPattern,0));
}
/*****************************************************************************
FUNCTION : void cc_generateLayerList
PURPOSE : generates list with data of the layers
NOTES :
UPDATE : 20.11.95 <Juergen Gatter>
******************************************************************************/
krui_err cc_generateLayerList(void)
{
int i;
struct Unit* UnitPtr;
FREE_IF_USED(ListOfLayers); /* we allocate a new list */
CALLOC_ERRORCHECK(ListOfLayers,MINIMAL_LAYERLIST_SIZE+NoOfLayers,
Layer_Type);
ListOfLayers[0].NoOfUnitsInLayer = NoOfInputUnits;
ListOfLayers[0].xPosFirstRow = cc_hiddenXminPos;
SizeOfLayerlist = MINIMAL_LAYERLIST_SIZE+NoOfLayers;
for (i=1;i<SizeOfLayerlist;i++){
ListOfLayers[i].xPosFirstRow = MAX_POS;
ListOfLayers[i].NoOfUnitsInLayer = 0;
}
/* calculating data for the layers */
FOR_ALL_UNITS(UnitPtr){
if (IS_HIDDEN_UNIT(UnitPtr)){
if(CC_LAYER_NO(UnitPtr) >=SizeOfLayerlist)
printf("\n\n\nInternal error with layers\n\n\n");
else{
ListOfLayers[CC_LAYER_NO(UnitPtr)].NoOfUnitsInLayer++;
ListOfLayers[CC_LAYER_NO(UnitPtr)].xPosFirstRow =
MIN(ListOfLayers[CC_LAYER_NO(UnitPtr)].xPosFirstRow,
GET_UNIT_XPOS(UnitPtr));
}
}
}
return(KRERR_NO_ERROR);
}
/*****************************************************************************
FUNCTION : void cc_actualizeLayerList
PURPOSE : changes the Size of the LayerList, iff needed.
NOTES : the List have to be generated with cc_generateLayerList.
UPDATE : 30.03.96 <Juergen Gatter>
******************************************************************************/
krui_err cc_actualizeLayerlist(struct Unit* UnitPtr, int LayerNo)
{
int i;
struct CC_LAYER* Newlist;
if (LayerNo > NoOfLayers){
NoOfLayers++;
if (NoOfLayers >= SizeOfLayerlist-1){ /* then double size */
CALLOC_ERRORCHECK(Newlist,SizeOfLayerlist * 2,struct CC_LAYER);
for(i=0;i<SizeOfLayerlist;i++)
Newlist[i]=ListOfLayers[i];
for(i=SizeOfLayerlist;i<2*SizeOfLayerlist;i++)
Newlist[i].NoOfUnitsInLayer=0;
SizeOfLayerlist *= 2;
free(ListOfLayers);
ListOfLayers=Newlist;
}
ListOfLayers[NoOfLayers].NoOfUnitsInLayer=1;
ListOfLayers[NoOfLayers].xPosFirstRow=
FIRST_ROW_NEXT_LAYER(NoOfLayers-1);
}else
ListOfLayers[LayerNo].NoOfUnitsInLayer++;
return(KRERR_NO_ERROR);
}
/*****************************************************************************
FUNCTION : krui_err cc_generateHiddenUnit
PURPOSE : Generates a new hidden unit
NOTES :
UPDATE : 5.2.93
******************************************************************************/
krui_err cc_generateHiddenUnit(int GroupNo)
{
int LayerOfNewUnit;
int CurrentUnit,dummy,NewHiddenUnit;
struct Unit *HiddenUnitPtr,*OutputUnitPtr;
bestSpecialUnitPtr=cc_getModifiedBestSpecialUnitPtr(GroupNo);
LayerOfNewUnit = CC_LAYER_NO(bestSpecialUnitPtr);
KernelErrorCode=cc_actualizeLayerlist(bestSpecialUnitPtr,LayerOfNewUnit);
ERROR_CHECK;
LastInsertedHiddenUnit=
CurrentUnit =
KernelErrorCode =
kr_copyUnit(ONLY_INPUTS,GET_UNIT_NO(bestSpecialUnitPtr));
if(KernelErrorCode < 0) return(KernelErrorCode);
KernelErrorCode = KRERR_NO_ERROR;
KernelErrorCode = kr_unitSetTType(CurrentUnit,HIDDEN);
ERROR_CHECK;
HiddenUnitPtr = kr_getUnitPtr(CurrentUnit);
ERROR_CHECK;
CC_SET_LAYER_NO(HiddenUnitPtr,LayerOfNewUnit);
KernelErrorCode = cc_setHiddenUnit(HiddenUnitPtr,LayerOfNewUnit);
ERROR_CHECK;
KernelErrorCode = krui_setCurrentUnit(CurrentUnit);
ERROR_CHECK;
NewHiddenUnit = CurrentUnit;
/* generate links between output unit and new hidden unit */
FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
CurrentUnit = GET_UNIT_NO(OutputUnitPtr);
KernelErrorCode = krui_setCurrentUnit(CurrentUnit);
ERROR_CHECK;
KernelErrorCode = krui_createLink(NewHiddenUnit,0.0);
ERROR_CHECK;
} /* and change its Layer if necessary */
KernelErrorCode = kr_topoSort(TOPOLOGICAL_CC);
ERROR_CHECK;
KernelErrorCode = cc_setPointers();
ERROR_CHECK;
NetModified = FALSE;
return(KRERR_NO_ERROR);
}
/*****************************************************************************
FUNCTION : cc_test
PURPOSE : Tests whether to continue learning or not.
NOTES :
UPDATE : 5.2.93
******************************************************************************/
int cc_test(int StartPattern, int EndPattern, float maxPixelError)
{
int p,sub,pat,o;
int start, end,n,dummy;
Patterns out_pat;
struct Unit *unitPtr;
/* compute the necessary sub patterns */
KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
ERROR_CHECK;
cc_getPatternParameter(StartPattern,EndPattern,&start,&end,&n);
for(p=start; p<=end;p++){
cc_getActivationsForActualPattern(p,start,&pat,&sub);
PROPAGATE_THROUGH_OUTPUT_LAYER(unitPtr,dummy,p);
out_pat = kr_getSubPatData(pat,sub,OUTPUT,NULL);
FOR_ALL_OUTPUT_UNITS(unitPtr,o){
if((fabs(*(out_pat++) - unitPtr->Out.output))>maxPixelError){
return(CONTINUE_LEARNING);
}
}
}
cc_actualNetSaved=TRUE;
return(STOP_LEARNING);
}
/*****************************************************************************
FUNCTION : cc_generateSpecialUnits
PURPOSE : Generates the special units
NOTES :
UPDATE : 5.2.93
******************************************************************************/
krui_err cc_generateSpecialUnits(int type)
{
int i,selector,calcLayerNo;
struct Unit *UnitPtr;
struct Unit *SpecUnitPtr;
int CurrentUnit;
cc_MakeMiscCalculationsForModifications();
for(i=0;i<cc_MaxSpecialUnitNo;i++) {
selector = ((type==RANDOM) ? i % (NO_OF_ACT_FUNCS - 1) : type);
KernelErrorCode =
kr_unitSetTType(CurrentUnit=kr_makeDefaultUnit(),SPECIAL);
ERROR_CHECK;
KernelErrorCode = krui_setUnitActFunc(CurrentUnit,
cc_actFuncArray[selector]);
ERROR_CHECK;
SpecUnitPtr = kr_getUnitPtr(CurrentUnit);
ERROR_CHECK;
KernelErrorCode = krui_setCurrentUnit(CurrentUnit);
ERROR_CHECK;
KernelErrorCode = cc_calculateConnections(i);
ERROR_CHECK;
calcLayerNo=0;
FOR_ALL_UNITS(UnitPtr){
if((IS_INPUT_UNIT(UnitPtr) || IS_HIDDEN_UNIT(UnitPtr)) &&
cc_UnitsHaveToBeConnected(i,UnitPtr) &&
UNIT_IN_USE(UnitPtr)) {
if (CC_LAYER_NO(UnitPtr) > calcLayerNo)
calcLayerNo = CC_LAYER_NO(UnitPtr);
KernelErrorCode =
krui_createLink(GET_UNIT_NO(UnitPtr),
cc_generateRandomNo(CC_MAX_VALUE));
ERROR_CHECK;
}
}
CC_SET_LAYER_NO(SpecUnitPtr,calcLayerNo+1);
}
KernelErrorCode = kr_topoSort(TOPOLOGICAL_CC);
ERROR_CHECK;
KernelErrorCode = cc_setPointers();
ERROR_CHECK;
cc_setSpecialUnits(cc_outputXMax+2);
return(KRERR_NO_ERROR);
}
/*****************************************************************************
FUNCTION : TEST_CasCor
PURPOSE : main routine for the test of Cascade Correlation nets
RETURNS : kernel error code
NOTES : Output Parameters: 1 : error of the network (sum of all cycles)
UPDATE : 17.01.96 <Juergen Gatter>
******************************************************************************/
krui_err TEST_CasCor(int start_pattern, int end_pattern,
float *parameterInArray, int NoOfInParams,
float **parameterOutArray, int *NoOfOutParams)
{
int saved_cc_fastmode;
static float OutParameter[1];
KernelErrorCode = KRERR_NO_ERROR; /* reset return code */
if (NoOfInParams < 1) { /* Not enough input parameters */
KernelErrorCode = KRERR_PARAMETERS;
return (KernelErrorCode);
}
*NoOfOutParams = 1; /* One return value is available (the
learning error) */
*parameterOutArray = OutParameter; /* set the output parameter reference */
saved_cc_fastmode = cc_fastmode;
cc_fastmode = FALSE;
NET_ERROR(OutParameter) = cc_getErr(start_pattern, end_pattern);
cc_fastmode = saved_cc_fastmode;
cc_actualNetSaved = FALSE;
return (KernelErrorCode);
}
syntax highlighted by Code2HTML, v. 0.9.1