📄 cconditionaldistribution.cpp
字号:
for(j=1;j<ulNumberOfInputs+1;j++)
{
dStimulus+=ppdwih[i][j]*pdInputs[j-1];
}
pdah[i]=1.0/(1.0+exp(-dStimulus));
}
double dTotalOutput=0.0;
//Unlike the neural network in CMLP.cpp, the one used here has a special function to calculate the
//activity of its outputs in order to guarantee that they sum to unity (as befits closed-world probabilities).
//This function is called "softmax" and is described more fully in books such as [Bishop95]
for(i=0;i<ulNumberOfOutputs;i++)
{
dStimulus=ppdwho[i][0];
for(j=1;j<ulNumberOfHiddenNodes+1;j++)
{
dStimulus+=ppdwho[i][j]*pdah[j-1];
}
//Translate this stimulation into the activity of the output neuron using the activation
//function:
pdao[i]=exp(dStimulus);
dTotalOutput+=pdao[i];
}
//Deallocate the temporary storage that was used for the hidden neuron activities
delete []pdah;
//Normalise the output neuron activities
for(i=0;i<ulNumberOfOutputs;i++)
{
pdao[i]/=dTotalOutput;
}
//Remember that we're returning a pointer to "new"ed storage, so the calling function
//must deallocate it to avoid memory leaks.
return pdao;
}
//Generates a sample from the conditional distribution by selecting one of the distribution's bins in
//accordance with their probabilities and generating a specific sample from within the bin
double CConditionalDistribution::dGetOutputs(
const double * const pdInputs
)
{
//Use the neural network to calculate the bin probabilities as a function of the conditional distribution's inputs
double *pdOutputs;
pdOutputs=pdGetBinProbabilities(pdInputs);
unsigned long ulCurrentBin;
double dOutput;
//This outer loop guarantees that events less likely than 1 in 100 do not occur. Though not strictly necessary
//it helps to avoid samples that cannot be justified statistically on the basis of the model's training data.
do
{
//The sampling mechanism in this inner loop is identical to that of the unconditional distribution
ulCurrentBin=0;
double dTargetProbability=double(rand())/double(RAND_MAX);
double dAccumulator=pdOutputs[ulCurrentBin];
while(dTargetProbability>dAccumulator)
{
ulCurrentBin++;
dAccumulator+=pdOutputs[ulCurrentBin];
}
}
while(pdOutputs[ulCurrentBin]<0.01);
dOutput=double(ulCurrentBin)/double(ulNumberOfOutputs)+double(rand())/double(RAND_MAX)*(1.0/double(ulNumberOfOutputs));
delete []pdOutputs;
return dOutput;
}
double CConditionalDistribution::dGetPerformance(void)
{
//dBestError is computed by a call to dGetPerformance
return dBestError;
}
//This function measures the performance of the conditional distribution model - that is how consistent it is with
//the exemplar data passed to this function. This consistency is measured as the mean log-probability with which
//the distribution model "explains" the data.
double CConditionalDistribution::dGetPerformance(
const unsigned long ulNumberOfPatterns,
double ** const ppdInputs,
double * const pdTargets
)
{
unsigned long i,j;
//Storage for the error measure
double dError=0.0;
//Will store the neural network outputs (i.e. bin probabilities)
double *pdOutputs;
//Prepare some storage for the binary target vector (explained below)
double *pdBinaryTargets=new double[ulNumberOfOutputs];
//Go through each pattern (example) in the data set and
for(i=0;i<ulNumberOfPatterns;i++)
{
//Compute the probabilities associated with each bin in the distribution for the current input
pdOutputs=pdGetBinProbabilities(ppdInputs[i]);
//Now, for each bin
for(j=0;j<ulNumberOfOutputs;j++)
{
//This section of code translates the target output associated with the current example into a
//vector of length ulNumberOfOutputs, containing zeros in all positions but for a one corresponding to
//the bin that actually contains target output specified in the current example.
//This vector can be thought of as a vector of target probabiltiies for the bins in the distribution model
//and hence for the outputs of teh neural network: if the distribution predicted the examples perfectly
//then, for this pattern, all bins would have probability zero except for the one that actually contained
//the example output.
if(pdTargets[i]>=double(j)/double(ulNumberOfOutputs)
&& pdTargets[i]<double(j+1)/double(ulNumberOfOutputs))
{
pdBinaryTargets[j]=1.0;
}
else
{
pdBinaryTargets[j]=0.0;
}
//The actual error measure is derived below. This is the cross entropy function and can only be used
//when the bin probabilities are constrained to sum to, at most, unity. (See [Bishop95].)
dError-=pdBinaryTargets[j]*log(pdOutputs[j]);
}
//Deallocate the memory used to store the network outputs.
delete []pdOutputs;
}
//Divide the error by the number of patterns to give the average error per sample - makes
//the error measure independent of the number of samples and hence a little more
//interpretable.
dError/=double(ulNumberOfPatterns);
//Clean up allocated memory
delete []pdBinaryTargets;
//Return the computed error
return dError;
}
int CConditionalDistribution::Save(const char * const pFileName)
{
unsigned long i,j;
assert(pFileName);
//Create the output stream to save the network to.
ofstream *pOut=new ofstream(pFileName);
//Make sure it was created and opened successfully.
if(!pOut)
{
assert(false);
return 0;
}
if(!pOut->is_open())
{
assert(false);
delete pOut;
return 0;
}
//Make sure we don't lose information.
pOut->precision(15);
//Save all the network info:
//Its structure...
*pOut<<ulNumberOfInputs;
*pOut<<"\n";
*pOut<<ulNumberOfHiddenNodes;
*pOut<<"\n";
*pOut<<ulNumberOfOutputs;
*pOut<<"\n";
//Its weights
for(i=0;i<ulNumberOfHiddenNodes;i++)
{
for(j=0;j<ulNumberOfInputs+1;j++)
{
*pOut<<ppdwih[i][j];
*pOut<<"\t";
}
*pOut<<"\n";
}
for(i=0;i<ulNumberOfOutputs;i++)
{
for(j=0;j<ulNumberOfHiddenNodes+1;j++)
{
*pOut<<ppdwho[i][j];
*pOut<<"\t";
}
*pOut<<"\n";
}
//When training started...
*pOut<<"Training started\t";
*pOut<<pTrainingStartTime;
*pOut<<"\t";
*pOut<<pTrainingStartDate;
*pOut<<"\n";
//the current date and time...
char *pTime=new char[256];
*pOut<<"Current time\t\t";
_strtime(pTime);
*pOut<<pTime;
*pOut<<"\t";
_strdate(pTime);
*pOut<<pTime;
*pOut<<"\n";
delete []pTime;
//And how well the network currently performs.
*pOut<<"Performance\t\t";
*pOut<<dBestError;
*pOut<<"\n";
//Close the file and delete the stream.
pOut->close();
delete pOut;
//Return that the save was successful.
return 1;
}
int CConditionalDistribution::Load(const char * const pFileName)
{
unsigned long i,j;
assert(pFileName);
//Create a stream to load the network from
ifstream *pIn=new ifstream(pFileName,ios::nocreate);
//Check to make sure that it was created and could be opened.
if(!pIn)
{
assert(false);
return 0;
}
if(!pIn->is_open())
{
assert(false);
delete pIn;
return 0;
}
//Since we're about to load a new network, we should delete the storage used by the
//current one to prevent memory leaks.
DeallocateMemory();
//Load the structure of the new network
*pIn>>ulNumberOfInputs;
*pIn>>ulNumberOfHiddenNodes;
*pIn>>ulNumberOfOutputs;
//Allocate memory to store its weights
AllocateMemory();
//Reset its status so that it can be trained if necessary
Reset();
//Load in its weights
for(i=0;i<ulNumberOfHiddenNodes;i++)
{
for(j=0;j<ulNumberOfInputs+1;j++)
{
*pIn>>ppdwih[i][j];
ppdBestwih[i][j]=ppdwih[i][j];
}
}
for(i=0;i<ulNumberOfOutputs;i++)
{
for(j=0;j<ulNumberOfHiddenNodes+1;j++)
{
*pIn>>ppdwho[i][j];
ppdBestwho[i][j]=ppdwho[i][j];
}
}
//Close and delete the stream.
pIn->close();
delete pIn;
//Indicate that we've been successful.
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -