Initial import
git-svn-id: http://moon:8086/svn/software/trunk/libsrc/nn@1 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -0,0 +1,909 @@
|
||||
/**********************************************************************
|
||||
* nnet.c
|
||||
*
|
||||
* (C) 2000 J. Ahrensfeld
|
||||
*
|
||||
**********************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "nnfile.h"
|
||||
#include "nntypes.h"
|
||||
#include "nnet.h"
|
||||
|
||||
/**********************************************************************/
|
||||
//#define COOL_FEEDFORWARD
|
||||
//#define COOL_BACKPROP
|
||||
|
||||
/**********************************************************************/
|
||||
char *unitStr[] =
|
||||
{
|
||||
"Bias", "Input", "Hidden", "Output"
|
||||
};
|
||||
|
||||
/**********************************************************************/
|
||||
UINT32 NetInit(struct _sNNET *pObj, NETFILE *pNetData, UINT32 netID)
|
||||
{
|
||||
UINT32 i, j, k, layCnt, numUnits;
|
||||
|
||||
pObj->nUnits = 0;
|
||||
pObj->ID = netID;
|
||||
pObj->pUnit = NULL;
|
||||
pObj->pLayer = NULL;
|
||||
pObj->nLayers = 0;
|
||||
pObj->sse = 0.0;
|
||||
pObj->pInputID = 0;
|
||||
pObj->pHiddenID = 0;
|
||||
pObj->pOutputID = 0;
|
||||
pObj->nIn = 0;
|
||||
pObj->nOut = 0;
|
||||
pObj->nHidden = 0;
|
||||
pObj->nnType = pNetData->nntype;
|
||||
pObj->initwrange = pNetData->initwrange;
|
||||
|
||||
pObj->nLayers = 2 + pNetData->nHiddenLayers;
|
||||
|
||||
pObj->pLayer = (LAYER*)nnMalloc(pObj->pLayer, pObj->nLayers*sizeof(LAYER));
|
||||
|
||||
layCnt = 0;
|
||||
srand(12345);
|
||||
rand((UINT16)time(NULL));
|
||||
|
||||
/* Init Units */
|
||||
NetAddUnit(pObj, UTYPE_BIAS, 0); /* Bias Unit has index 0 */
|
||||
|
||||
for(i=0; i < (UINT32)pNetData->LInfo[0].nNeurons; i++)
|
||||
NetAddUnit(pObj, UTYPE_INPUT, 0); /* Input Units */
|
||||
|
||||
for(layCnt++; layCnt < pObj->nLayers-1; layCnt++)
|
||||
for(i=0; i < (UINT32)pNetData->LInfo[layCnt].nNeurons; i++)
|
||||
NetAddUnit(pObj, UTYPE_HIDDEN, pNetData->LInfo[layCnt].NeuronType);/* Hidden Units */
|
||||
|
||||
for(i=0; i < (UINT32)pNetData->LInfo[layCnt].nNeurons; i++)
|
||||
NetAddUnit(pObj, UTYPE_OUTPUT, pNetData->LInfo[layCnt].NeuronType); /* Output Units */
|
||||
|
||||
j = 0;
|
||||
for(i=0; i < pObj->nLayers; i++)
|
||||
{
|
||||
numUnits = pNetData->LInfo[i].nNeurons;
|
||||
if (i==0)
|
||||
numUnits++; // +1 for bias unit
|
||||
|
||||
LayerInit(&pObj->pLayer[i], &pObj->pUnit[j], numUnits, i);
|
||||
j += numUnits;
|
||||
}
|
||||
|
||||
for(k=0; k < pObj->nUnits; k++)
|
||||
{
|
||||
pObj->pUnit[k].ppRecurr = (FLOAT64**)realloc(pObj->pUnit[k].ppRecurr, pObj->nUnits*sizeof(FLOAT64*));
|
||||
pObj->pUnit[k].ppRecurrOld = (FLOAT64**)realloc(pObj->pUnit[k].ppRecurrOld, pObj->nUnits*sizeof(FLOAT64*));
|
||||
for (i=0; i < pObj->nUnits; i++)
|
||||
{
|
||||
pObj->pUnit[k].ppRecurr[i] = (FLOAT64*)malloc(pObj->nUnits*sizeof(FLOAT64));
|
||||
pObj->pUnit[k].ppRecurrOld[i] = (FLOAT64*)malloc(pObj->nUnits*sizeof(FLOAT64));
|
||||
memset(pObj->pUnit[k].ppRecurr[i], 0, (pObj->nUnits)*sizeof(FLOAT64));
|
||||
memset(pObj->pUnit[k].ppRecurrOld[i], 0, (pObj->nUnits)*sizeof(FLOAT64));
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetWire(struct _sNNET *pObj, UINT32 nnType)
|
||||
{
|
||||
UINT32 layer, i, j, firstUnitInLayer_i, firstUnitInLayer_j;
|
||||
|
||||
|
||||
switch(nnType)
|
||||
{
|
||||
case NNTYPE_MLP:
|
||||
|
||||
/* Wire bias unit */
|
||||
layer=0;
|
||||
for(j=pObj->pLayer[layer].nUnits; j < pObj->nUnits; j++)
|
||||
NetAddConnection(pObj,0, j);
|
||||
|
||||
/* Wire input units */
|
||||
firstUnitInLayer_i = 1;
|
||||
for (i=0; i < pObj->pLayer[layer].nUnits-1; i++)
|
||||
{
|
||||
firstUnitInLayer_j = pObj->pLayer[layer+1].ppUnit[0]->globalUnitID;
|
||||
for(j=0; j < pObj->pLayer[layer+1].nUnits; j++)
|
||||
{
|
||||
NetAddConnection(pObj,i+firstUnitInLayer_i, j+firstUnitInLayer_j);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Wire hidden units */
|
||||
layer++;
|
||||
for (layer; layer < pObj->nLayers-1; layer++)
|
||||
{
|
||||
firstUnitInLayer_i = pObj->pLayer[layer].ppUnit[0]->globalUnitID;
|
||||
for (i=0; i < pObj->pLayer[layer].nUnits; i++)
|
||||
{
|
||||
firstUnitInLayer_j = pObj->pLayer[layer+1].ppUnit[0]->globalUnitID;
|
||||
for(j=0; j < pObj->pLayer[layer+1].nUnits; j++)
|
||||
{
|
||||
NetAddConnection(pObj,i+firstUnitInLayer_i, j+firstUnitInLayer_j);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NNTYPE_RECURRENT:
|
||||
|
||||
/* Wire bias unit */
|
||||
/* Wire input units */
|
||||
firstUnitInLayer_i = 1;
|
||||
for (i=0; i < pObj->pLayer[0].nUnits; i++)
|
||||
{
|
||||
for(j=pObj->pLayer[0].nUnits; j < pObj->nUnits; j++)
|
||||
{
|
||||
NetAddConnection(pObj,i, j);
|
||||
}
|
||||
|
||||
}
|
||||
/* Wire hidden units */
|
||||
for (i=pObj->pLayer[0].nUnits; i < pObj->nUnits; i++)
|
||||
{
|
||||
for(j=pObj->pLayer[0].nUnits; j < pObj->nUnits; j++)
|
||||
{
|
||||
NetAddConnection(pObj,i, j);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetFree(struct _sNNET *pObj)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
for (i=0; i < pObj->nUnits; i++)
|
||||
UnitFree(&pObj->pUnit[i]);
|
||||
|
||||
for (i=0; i < pObj->nLayers; i++)
|
||||
LayerFree(&pObj->pLayer[i]);
|
||||
|
||||
nnFree(pObj->pUnit);
|
||||
nnFree(pObj->pLayer);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetAddUnit(struct _sNNET *pObj, UINT32 unitType, UINT32 FType)
|
||||
{
|
||||
UINT32 uid;
|
||||
|
||||
uid = pObj->nUnits;
|
||||
pObj->pUnit = (UNIT*)realloc(pObj->pUnit, (uid+1)*sizeof(UNIT));
|
||||
|
||||
switch(unitType)
|
||||
{
|
||||
case UTYPE_INPUT:
|
||||
pObj->pInputID = (UINT32*)realloc(pObj->pInputID, (pObj->nIn+1)*sizeof(UINT32));
|
||||
pObj->pInputID[pObj->nIn] = uid;
|
||||
pObj->nIn++;
|
||||
break;
|
||||
|
||||
case UTYPE_HIDDEN:
|
||||
pObj->pHiddenID = (UINT32*)realloc(pObj->pHiddenID, (pObj->nHidden+1)*sizeof(UINT32));
|
||||
pObj->pHiddenID[pObj->nHidden] = uid;
|
||||
pObj->nHidden++;
|
||||
break;
|
||||
|
||||
case UTYPE_OUTPUT:
|
||||
pObj->pOutputID = (UINT32*)realloc(pObj->pOutputID, (pObj->nOut+1)*sizeof(UINT32));
|
||||
pObj->pOutputID[pObj->nOut] = uid;
|
||||
pObj->nOut++;
|
||||
break;
|
||||
}
|
||||
|
||||
UnitInit(&pObj->pUnit[uid], unitType, FType, uid);
|
||||
pObj->nUnits++;
|
||||
|
||||
return uid;
|
||||
}
|
||||
|
||||
void NetPrint(struct _sNNET *pObj)
|
||||
{
|
||||
UINT32 layer, i, j, id, nAxonTo, firstUnitInLayer_i;
|
||||
|
||||
printf("Connection Table\n");
|
||||
|
||||
/* Wire hidden units */
|
||||
for (layer=0; layer < pObj->nLayers; layer++)
|
||||
{
|
||||
firstUnitInLayer_i = pObj->pLayer[layer].ppUnit[0]->globalUnitID;
|
||||
printf("*** LAYER %d ***\n",layer);
|
||||
for (i=0; i < pObj->pLayer[layer].nUnits; i++)
|
||||
{
|
||||
id = pObj->pUnit[i+firstUnitInLayer_i].globalUnitID;
|
||||
nAxonTo = pObj->pUnit[id].nAxonTo;
|
||||
if (!nAxonTo)
|
||||
continue;
|
||||
printf("Axon of %s unit %d.%d (ID #%d) connected to \n",unitStr[pObj->pUnit[id].UType],pObj->pUnit[id].layerID,pObj->pUnit[id].unitID, id);
|
||||
|
||||
for (j=0; j < nAxonTo; j++)
|
||||
{
|
||||
id = pObj->pUnit[i+firstUnitInLayer_i].pAxonTo[j].unitID;
|
||||
printf("%s unit %d.%d (ID #%d)\n",unitStr[pObj->pUnit[id].UType],pObj->pUnit[id].layerID,pObj->pUnit[id].unitID,id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
UINT32 LayerInit(struct _sLAYER *pObj, struct _sUNIT *pUnit, UINT32 nUnits, UINT32 LayID)
|
||||
{
|
||||
UINT32 i;
|
||||
pObj->ID = LayID;
|
||||
pObj->nUnits = nUnits;
|
||||
|
||||
pObj->ppUnit = (UNIT**) malloc(pObj->nUnits*sizeof(UNIT*));
|
||||
|
||||
for(i=0; i < pObj->nUnits; i++)
|
||||
{
|
||||
pUnit[i].layerID = LayID;
|
||||
pUnit[i].unitID = i;
|
||||
pObj->ppUnit[i] = &pUnit[i];
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 LayerFree(struct _sLAYER *pObj)
|
||||
{
|
||||
free(pObj->ppUnit);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
UINT32 UnitInit(struct _sUNIT *pObj, UINT32 type, UINT32 FType, UINT32 ID)
|
||||
{
|
||||
pObj->globalUnitID = ID;
|
||||
pObj->layerID = 0;
|
||||
pObj->unitID = 0;
|
||||
pObj->UType = type;
|
||||
|
||||
pObj->nAxonTo = 0;
|
||||
pObj->nWeights = 0;
|
||||
|
||||
pObj->pAxonFrom = (UINT32*)malloc(sizeof(UINT32));
|
||||
pObj->pAxonTo = (WTINFO*)malloc(sizeof(WTINFO));
|
||||
pObj->pWeight = (FLOAT64*)malloc(sizeof(FLOAT64));
|
||||
pObj->pSlope = (FLOAT64*)malloc(sizeof(FLOAT64));
|
||||
pObj->pdWeight = (FLOAT64*)malloc(sizeof(FLOAT64));
|
||||
pObj->ppRecurr = (FLOAT64**)malloc(sizeof(FLOAT64*));
|
||||
*pObj->ppRecurr = (FLOAT64*)malloc(sizeof(FLOAT64));
|
||||
pObj->ppRecurrOld = (FLOAT64**)malloc(sizeof(FLOAT64*));
|
||||
*pObj->ppRecurrOld = (FLOAT64*)malloc(sizeof(FLOAT64));
|
||||
|
||||
*pObj->pAxonFrom = UNIT_ID_INPUT;
|
||||
pObj->pAxonTo->unitID = UNIT_ID_OUTPUT;
|
||||
*pObj->pWeight = 1.0;
|
||||
*pObj->pSlope = 0.0;
|
||||
*pObj->pdWeight = 0.0;
|
||||
**pObj->ppRecurr = 0.12345;
|
||||
**pObj->ppRecurrOld = 0.12345;
|
||||
|
||||
pObj->net = 0.0;
|
||||
pObj->error = 0.0;
|
||||
pObj->delta = 0.0;
|
||||
pObj->axon = 0.0;
|
||||
pObj->lastAxon = 0.0;
|
||||
|
||||
pObj->F = 0;
|
||||
pObj->Fd = 0;
|
||||
pObj->FType = 0;
|
||||
|
||||
if (type==UTYPE_BIAS)
|
||||
{
|
||||
pObj->axon = 1.0;
|
||||
pObj->lastAxon = pObj->axon;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (type == UTYPE_INPUT)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
UnitSetFunc(pObj, FType);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 UnitSetFunc(struct _sUNIT *pObj, UINT32 FuncType)
|
||||
{
|
||||
switch(FuncType)
|
||||
{
|
||||
case Lin:
|
||||
pObj->F = Linear;
|
||||
pObj->Fd = dLinear;
|
||||
pObj->FType = Lin;
|
||||
break;
|
||||
|
||||
case Tanh:
|
||||
pObj->F = Tanh2;
|
||||
pObj->Fd = dTanh;
|
||||
pObj->FType = Tanh;
|
||||
break;
|
||||
|
||||
case ASig:
|
||||
pObj->F = ASigmoid;
|
||||
pObj->Fd = dSigmoid;
|
||||
pObj->FType = ASig;
|
||||
break;
|
||||
|
||||
case SSig:
|
||||
pObj->F = SSigmoid;
|
||||
pObj->Fd = dSSigmoid;
|
||||
pObj->FType = SSig;
|
||||
break;
|
||||
|
||||
case Sig:
|
||||
pObj->F = Sigmoid;
|
||||
pObj->Fd = dSigmoid;
|
||||
pObj->FType = Sig;
|
||||
break;
|
||||
|
||||
case FSig:
|
||||
pObj->F = FSigmoid;
|
||||
pObj->Fd = dFSigmoid;
|
||||
pObj->FType = FSig;
|
||||
break;
|
||||
|
||||
default:
|
||||
pObj->F = Sigmoid;
|
||||
pObj->Fd = dSigmoid;
|
||||
pObj->FType = Sig;
|
||||
break;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetAddConnection(struct _sNNET *pObj, UINT32 ID_i, UINT32 ID_j)
|
||||
{
|
||||
UINT32 *pFrom = NULL, i, k;
|
||||
FLOAT64 *pWeight = NULL, *pdWeight = NULL;
|
||||
WTINFO *pTo = NULL;
|
||||
|
||||
UNIT *pUnit_i, *pUnit_j;
|
||||
|
||||
if (ID_j==0 || ID_j >= pObj->nUnits)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (ID_i >= pObj->nUnits)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
pUnit_i = &pObj->pUnit[ID_i];
|
||||
pUnit_j = &pObj->pUnit[ID_j];
|
||||
|
||||
for(i=0; i < pUnit_i->nAxonTo; i++)
|
||||
{
|
||||
if (pUnit_i->pAxonTo[i].unitID == ID_j)
|
||||
{
|
||||
printf("Axon of unit #%d already connected to unit #%d\n",ID_i,ID_j);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unit j */
|
||||
pUnit_j->pAxonFrom = realloc(pUnit_j->pAxonFrom, (pUnit_j->nWeights + 1)*sizeof(UINT32));
|
||||
pUnit_j->pWeight = realloc(pUnit_j->pWeight,(pUnit_j->nWeights + 1)*sizeof(FLOAT64));
|
||||
pUnit_j->pSlope = realloc(pUnit_j->pSlope,(pUnit_j->nWeights + 1)*sizeof(FLOAT64));
|
||||
pUnit_j->pdWeight = realloc(pUnit_j->pdWeight,(pUnit_j->nWeights + 1)*sizeof(FLOAT64));
|
||||
|
||||
pUnit_j->pAxonFrom[pUnit_j->nWeights] = pUnit_i->globalUnitID;
|
||||
pUnit_j->pWeight[pUnit_j->nWeights] = 2.0*(0.5 - (FLOAT64)rand()/(FLOAT64)RAND_MAX)*pObj->initwrange;
|
||||
pUnit_j->pdWeight[pUnit_j->nWeights] = 0.0;
|
||||
pUnit_j->pSlope[pUnit_j->nWeights] = 0.0;
|
||||
|
||||
/* Unit i */
|
||||
pUnit_i->pAxonTo = realloc(pUnit_i->pAxonTo, (pUnit_i->nAxonTo + 1)*sizeof(WTINFO));
|
||||
pUnit_i->pAxonTo[pUnit_i->nAxonTo].unitID = pUnit_j->globalUnitID;
|
||||
pUnit_i->pAxonTo[pUnit_i->nAxonTo].weightID = pUnit_j->nWeights;
|
||||
pUnit_i->nAxonTo++;
|
||||
pUnit_j->nWeights++;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
UINT32 NetRTRLFeedForward(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut)
|
||||
{
|
||||
UINT32 k, i, id;
|
||||
UNIT * pUnit_i, *pUnit_k;
|
||||
|
||||
// Input units (one pattern per training interval)
|
||||
for (k=0; k < pObj->nIn; k++)
|
||||
{
|
||||
id = pObj->pInputID[k];
|
||||
pObj->pUnit[id].axon = pIn[k];
|
||||
}
|
||||
// ************* FEED FORWARD *********************
|
||||
// Calc net(t+1)
|
||||
// Hidden Units (update every time step)
|
||||
for (k=0; k < pObj->nHidden; k++)
|
||||
{
|
||||
id = pObj->pHiddenID[k];
|
||||
pUnit_k = &pObj->pUnit[id];
|
||||
pUnit_k->net =0.0;
|
||||
|
||||
for (i =0; i < pUnit_k->nWeights; i++)
|
||||
{
|
||||
pUnit_i = &pObj->pUnit[pUnit_k->pAxonFrom[i]];
|
||||
pUnit_k->net += pUnit_k->pWeight[i]*pUnit_i->axon;
|
||||
}
|
||||
}
|
||||
// Output units (update every time step)
|
||||
for (k=0; k < pObj->nOut; k++)
|
||||
{
|
||||
id = pObj->pOutputID[k];
|
||||
pUnit_k = &pObj->pUnit[id];
|
||||
pUnit_k->net =0.0;
|
||||
|
||||
for (i =0; i < pUnit_k->nWeights; i++)
|
||||
{
|
||||
pUnit_i = &pObj->pUnit[pUnit_k->pAxonFrom[i]];
|
||||
pUnit_k->net += pUnit_k->pWeight[i]*pUnit_i->axon;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Axon(t+1)
|
||||
for (k=0; k < pObj->nUnits; k++)
|
||||
{
|
||||
pObj->pUnit[k].lastAxon = pObj->pUnit[k].axon;
|
||||
if (pObj->pUnit[k].F)
|
||||
{
|
||||
pObj->pUnit[k].axon = pObj->pUnit[k].F(pObj->pUnit[k].net);
|
||||
}
|
||||
}
|
||||
|
||||
for (k=0; k < pObj->nOut; k++)
|
||||
{
|
||||
pUnit_k = &pObj->pUnit[pObj->pOutputID[k]];
|
||||
pOut[k] = pUnit_k->axon;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
UINT32 NetRTRL(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut, FLOAT64 *pTarget, FLOAT64 alpha, FLOAT64 eta, UINT32 nPattern, UINT32 trainInterval)
|
||||
{
|
||||
|
||||
UINT32 j, k, i, t, id, p, n, uid_i, uid_j;
|
||||
UNIT * pUnit_i, *pUnit_j, *pUnit_k, *pUnit_n;
|
||||
FLOAT64 sum, err;
|
||||
|
||||
pObj->sse = 0;
|
||||
|
||||
for (p=0; p < nPattern; p++)
|
||||
{
|
||||
// Input units (one pattern per training interval)
|
||||
NetRTRLFeedForward(pObj, &pIn[p*pObj->nIn], &pOut[p*pObj->nOut]);
|
||||
|
||||
// delta(t)
|
||||
for (j=0; j < pObj->nUnits; j++)
|
||||
{
|
||||
|
||||
uid_j = j;
|
||||
pUnit_j = &pObj->pUnit[uid_j];
|
||||
|
||||
for (i=0; i < pObj->nUnits; i++)
|
||||
{
|
||||
|
||||
uid_i = i;
|
||||
pUnit_i = &pObj->pUnit[uid_i];
|
||||
|
||||
for (k=0; k < pObj->nUnits; k++)
|
||||
{
|
||||
pUnit_k = &pObj->pUnit[k];
|
||||
|
||||
sum = 0.0;
|
||||
for (n=0; n < pUnit_k->nWeights; n++)
|
||||
{
|
||||
pUnit_n = &pObj->pUnit[pUnit_k->pAxonFrom[n]];
|
||||
sum += pUnit_k->pWeight[n]*pUnit_n->ppRecurrOld[uid_i][uid_j];
|
||||
|
||||
}
|
||||
if (pUnit_k->Fd)
|
||||
{
|
||||
if (uid_i == k)
|
||||
pUnit_k->ppRecurr[uid_i][uid_j] = pUnit_k->Fd(pUnit_k->axon)*(sum+pUnit_j->lastAxon);
|
||||
else
|
||||
pUnit_k->ppRecurr[uid_i][uid_j] = pUnit_k->Fd(pUnit_k->axon)*sum;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (k=0; k < pObj->nUnits; k++)
|
||||
for (i=0; i < pObj->nUnits; i++)
|
||||
for (j=0; j < pObj->nUnits; j++)
|
||||
pObj->pUnit[k].ppRecurrOld[i][j] = pObj->pUnit[k].ppRecurr[i][j];
|
||||
|
||||
// dW(t)
|
||||
for (k=0; k < pObj->nOut; k++)
|
||||
{
|
||||
pUnit_k = &pObj->pUnit[pObj->pOutputID[k]];
|
||||
err = pTarget[p*pObj->nOut+k] - pUnit_k->axon;
|
||||
pUnit_k->error = err;
|
||||
// pUnit_k->error = log10(fabs((1 + err)/(1 - err)));
|
||||
// err = log10(fabs((1 + err)/(1 - err)));
|
||||
pObj->sse += err*err;
|
||||
|
||||
for (i=0; i < pObj->nUnits; i++)
|
||||
{
|
||||
uid_i = i;
|
||||
pUnit_i = &pObj->pUnit[i];
|
||||
for (j=0; j < pUnit_i->nWeights; j++)
|
||||
{
|
||||
uid_j = pUnit_i->pAxonFrom[j];
|
||||
pUnit_j = &pObj->pUnit[uid_j];
|
||||
pUnit_i->pdWeight[j] += alpha*err*pUnit_k->ppRecurr[uid_i][uid_j] + (1.0-alpha)*pUnit_i->pdWeight[j];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// After training interval adjust Hidden and Output Units
|
||||
for (i=0; i < pObj->nUnits; i++)
|
||||
{
|
||||
pUnit_i = &pObj->pUnit[i];
|
||||
for (j=0; j < pUnit_i->nWeights; j++)
|
||||
{
|
||||
pUnit_i->pWeight[j] += eta*pUnit_i->pdWeight[j];
|
||||
pUnit_i->pdWeight[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
pObj->sse *= 0.5;
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
UINT32 NetTrain(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut, FLOAT64 *pTarget, FLOAT64 eta, FLOAT64 alpha, UINT32 len)
|
||||
{
|
||||
UINT32 j, k, i, p, n;
|
||||
UNIT *pUnit_j, *pUnit_k;
|
||||
FLOAT64 slope;
|
||||
|
||||
n=0;
|
||||
pObj->sse =0.0;
|
||||
for (p=0; p < len; p++)
|
||||
{
|
||||
NetFeedForward(pObj, &pIn[p*(pObj->nIn)], &pOut[n]);
|
||||
NetBackPropErr(pObj, &pIn[p*(pObj->nIn)], &pTarget[n]);
|
||||
|
||||
/* Adjust Hidden and Output Units */
|
||||
for (k=pObj->nIn+1; k < pObj->nUnits; k++)
|
||||
{
|
||||
pUnit_k = &pObj->pUnit[k];
|
||||
slope = 0.0;
|
||||
for (i =0; i < pUnit_k->nWeights; i++)
|
||||
{
|
||||
j = pUnit_k->pAxonFrom[i];
|
||||
pUnit_j = &pObj->pUnit[j];
|
||||
pUnit_k->pdWeight[i] = alpha*pUnit_j->axon*pUnit_k->delta + (1.0-alpha)*pUnit_k->pdWeight[i];
|
||||
pUnit_k->pWeight[i] += eta*pUnit_k->pdWeight[i];
|
||||
}
|
||||
}
|
||||
n++;
|
||||
}
|
||||
pObj->sse *= 0.5;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetTrain2(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut, FLOAT64 *pError, FLOAT64 eta, FLOAT64 alpha, UINT32 len)
|
||||
{
|
||||
UINT32 j, k, i, p, n;
|
||||
UNIT *pUnit_j, *pUnit_k;
|
||||
|
||||
n=0;
|
||||
for (p=0; p < len; p++)
|
||||
{
|
||||
NetBackPropErr2(pObj, &pIn[p*(pObj->nIn)], &pError[n]);
|
||||
|
||||
/* Adjust Hidden and Output Units */
|
||||
for (k=pObj->nIn+1; k < pObj->nUnits; k++)
|
||||
{
|
||||
pUnit_k = &pObj->pUnit[k];
|
||||
for (i =0; i < pUnit_k->nWeights; i++)
|
||||
{
|
||||
j = pUnit_k->pAxonFrom[i];
|
||||
pUnit_j = &pObj->pUnit[j];
|
||||
pUnit_k->pdWeight[i] = eta*pUnit_j->axon*pUnit_k->delta;
|
||||
pUnit_k->pWeight[i] += alpha*pUnit_k->pdWeight[i];
|
||||
}
|
||||
}
|
||||
n++;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetFeedForward(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut)
|
||||
{
|
||||
UINT32 j, k, m, i;
|
||||
UNIT *pUnit_j, *pUnit_k, **ppU;
|
||||
|
||||
m=0;
|
||||
/* Input Layer */
|
||||
for (k=1; k < pObj->nIn+1; k++)
|
||||
{
|
||||
pUnit_k = &pObj->pUnit[k];
|
||||
pUnit_k->axon = pIn[m++];
|
||||
}
|
||||
#ifndef COOL_FEEDFORWARD
|
||||
|
||||
/* Input, Hidden and Output Layers */
|
||||
for (k=pObj->pLayer[0].nUnits; k < pObj->nUnits; k++)
|
||||
{
|
||||
pUnit_k = &pObj->pUnit[k];
|
||||
pUnit_k->net =0.0;
|
||||
for (i =0; i < pUnit_k->nWeights; i++)
|
||||
{
|
||||
j = pUnit_k->pAxonFrom[i];
|
||||
pUnit_j = &pObj->pUnit[j];
|
||||
pUnit_k->net += pUnit_k->pWeight[i]*pUnit_j->axon;
|
||||
}
|
||||
pUnit_k->axon = pUnit_k->F(pUnit_k->net);
|
||||
}
|
||||
#else
|
||||
#pragma message ("nnet.c: Using cool feed forward computing.")
|
||||
/********************************************************/
|
||||
/* TEST: don't care for layer organization */
|
||||
/********************************************************/
|
||||
for (i=0; i < pObj->nUnits; i++)
|
||||
pObj->pUnit[i].net = 0.0;
|
||||
|
||||
for (j=0; j < pObj->nUnits; j++)
|
||||
{
|
||||
pUnit_j = &pObj->pUnit[j];
|
||||
if (pUnit_j->F)
|
||||
pUnit_j->axon = pUnit_j->F(pUnit_j->net);
|
||||
|
||||
for (i=0; i < pUnit_j->nAxonTo; i++)
|
||||
{
|
||||
k = pUnit_j->pAxonTo[i].unitID;
|
||||
wid = pUnit_j->pAxonTo[i].weightID;
|
||||
pUnit_k = &pObj->pUnit[k];
|
||||
pUnit_k->net += pUnit_k->pWeight[wid]*pUnit_j->axon;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/********************************************************/
|
||||
ppU = pObj->pLayer[pObj->nLayers-1].ppUnit;
|
||||
for (j = 0; j < pObj->nOut; j++)
|
||||
{
|
||||
pOut[j] = (*ppU)->axon;
|
||||
ppU++;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetBackPropErr(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pTarget)
|
||||
{
|
||||
UINT32 j, k, i, target, numLayers, layer;
|
||||
UNIT **ppUnit_j, **ppUnit_k, *pUnit_j, *pUnit_k;
|
||||
FLOAT64 err;
|
||||
|
||||
|
||||
numLayers = pObj->nLayers;
|
||||
|
||||
/* Zero Errors of all units */
|
||||
for (j = pObj->pLayer[0].nUnits; j < pObj->nUnits; j++)
|
||||
{
|
||||
pObj->pUnit[j].error = 0;
|
||||
}
|
||||
|
||||
/* Calc Error Output Layer */
|
||||
target=0;
|
||||
ppUnit_j = pObj->pLayer[numLayers-1].ppUnit;
|
||||
|
||||
for (j=0; j < pObj->pLayer[numLayers-1].nUnits; j++)
|
||||
{
|
||||
pUnit_j = *(ppUnit_j++);
|
||||
err = pTarget[target++] - pUnit_j->axon;
|
||||
pUnit_j->error = log10(fabs((1 + err)/(1 - err)));
|
||||
pUnit_j->delta = pUnit_j->error*pUnit_j->Fd(pUnit_j->axon);
|
||||
pObj->sse += err*err;
|
||||
}
|
||||
|
||||
#ifndef COOL_BACKPROP
|
||||
|
||||
/* Calc Error Hidden Layer */
|
||||
for (layer = numLayers-1; layer > 1; layer--)
|
||||
{
|
||||
ppUnit_k = pObj->pLayer[layer].ppUnit;
|
||||
for (k =0; k < pObj->pLayer[layer].nUnits; k++)
|
||||
{
|
||||
pUnit_k = *(ppUnit_k++);
|
||||
for (i=1; i < pUnit_k->nWeights; i++)
|
||||
{
|
||||
j = pUnit_k->pAxonFrom[i];
|
||||
pUnit_j = &pObj->pUnit[j];
|
||||
if (pUnit_j->UType == UTYPE_HIDDEN)
|
||||
{
|
||||
pUnit_k->pSlope[j] += pUnit_k->delta*pUnit_k->axon;
|
||||
pUnit_j->error += pUnit_k->pWeight[i]*pUnit_k->delta;
|
||||
pUnit_j->delta = pUnit_j->error*pUnit_j->Fd(pUnit_j->axon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#pragma message ("nnet.c: Using cool error back propagation.")
|
||||
#error ("nnet.c: Implement cool error back propagation.")
|
||||
#endif
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetBackPropErr2(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pError)
|
||||
{
|
||||
UINT32 j, k, i, error, numLayers, layer;
|
||||
UNIT **ppUnit_j, **ppUnit_k, *pUnit_j, *pUnit_k;
|
||||
FLOAT64 err;
|
||||
|
||||
|
||||
numLayers = pObj->nLayers;
|
||||
|
||||
/* Zero Errors of all units */
|
||||
for (j = pObj->pLayer[0].nUnits; j < pObj->nUnits; j++)
|
||||
{
|
||||
pObj->pUnit[j].error = 0;
|
||||
}
|
||||
|
||||
/* Calc Error Output Layer */
|
||||
pObj->sse =0.0;
|
||||
error=0;
|
||||
ppUnit_j = pObj->pLayer[numLayers-1].ppUnit;
|
||||
|
||||
for (j=0; j < pObj->pLayer[numLayers-1].nUnits; j++)
|
||||
{
|
||||
pUnit_j = *(ppUnit_j++);
|
||||
err = pError[error++];
|
||||
pUnit_j->error = log10(fabs((1 + err)/(1 - err)));
|
||||
pUnit_j->delta = pUnit_j->error*pUnit_j->Fd(pUnit_j->axon);
|
||||
pObj->sse += err*err;
|
||||
}
|
||||
|
||||
/* Calc Error Hidden Layer */
|
||||
for (layer = numLayers-1; layer > 1; layer--)
|
||||
{
|
||||
ppUnit_k = pObj->pLayer[layer].ppUnit;
|
||||
for (k =0; k < pObj->pLayer[layer].nUnits; k++)
|
||||
{
|
||||
pUnit_k = *(ppUnit_k++);
|
||||
for (i=1; i < pUnit_k->nWeights; i++)
|
||||
{
|
||||
j = pUnit_k->pAxonFrom[i];
|
||||
pUnit_j = &pObj->pUnit[j];
|
||||
pUnit_j->error += pUnit_k->pWeight[i]*pUnit_k->delta;
|
||||
pUnit_j->delta = pUnit_j->error*pUnit_j->Fd(pUnit_j->axon);
|
||||
}
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 NetWeightUpd(struct _sNNET *pObj, FLOAT64 *pIn, UINT32 len)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 UnitFree(struct _sUNIT *pObj)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void* nnMalloc(void *pBuffer, UINT32 size)
|
||||
{
|
||||
|
||||
if (pBuffer == NULL)
|
||||
pBuffer = malloc(size);
|
||||
else
|
||||
pBuffer = NULL;
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
void* nnFree(void *pBuffer)
|
||||
{
|
||||
|
||||
if (pBuffer != NULL)
|
||||
free(pBuffer);
|
||||
|
||||
pBuffer = NULL;
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
#define K_SIGM 1.0
|
||||
#define K_TANH 1.0
|
||||
|
||||
FLOAT64 Sigmoid(FLOAT64 x)
|
||||
{
|
||||
return 1.0 / (1.0 + exp(-K_SIGM*x));
|
||||
}
|
||||
|
||||
FLOAT64 dSigmoid(FLOAT64 x)
|
||||
{
|
||||
return x*(1.0-x);
|
||||
}
|
||||
|
||||
FLOAT64 Linear(FLOAT64 x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
FLOAT64 dLinear(FLOAT64 x)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
FLOAT64 Tanh2(FLOAT64 x)
|
||||
{
|
||||
FLOAT64 e1 = exp(2*K_TANH*x);
|
||||
e1 = (e1-1.0)/(e1+1.0);
|
||||
return e1;
|
||||
}
|
||||
|
||||
FLOAT64 dTanh2(FLOAT64 x)
|
||||
{
|
||||
FLOAT64 e1 = exp(2*K_TANH*x);
|
||||
FLOAT64 e11 = e1+1.0;
|
||||
|
||||
return 4*K_TANH*e1 / (e11*e11);
|
||||
}
|
||||
|
||||
FLOAT64 ASigmoid(FLOAT64 x)
|
||||
{
|
||||
return 1.0 / (1.0 + exp(-K_SIGM*x));
|
||||
}
|
||||
|
||||
FLOAT64 SSigmoid(FLOAT64 x)
|
||||
{
|
||||
return - 0.5 + 1.0 / (1.0 + exp(-x));
|
||||
}
|
||||
|
||||
FLOAT64 dSSigmoid(FLOAT64 x)
|
||||
{
|
||||
FLOAT64 e1 = exp(K_SIGM*x);
|
||||
FLOAT64 e11 = 1.0 + e1;
|
||||
return K_SIGM*e1 / (e11*e11);
|
||||
}
|
||||
|
||||
FLOAT64 FSigmoid(FLOAT64 x)
|
||||
{
|
||||
FLOAT64 kx = K_SIGM*x;
|
||||
return kx / (1.0 + fabs(kx));
|
||||
}
|
||||
|
||||
FLOAT64 dFSigmoid(FLOAT64 x)
|
||||
{
|
||||
return fabs(x*(1.0-x));
|
||||
}
|
||||
|
||||
FLOAT64 dTanh(FLOAT64 x)
|
||||
{
|
||||
return 1.0-x*x;
|
||||
}
|
||||
|
||||
FLOAT64 NullFunc(FLOAT64 x)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/**********************************************************************
|
||||
* nnet.h
|
||||
*
|
||||
* (C) 2000 J. Ahrensfeld
|
||||
*
|
||||
**********************************************************************/
|
||||
#ifndef NNET_H
|
||||
#define NNET_H
|
||||
|
||||
#define UTYPE_BIAS 0
|
||||
#define UTYPE_INPUT 1
|
||||
#define UTYPE_HIDDEN 2
|
||||
#define UTYPE_OUTPUT 3
|
||||
|
||||
#define UNIT_ID_INPUT (-UTYPE_INPUT)
|
||||
#define UNIT_ID_OUTPUT (-UTYPE_OUTPUT)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
#endif
|
||||
#ifndef M_E
|
||||
#define M_E 2.71828182845904523536028747135266
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
NNTYPE_MLP = 0,
|
||||
NNTYPE_RECURRENT
|
||||
};
|
||||
|
||||
/**********************************************************************/
|
||||
typedef struct _sWTINFO
|
||||
{
|
||||
UINT32 unitID, weightID;
|
||||
|
||||
} WTINFO;
|
||||
|
||||
typedef struct _sUNIT
|
||||
{
|
||||
UINT32 nWeights, nAxonTo, *pAxonFrom, UType, FType, globalUnitID, layerID, unitID;
|
||||
WTINFO *pAxonTo;
|
||||
FLOAT64 axon, lastAxon, *pWeight, *pdWeight, net, error, delta, *pSlope;
|
||||
FLOAT64 (*F)(FLOAT64); /* Zeiger auf Aktivierungsfunktion */
|
||||
FLOAT64 (*Fd)(FLOAT64); /* Zeiger auf Ableitungsfunktion */
|
||||
FLOAT64 **ppRecurr, **ppRecurrOld;
|
||||
|
||||
} UNIT;
|
||||
|
||||
typedef struct _sLAYER
|
||||
{
|
||||
UINT32 nUnits, ID;
|
||||
UNIT **ppUnit;
|
||||
} LAYER;
|
||||
|
||||
typedef struct _sNNET
|
||||
{
|
||||
UINT32 nLayers, nUnits, nnType, ID, nIn, nOut, nHidden;
|
||||
struct _sLAYER *pLayer;
|
||||
struct _sUNIT *pUnit;
|
||||
UINT32 *pInputID, *pHiddenID, *pOutputID;
|
||||
FLOAT64 sse, initwrange;
|
||||
|
||||
} NNET;
|
||||
|
||||
enum
|
||||
{
|
||||
Null, Lin, Tanh, ASig, Sig, SSig, FSig
|
||||
};
|
||||
|
||||
UINT32 NetInit(struct _sNNET *pObj, struct _sNETFILE *pNetData, UINT32 netID);
|
||||
UINT32 NetAddUnit(struct _sNNET *pObj, UINT32 unitType, UINT32 FType);
|
||||
UINT32 NetAddConnection(struct _sNNET *pObj, UINT32 ID_i, UINT32 ID_j);
|
||||
UINT32 NetFeedForward(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut);
|
||||
UINT32 NetBackPropErr(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pTarget);
|
||||
UINT32 NetBackPropErr2(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pError);
|
||||
UINT32 NetWeightUpd(struct _sNNET *pObj, FLOAT64 *pIn, UINT32 len);
|
||||
UINT32 NetTrain(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut, FLOAT64 *pTarget, FLOAT64 eta, FLOAT64 alpha, UINT32 len);
|
||||
UINT32 NetTrain2(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut, FLOAT64 *pError, FLOAT64 eta, FLOAT64 alpha, UINT32 len);
|
||||
UINT32 NetRTRL(struct _sNNET *pObj, FLOAT64 *pIn, FLOAT64 *pOut, FLOAT64 *pTarget, FLOAT64 eta, FLOAT64 alpha, UINT32 nPattern, UINT32 trainInterval);
|
||||
UINT32 NetWire(struct _sNNET *pObj, UINT32 nnType);
|
||||
UINT32 NetFree(struct _sNNET *pObj);
|
||||
void NetPrint(struct _sNNET *pObj);
|
||||
|
||||
UINT32 LayerInit(struct _sLAYER *pObj, struct _sUNIT *pUnit, UINT32 nUnits, UINT32 LayID);
|
||||
UINT32 LayerFree(struct _sLAYER *pObj);
|
||||
|
||||
UINT32 UnitInit(struct _sUNIT *pObj, UINT32 type, UINT32 FType, UINT32 ID);
|
||||
UINT32 UnitSetFunc(struct _sUNIT *pObj, UINT32 FuncType);
|
||||
UINT32 UnitFree(struct _sUNIT *pObj);
|
||||
|
||||
/* Wrapper functions */
|
||||
void* nnMalloc(void *pBuffer, UINT32 size);
|
||||
void* nnFree(void *pBuffer);
|
||||
|
||||
/* Activation Functions */
|
||||
FLOAT64 Func(FLOAT64 x);
|
||||
FLOAT64 dFunc(FLOAT64 x);
|
||||
|
||||
FLOAT64 Linear(FLOAT64 x);
|
||||
FLOAT64 dLinear(FLOAT64 x);
|
||||
FLOAT64 Tanh2(FLOAT64 x);
|
||||
FLOAT64 dTanh2(FLOAT64 x);
|
||||
FLOAT64 ASigmoid(FLOAT64 x);
|
||||
FLOAT64 SSigmoid(FLOAT64 x);
|
||||
FLOAT64 dSSigmoid(FLOAT64 x);
|
||||
FLOAT64 Sigmoid(FLOAT64 x);
|
||||
FLOAT64 dSigmoid(FLOAT64 x);
|
||||
FLOAT64 FSigmoid(FLOAT64 x);
|
||||
FLOAT64 dFSigmoid(FLOAT64 x);
|
||||
FLOAT64 dTanh(FLOAT64 x);
|
||||
FLOAT64 NullFunc(FLOAT64 x);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,440 @@
|
||||
/**********************************************************************
|
||||
* netfile.c
|
||||
*
|
||||
* (C) 2000 J. Ahrensfeld
|
||||
*
|
||||
**********************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "nntypes.h"
|
||||
#include "nnet.h"
|
||||
#include "nnfile.h"
|
||||
|
||||
/**********************************************************************/
|
||||
#define VERSION "0.1"
|
||||
#define MAX_TOKENS 15
|
||||
#define MAX_NEURON_TYPES 6
|
||||
|
||||
/**********************************************************************/
|
||||
char *pszNNtypeList[] =
|
||||
{
|
||||
"MLP", "RECURRENT", 0
|
||||
};
|
||||
|
||||
char *pszTokenList[]=
|
||||
{
|
||||
"NINPUTS","NOUTPUTS","NHIDDENLAYERS","NHIDDENNEURONS","HIDDENTYPE","OUTPUTTYPE",
|
||||
"TRAINING","LEARNINGRATE","MOMENTUM","ERRORTHRESHOLD","MAXEPOCHS","REPORTUPDATE",
|
||||
"MAXPATTERNS", "INITWEIGHTRANGE", "NNTYPE", 0
|
||||
};
|
||||
|
||||
char *pszNeuronTypeList[]=
|
||||
{
|
||||
"NULL", "LINEAR", "TANH", "ASIGMOID", "SIGMOID", "SSIGMOID", "FSIGMOID", 0
|
||||
};
|
||||
|
||||
enum Token
|
||||
{
|
||||
NINPUTS, NOUTPUTS, NHIDDENLAYERS, NHIDDENNEURONS, HIDDENTYPE, OUTPUTTYPE,
|
||||
TRAINING, LEARNINGRATE, MOMENTUM, ERRORTHRESHOLD, MAXEPOCHS, REPORTUPDATE,
|
||||
MAXPATTERNS, INITWEIGHTRANGE, NNTYPE, NOTFOUND
|
||||
};
|
||||
|
||||
/**********************************************************************/
|
||||
int ReadNextToken(FILE *pFile, char *pToken)
|
||||
{
|
||||
int i, res=EXIT_FAILURE;
|
||||
while(!feof(pFile))
|
||||
{
|
||||
fscanf(pFile,"%s",pToken);
|
||||
if((pToken[0]=='#') || (pToken[0] < '0'))
|
||||
continue;
|
||||
res = EXIT_SUCCESS;
|
||||
for (i=0; pToken[i]; i++)
|
||||
pToken[i]=toupper(pToken[i]);
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
int ReadValue(FILE *pFile, char* szValue)
|
||||
{
|
||||
int i;
|
||||
szValue[0] = 0;
|
||||
fscanf(pFile,"%s",szValue);
|
||||
for (i=0; szValue[i]; i++)
|
||||
szValue[i]=toupper(szValue[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Seek(FILE *pFile, char **pTokenList, int nMaxToken, int *RetToken)
|
||||
{
|
||||
char szToken[256];
|
||||
int nToken=0, res = EXIT_FAILURE, status=EXIT_SUCCESS;
|
||||
*RetToken = NOTFOUND;
|
||||
|
||||
while ((status == EXIT_SUCCESS) && (*RetToken == NOTFOUND))
|
||||
{
|
||||
status=ReadNextToken(pFile,szToken);
|
||||
for (nToken=0; nToken < nMaxToken; nToken++)
|
||||
{
|
||||
if(strcmp(szToken,pszTokenList[nToken]))
|
||||
continue;
|
||||
//cout << "Token(" << nToken << "): " << szToken << endl;
|
||||
*RetToken = nToken;
|
||||
res = EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ReadNetFile(char* szFileName, NETFILE *NetData)
|
||||
{
|
||||
|
||||
char szValue[80], szToken[256];
|
||||
FILE *pFile;
|
||||
UINT32 pos;
|
||||
NETFILE net;
|
||||
UINT32 Token, t, status, i, error;
|
||||
UINT32 layer, neurons, neuronType;
|
||||
UINT32 size, p;
|
||||
|
||||
/***************************************************************************/
|
||||
// INIT
|
||||
net.nInputs = 0;
|
||||
net.nOutputs = 0;
|
||||
net.nHiddenLayers = 0;
|
||||
net.nHiddenNeurons = 0;
|
||||
net.nTrainingSets = 0;
|
||||
net.LearningRate = 0.4;
|
||||
net.Momentum = 0.8;
|
||||
net.ErrorThreshold = 0;
|
||||
net.MaxEpochs = 25000;
|
||||
net.reportUpd = 100;
|
||||
net.maxPatterns = 1000000;
|
||||
net.initwrange = 1.0;
|
||||
net.nntype = NNTYPE_MLP;
|
||||
|
||||
/***************************************************************************/
|
||||
error = EXIT_FAILURE;
|
||||
|
||||
while(1)
|
||||
{
|
||||
/***************************************************************************/
|
||||
/* Datei oeffnen */
|
||||
/***************************************************************************/
|
||||
printf("Lese Datei %s\n",szFileName);
|
||||
pFile = fopen(szFileName,"r");
|
||||
if (pFile==NULL)
|
||||
|
||||
{
|
||||
printf("Die Datei %s konnte nicht geöffnet werden.\n",szFileName);
|
||||
break;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Erwarte "net"-Identifier */
|
||||
/***************************************************************************/
|
||||
ReadNextToken(pFile, szToken);
|
||||
pos = ftell(pFile);
|
||||
|
||||
if (!strcmp(szToken,"NET"))
|
||||
printf("%s\n",szToken);
|
||||
else
|
||||
{
|
||||
printf("ERROR: Missing NET-identifier\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Inputs, Outputs, Layer */
|
||||
/***************************************************************************/
|
||||
pos=fseek(pFile, 0, SEEK_SET);
|
||||
status = 0;
|
||||
Token = NOTFOUND;
|
||||
|
||||
while ((net.nInputs*net.nOutputs*net.nHiddenLayers)==0 && !status)
|
||||
{
|
||||
status=Seek(pFile,pszTokenList, MAX_TOKENS, &Token);
|
||||
switch (Token)
|
||||
{
|
||||
case NNTYPE:
|
||||
net.nntype = NNTYPE_MLP;
|
||||
ReadValue(pFile, szValue);
|
||||
i=0;
|
||||
while(pszNNtypeList[i])
|
||||
{
|
||||
if(!strcmp(szValue, pszNNtypeList[i]))
|
||||
{
|
||||
net.nntype = i;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
printf("Neural Net type is %s\n",pszNNtypeList[net.nntype]);
|
||||
break;
|
||||
|
||||
case NINPUTS:
|
||||
ReadValue(pFile, szValue);
|
||||
net.nInputs = atoi(szValue);
|
||||
printf("nInputs = %d\n",net.nInputs);
|
||||
break;
|
||||
|
||||
case NOUTPUTS:
|
||||
ReadValue(pFile, szValue);
|
||||
net.nOutputs = atoi(szValue);
|
||||
printf("nOutputs = %d\n",net.nOutputs);
|
||||
break;
|
||||
|
||||
case NHIDDENLAYERS:
|
||||
ReadValue(pFile, szValue);
|
||||
net.nHiddenLayers = atoi(szValue);
|
||||
printf("nHiddenLayers = %d\n",net.nHiddenLayers);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(status == EXIT_FAILURE)
|
||||
{
|
||||
printf("Invalid file Inputs, Outputs, Layer!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Layer Organization */
|
||||
/***************************************************************************/
|
||||
pos=fseek(pFile, 0, SEEK_SET);
|
||||
t = 0;
|
||||
status = 0;
|
||||
Token = NOTFOUND;
|
||||
|
||||
while (t < net.nHiddenLayers && !status )
|
||||
{
|
||||
status = Seek(pFile,pszTokenList, MAX_TOKENS, &Token);
|
||||
if ((Token != NHIDDENNEURONS) && !feof(pFile))
|
||||
continue;
|
||||
{
|
||||
ReadValue(pFile, szValue);
|
||||
layer = atoi(szValue);
|
||||
ReadValue(pFile, szValue);
|
||||
neurons = atoi(szValue);
|
||||
printf("HiddenLayer[%d]: %d Neurons\n",layer,neurons);
|
||||
net.LInfo[layer].nNeurons = neurons;
|
||||
net.nHiddenNeurons += neurons;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
printf("Total number of Hidden Neurons = %d\n",net.nHiddenNeurons);
|
||||
|
||||
if(status == EXIT_FAILURE)
|
||||
{
|
||||
printf("Invalid Layer Organization!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* NeuronType */
|
||||
/***************************************************************************/
|
||||
pos=fseek(pFile, 0, SEEK_SET);
|
||||
|
||||
for (layer=0; layer <net.nHiddenLayers; layer++)
|
||||
net.LInfo[layer].NeuronType = Tanh;
|
||||
|
||||
while (!feof(pFile))
|
||||
{
|
||||
status=0;
|
||||
Token = NOTFOUND;
|
||||
|
||||
status=Seek(pFile,pszTokenList, MAX_TOKENS, &Token);
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case HIDDENTYPE:
|
||||
ReadValue(pFile, szValue);
|
||||
layer = atoi(szValue);
|
||||
ReadValue(pFile, szValue);
|
||||
for (neuronType=0; neuronType < MAX_NEURON_TYPES; neuronType++)
|
||||
{
|
||||
if(!strcmp(szValue,pszNeuronTypeList[neuronType]))
|
||||
break;
|
||||
}
|
||||
if (neuronType==MAX_NEURON_TYPES)
|
||||
neuronType = Sig;
|
||||
printf("HiddenType[%d] = %s (%d)\n",layer,szValue,neuronType);
|
||||
net.LInfo[layer].NeuronType = neuronType;
|
||||
break;
|
||||
|
||||
case OUTPUTTYPE:
|
||||
ReadValue(pFile, szValue);
|
||||
for (net.OutType=0; net.OutType < MAX_NEURON_TYPES; net.OutType++)
|
||||
{
|
||||
if(!strcmp(szValue,pszNeuronTypeList[net.OutType]))
|
||||
break;
|
||||
}
|
||||
if (net.OutType==MAX_NEURON_TYPES)
|
||||
net.OutType = Tanh;
|
||||
|
||||
printf("Output Type = %s (%d)\n",szValue,net.OutType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
net.LInfo[0].NeuronType = 0;
|
||||
net.LInfo[0].nNeurons = net.nInputs;
|
||||
net.LInfo[net.nHiddenLayers+1].NeuronType = net.OutType;
|
||||
net.LInfo[net.nHiddenLayers+1].nNeurons = net.nOutputs;
|
||||
|
||||
/***************************************************************************/
|
||||
/* Parameter */
|
||||
/***************************************************************************/
|
||||
pos=fseek(pFile, 0, SEEK_SET);
|
||||
|
||||
while (!feof(pFile))
|
||||
{
|
||||
status=0;
|
||||
Token = NOTFOUND;
|
||||
|
||||
status=Seek(pFile,pszTokenList, MAX_TOKENS, &Token);
|
||||
|
||||
switch(Token)
|
||||
{
|
||||
case LEARNINGRATE:
|
||||
ReadValue(pFile, szValue);
|
||||
net.LearningRate = atof(szValue);
|
||||
printf("Learning Rate = %g\n",net.LearningRate);
|
||||
break;
|
||||
|
||||
case MOMENTUM:
|
||||
ReadValue(pFile, szValue);
|
||||
net.Momentum = atof(szValue);
|
||||
printf("Momentum = %g\n",net.Momentum);
|
||||
break;
|
||||
|
||||
case ERRORTHRESHOLD:
|
||||
ReadValue(pFile, szValue);
|
||||
net.ErrorThreshold = atof(szValue);
|
||||
printf("Error Threshold = %g\n",net.ErrorThreshold);
|
||||
break;
|
||||
|
||||
case MAXEPOCHS:
|
||||
ReadValue(pFile, szValue);
|
||||
net.MaxEpochs = atoi(szValue);
|
||||
printf("Max. Epochs = %d\n",net.MaxEpochs);
|
||||
break;
|
||||
|
||||
case REPORTUPDATE:
|
||||
ReadValue(pFile, szValue);
|
||||
net.reportUpd = atoi(szValue);
|
||||
printf("Report every %d epoch\n",net.reportUpd);
|
||||
break;
|
||||
|
||||
case MAXPATTERNS:
|
||||
ReadValue(pFile, szValue);
|
||||
net.maxPatterns = atoi(szValue);
|
||||
printf("Read max. %d patterns\n",net.maxPatterns);
|
||||
break;
|
||||
|
||||
case INITWEIGHTRANGE:
|
||||
ReadValue(pFile, szValue);
|
||||
net.initwrange = (double)atof(szValue);
|
||||
printf("Init weight range = +/- %2.2g\n",net.initwrange);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Training Data */
|
||||
/***************************************************************************/
|
||||
pos=fseek(pFile, 0, SEEK_SET);
|
||||
status=0;
|
||||
Token = NOTFOUND;
|
||||
|
||||
while (Token != TRAINING && !status )
|
||||
status=Seek(pFile,pszTokenList, MAX_TOKENS, &Token);
|
||||
|
||||
if(status == EXIT_FAILURE)
|
||||
{
|
||||
printf("No Training Data found.\n");
|
||||
break;
|
||||
}
|
||||
status = 0;
|
||||
|
||||
/* Count number of Patterns */
|
||||
while (!status)
|
||||
{
|
||||
for (i=0; i < net.nInputs; i++)
|
||||
status=ReadValue(pFile, szValue);
|
||||
|
||||
if (szValue[0] < ' ') break;
|
||||
|
||||
for (i=0; i < net.nOutputs; i++)
|
||||
status=ReadValue(pFile, szValue);
|
||||
|
||||
if (szValue[0] < ' ') break;
|
||||
|
||||
net.nTrainingSets++;
|
||||
}
|
||||
|
||||
if(net.nTrainingSets == 0)
|
||||
{
|
||||
printf("Missing Training Data!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(net.maxPatterns < net.nTrainingSets)
|
||||
net.nTrainingSets = net.maxPatterns;
|
||||
|
||||
/* Alloc mem */
|
||||
size = net.nInputs*net.nTrainingSets;
|
||||
net.pInput = (FLOAT64*)malloc(size*sizeof(FLOAT64));
|
||||
|
||||
size = net.nOutputs*net.nTrainingSets;
|
||||
net.pTarget = (FLOAT64*)malloc(size*sizeof(FLOAT64));
|
||||
|
||||
/* Read training data */
|
||||
pos=fseek(pFile, 0, SEEK_SET);
|
||||
status=0;
|
||||
Token = NOTFOUND;
|
||||
while (Token != TRAINING && !status )
|
||||
status=Seek(pFile,pszTokenList, MAX_TOKENS, &Token);
|
||||
|
||||
for (p=0; p < net.nTrainingSets; p++)
|
||||
{
|
||||
for (i=0; i < net.nInputs; i++)
|
||||
{
|
||||
status=ReadValue(pFile, szValue);
|
||||
net.pInput[i+p*net.nInputs]= atof(szValue);
|
||||
}
|
||||
|
||||
if (szValue[0] < ' ') break;
|
||||
for (i=0; i < net.nOutputs; i++)
|
||||
{
|
||||
status=ReadValue(pFile, szValue);
|
||||
net.pTarget[i+p*net.nOutputs]= atof(szValue);
|
||||
}
|
||||
if (szValue[0] < ' ') break;
|
||||
}
|
||||
error = EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
printf("Number of Training Sets = %d\n",net.nTrainingSets);
|
||||
/******************************************************************************/
|
||||
fclose(pFile);
|
||||
*NetData = net;
|
||||
return error;
|
||||
}
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/**********************************************************************
|
||||
* netfile.h
|
||||
*
|
||||
* (C) 2000 J. Ahrensfeld
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef NNFILE_H
|
||||
#define NNFILE_H
|
||||
|
||||
#include "nntypes.h"
|
||||
|
||||
typedef struct _sLayerInfo
|
||||
{
|
||||
int nNeurons, NeuronType;
|
||||
} LayerInfo;
|
||||
|
||||
typedef struct _sNETFILE
|
||||
{
|
||||
UINT32 nInputs, nOutputs, nHiddenNeurons, nHiddenLayers, nTrainingSets, OutType;
|
||||
UINT32 MaxEpochs, reportUpd, maxPatterns, nntype;
|
||||
LayerInfo LInfo[64];
|
||||
double *pInput;
|
||||
double *pTarget;
|
||||
double LearningRate, Momentum, ErrorThreshold, initwrange;
|
||||
} NETFILE;
|
||||
|
||||
int ReadNetFile(char* szFileName, NETFILE *NInfo);
|
||||
|
||||
#endif /* NNFILE_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/**********************************************************************
|
||||
* nntiff.c
|
||||
*
|
||||
* (C) 2000 J. Ahrensfeld
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "nntypes.h"
|
||||
#include "nnet.h"
|
||||
#include "nntiff.h"
|
||||
#include "tiffio.h"
|
||||
|
||||
#define TIFF_FILENAME "test"
|
||||
#define TIFF_PASS_WIDTH 200
|
||||
#define TIFF_PASS_HEIGHT 200
|
||||
#define TIFF_NUM_FRAMES 1
|
||||
|
||||
/**********************************************************************/
|
||||
UINT32 CpyChar2Dbl(double *pDoubleArr, UINT8 *pCharArr, UINT32 nChars)
|
||||
{
|
||||
UINT32 i;
|
||||
for (i=0; i <nChars; i++)
|
||||
pDoubleArr[i] = (double)pCharArr[i];
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
UINT32 CpyDbl2Char(UINT8 *pCharArr, double *pDoubleArr, UINT32 nDoubles)
|
||||
{
|
||||
UINT32 i;
|
||||
for (i=0; i <nDoubles; i++)
|
||||
pCharArr[i] = (UINT8)(fabs(pDoubleArr[i])*0xFF);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
double dmax(double v1, double v2)
|
||||
{
|
||||
if (v1 > v2)
|
||||
return v1;
|
||||
|
||||
else
|
||||
return v2;
|
||||
}
|
||||
|
||||
void Normalize(double *pBuffer, double normVal, UINT32 len)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
double maxVal = normVal;
|
||||
for (i=0; i <len; i++)
|
||||
maxVal = dmax(maxVal, pBuffer[i]);
|
||||
|
||||
for (i=0; i <len; i++)
|
||||
pBuffer[i] = normVal * pBuffer[i] / maxVal;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SwapRowCol(UINT8 *pBuffer, UINT32 width, UINT32 height)
|
||||
{
|
||||
UINT32 row, col;
|
||||
UINT8 *pNewBuf = (UINT8*)_TIFFmalloc(width*height);
|
||||
|
||||
for (row=0; row <height; row++)
|
||||
{
|
||||
for (col=0; col <width; col++)
|
||||
pNewBuf[width*col+row] = pBuffer[col+row*width];
|
||||
}
|
||||
_TIFFmemcpy(pBuffer, pNewBuf, width*height);
|
||||
_TIFFfree(pNewBuf);
|
||||
|
||||
}
|
||||
|
||||
void ViewAlign(UINT8 **ppBuffer, UINT32 width, UINT32 height)
|
||||
{
|
||||
UINT8 temp;
|
||||
UINT32 col, row;
|
||||
UINT8 *pTemp = (UINT8*)_TIFFmalloc(width);
|
||||
|
||||
for (row=0; row <height; row++)
|
||||
{
|
||||
for (col=0; col <width/2; col++)
|
||||
{
|
||||
temp = ppBuffer[row][col];
|
||||
ppBuffer[row][col] = ppBuffer[row][col+width/2];
|
||||
ppBuffer[row][col+width/2] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
for (row=0; row <height/2; row++)
|
||||
{
|
||||
_TIFFmemcpy(pTemp, ppBuffer[row+height/2], width);
|
||||
_TIFFmemcpy(ppBuffer[row+height/2], ppBuffer[row], width);
|
||||
_TIFFmemcpy(ppBuffer[row], pTemp, width);
|
||||
}
|
||||
ppBuffer[height/2][width/2] /= 2;
|
||||
_TIFFfree(pTemp);
|
||||
|
||||
}
|
||||
|
||||
UINT32 TiffOutInit(TIFFOUT *pObj)
|
||||
{
|
||||
pObj->frameCnt=0;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UINT32 TiffOut(TIFFOUT *pObj, NNET *pNet)
|
||||
{
|
||||
|
||||
TIFF *pTifOut;
|
||||
|
||||
ttag_t config, nBits, nSamples, photometric;
|
||||
UINT8 *pLineBuf;
|
||||
UINT32 width, height, tx, ty;
|
||||
INT32 status, ci;
|
||||
char tiffName[100], framenum[8];
|
||||
FLOAT64 *pIn, *pOut, xVal, yVal;
|
||||
|
||||
|
||||
pLineBuf = NULL;
|
||||
pLineBuf = (char*)_TIFFmalloc(TIFF_PASS_WIDTH*sizeof(UINT8));
|
||||
pIn = (double*) malloc(pNet->nIn*sizeof(double));
|
||||
pOut = (double*) malloc(TIFF_PASS_HEIGHT*pNet->nOut*sizeof(double));
|
||||
|
||||
if (pNet->nIn == 2)
|
||||
{
|
||||
photometric = PHOTOMETRIC_MINISBLACK;
|
||||
width = 200;
|
||||
height = 200;
|
||||
config = PLANARCONFIG_CONTIG;
|
||||
nBits = 8;
|
||||
nSamples = 1;
|
||||
|
||||
sprintf(framenum,"%4d",pObj->frameCnt);
|
||||
|
||||
ci=0;
|
||||
while (framenum[ci])
|
||||
{
|
||||
if(framenum[ci]==0x20)
|
||||
framenum[ci]=0x30;
|
||||
ci++;
|
||||
}
|
||||
sprintf(tiffName,"%s%s.tiff",TIFF_FILENAME,framenum);
|
||||
pTifOut = TIFFOpen(tiffName,"w");
|
||||
|
||||
status = TIFFSetField(pTifOut, TIFFTAG_IMAGEWIDTH, TIFF_PASS_WIDTH);
|
||||
status = TIFFSetField(pTifOut, TIFFTAG_IMAGELENGTH, TIFF_PASS_HEIGHT);
|
||||
status = TIFFSetField(pTifOut, TIFFTAG_PLANARCONFIG, config);
|
||||
status = TIFFSetField(pTifOut, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
status = TIFFSetField(pTifOut, TIFFTAG_BITSPERSAMPLE, nBits);
|
||||
status = TIFFSetField(pTifOut, TIFFTAG_SAMPLESPERPIXEL, nSamples);
|
||||
status = TIFFSetField(pTifOut, TIFFTAG_ORIENTATION, 1);
|
||||
}
|
||||
|
||||
for (ty=0; ty < TIFF_PASS_HEIGHT; ty++)
|
||||
{
|
||||
yVal = (FLOAT64)ty / TIFF_PASS_WIDTH;
|
||||
for (tx=0; tx < TIFF_PASS_WIDTH; tx++)
|
||||
{
|
||||
xVal = (FLOAT64)tx / TIFF_PASS_WIDTH;
|
||||
pIn[0] = xVal;
|
||||
pIn[1] = yVal;
|
||||
NetFeedForward(pNet, pIn, &pOut[tx]);
|
||||
}
|
||||
Normalize(pOut, 1.0, TIFF_PASS_WIDTH);
|
||||
|
||||
CpyDbl2Char(pLineBuf, pOut, TIFF_PASS_WIDTH);
|
||||
status = TIFFWriteScanline(pTifOut, pLineBuf, ty, 0);
|
||||
}
|
||||
printf("Write frame %d\n",pObj->frameCnt++);
|
||||
TIFFClose(pTifOut);
|
||||
|
||||
if (pLineBuf)
|
||||
_TIFFfree(pLineBuf);
|
||||
if (pIn)
|
||||
free(pIn);
|
||||
if (pOut)
|
||||
free(pOut);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/**********************************************************************
|
||||
* nntiff.h
|
||||
*
|
||||
* (C) 2000 J. Ahrensfeld
|
||||
*
|
||||
**********************************************************************/
|
||||
typedef struct _sTIFFOUT
|
||||
{
|
||||
UINT32 frameCnt;
|
||||
} TIFFOUT;
|
||||
|
||||
UINT32 TiffOutInit(TIFFOUT *pObj);
|
||||
UINT32 TiffOut(TIFFOUT *pObj, NNET *pNet);
|
||||
@@ -0,0 +1,40 @@
|
||||
/**********************************************************************
|
||||
* nntypes.h
|
||||
*
|
||||
* (C) 2000 J. Ahrensfeld
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _NNTYPES_H
|
||||
#define _NNTYPES_H
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
/* Win32 data types */
|
||||
#include <windows.h>
|
||||
#define INT8 char
|
||||
#define INT16 short
|
||||
#define INT32 long
|
||||
#define UINT8 unsigned char
|
||||
#define UINT16 unsigned short
|
||||
#define UINT32 unsigned long
|
||||
/* INT and UINT are defined in windef.h */
|
||||
#define FLOAT32 float
|
||||
#define FLOAT64 double
|
||||
|
||||
#elif defined(__linux__)
|
||||
#if defined(__i386__)
|
||||
/* linux x86 data types */
|
||||
#define INT8 char
|
||||
#define INT16 short
|
||||
#define INT32 long
|
||||
#define UINT8 unsigned char
|
||||
#define UINT16 unsigned short
|
||||
#define UINT32 unsigned long
|
||||
#define INT int
|
||||
#define UINT unsigned int
|
||||
#define FLOAT32 float
|
||||
#define FLOAT64 double
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user