📄 tanksdoc.cpp
字号:
{
TRACE("failed.\n");
ASSERT(FALSE);
}
}
/******************************************************************************************************************/
//This code loads the examples of aiming errors, scales them as required by the unconditional and
//conditional distribution models, and trains those models.
if(!boGeneratingErrorTrainingData)
{
unsigned long i,j;
TRACE("Opening error training data file...");
//Open the file containing the error training data.
ifstream *pErrorTrainingData;
pErrorTrainingData=new ifstream(ErrorExemplarData,ios::nocreate);
if(pErrorTrainingData)
{
TRACE("successful.\n");
}
else
{
TRACE("failed.\n");
ASSERT(FALSE);
}
//Read in the number of examples the file contains.
*pErrorTrainingData>>ulNumberOfErrorPatterns;
*pErrorTrainingData>>ulNumberOfErrorInputs;
//Create a new conditional distribution model that will be used to capture the relationship between the
//aiming error made on one shot and the error on the next.
pErrorDistribution=new CConditionalDistribution(
ulNumberOfErrorInputs,
ulNumberOfHiddenNodesInConditionalErrorModel,
ulNumberOfBinsInDistributionModels);
if(boLoadTrainedErrorNetwork)
{
//If we've already trained one, load it
pErrorDistribution->Load(TrainedConditionalDistributionModel);
}
//Create a new unconditional distribution model that will be used to represent the distribution of aiming
//errors made on the first shot of each game
pUnconditionalErrorDistribution=new CUnconditionalDistribution(ulNumberOfBinsInDistributionModels);
TRACE("Loading error training data...");
//Allocate some memory for the example data
double **ppdErrorTrainingInputs;
double *pdErrorTrainingTargets;
ppdErrorTrainingInputs=new double*[ulNumberOfErrorPatterns];
pdErrorTrainingTargets=new double[ulNumberOfErrorPatterns];
//Allocate memory to record the maximum and minimum values of each input. All inputs to the conditional
//distribution model need to be scaled into the range -1 to +1, and the example outputs for both models
//in 0 to +1.
pdErrorInputMin=new double[ulNumberOfErrorInputs];
pdErrorInputMax=new double[ulNumberOfErrorInputs];
//If any of the memory allocation failed, alert the user.
if(!( ppdErrorTrainingInputs &&
pdErrorTrainingTargets &&
pdErrorInputMin &&
pdErrorInputMax))
{
TRACE("failed.\n");
ASSERT(FALSE);
}
//Initialise the min/max statistics to large values to ensure that they'll be overwritten
//when the data are analysed.
for(i=0;i<ulNumberOfErrorInputs;i++)
{
pdErrorInputMin[i]=1000.0;
pdErrorInputMax[i]=-1000.0;
}
dErrorMin=1000.0;
dErrorMax=-1000.0;
//This code loads the example data and records the minimum and maximum values attained by
//each input
//Each line of the data file consists of a number indicating when the shot occurred in the game
//(i.e. 1 means the first shot of a new game) and the angular error that the player made when
//aiming on that shot
for(i=0;i<ulNumberOfErrorPatterns;i++)
{
//Allocate memory to store the ith input example and check to make sure it succeded
ppdErrorTrainingInputs[i]=new double[ulNumberOfErrorInputs];
if(!ppdErrorTrainingInputs[i])
{
TRACE("failed.\n");
ASSERT(FALSE);
}
//Load the ith example
for(j=0;j<ulNumberOfErrorInputs;j++)
{
*pErrorTrainingData>>ppdErrorTrainingInputs[i][j];
}
//Allocate memory to store the corresponding output (angular aiming error in rads) of the ith pattern
if(!pdErrorTrainingTargets[i])
{
TRACE("failed.\n");
ASSERT(FALSE);
}
//Load it
*pErrorTrainingData>>pdErrorTrainingTargets[i];
if(pdErrorTrainingTargets[i]<dErrorMin)
{
dErrorMin=pdErrorTrainingTargets[i];
}
if(pdErrorTrainingTargets[i]>dErrorMax)
{
dErrorMax=pdErrorTrainingTargets[i];
}
//Maintain a record of the maximum and minimum values of each input
for(j=0;j<ulNumberOfErrorInputs;j++)
{
if(ppdErrorTrainingInputs[i][j]<pdErrorInputMin[j])
{
pdErrorInputMin[j]=ppdErrorTrainingInputs[i][j];
}
if(ppdErrorTrainingInputs[i][j]>pdErrorInputMax[j])
{
pdErrorInputMax[j]=ppdErrorTrainingInputs[i][j];
}
}
}
//Close and delete the exemplar data file
pErrorTrainingData->close();
delete pErrorTrainingData;
//Now scale all inputs to lie between -1.0 and +1.0
for(i=0;i<ulNumberOfErrorPatterns;i++)
{
for(j=0;j<ulNumberOfErrorInputs;j++)
{
//Inputs range between min and max
ppdErrorTrainingInputs[i][j]-=pdErrorInputMin[j];
//Inputs range between 0 and max-min
ppdErrorTrainingInputs[i][j]/=(pdErrorInputMax[j]-pdErrorInputMin[j]);
//Inputs range between 0 and 1
ppdErrorTrainingInputs[i][j]-=0.5;
//Inputs range between -0.5 and +0.5
ppdErrorTrainingInputs[i][j]*=2.0;
//Inputs range between -1.0 and +1.0
}
}
//Scale the distribution model targets to lie between 0 to +1. This needs to be done
//because the positions of the bins in the models are fixed and distributed evenly in this range.
for(i=0;i<ulNumberOfErrorPatterns;i++)
{
pdErrorTrainingTargets[i]-=dErrorMin;
pdErrorTrainingTargets[i]/=(dErrorMax-dErrorMin);
}
TRACE("successful.\n");
//Work out how many examples we're going to have to train the unconditional and conditional models.
//(See below for more details of how this works.)
unsigned long ulNumberOfUnconditionalPatterns=0;
unsigned long ulNumberOfConditionalPatterns=0;
for(i=0;i<ulNumberOfErrorPatterns;i++)
{
if(ppdErrorTrainingInputs[i][0]==-1)
{
ulNumberOfUnconditionalPatterns++;
}
else
{
ulNumberOfConditionalPatterns++;
}
}
//Allocate memory to store seperate data sets that will be used to train the unconditional and conditional
//distribution models. Note that the number of inputs to the conditional distribution is fixed at one in this
//application because we're are assuming that the distribution of aiming errors on each shot is primarily
//affected by the aiming error on the preceding shot.
double *pdUnconditionalTrainingTargets=new double[ulNumberOfUnconditionalPatterns];
double *pdConditionalTrainingTargets=new double[ulNumberOfConditionalPatterns];
double **ppdConditionalTrainingInputs=new double*[ulNumberOfConditionalPatterns];
for(i=0;i<ulNumberOfConditionalPatterns;i++)
{
ppdConditionalTrainingInputs[i]=new double[1];
}
//This section of code partitions the exemplar data into unconditional and conditional data sets. The
//unconditional data set contains the aiming errors made on the first shot of each game. The conditional
//data set consists of input-output pairs, where, for each pair, the input consists of the aiming error
//made on the previous shot, and the output the aiming error made on the current shot. The conditional
//model of aiming errors thus represents the effect of the accuracy of each shot on the accuracy of the next.
double dLastError=0.0;
ulNumberOfUnconditionalPatterns=0;
ulNumberOfConditionalPatterns=0;
for(i=0;i<ulNumberOfErrorPatterns;i++)
{
//This condition is true if the current pattern (example) was the first shot of a new game
if(ppdErrorTrainingInputs[i][0]==-1)
{
//If it was, add it to the data that will be used to train the unconditional distribution
pdUnconditionalTrainingTargets[ulNumberOfUnconditionalPatterns]=pdErrorTrainingTargets[i];
ulNumberOfUnconditionalPatterns++;
}
else
{
//If it wasn't, add it as a target output for the conditional distribution model...
pdConditionalTrainingTargets[ulNumberOfConditionalPatterns]=pdErrorTrainingTargets[i];
//...and set the corresponding input to be equal to the error made on the preceding shot. Note that
//this has to be re-scaled to be between -1 and +1.
ppdConditionalTrainingInputs[ulNumberOfConditionalPatterns][0]=2.0*(dLastError-0.5);
ulNumberOfConditionalPatterns++;
}
//Keep a record of the aiming error that was made on the current shot
dLastError=pdErrorTrainingTargets[i];
}
//Now we've copied this data into two new data sets, we can delete the original
for(i=0;i<ulNumberOfErrorPatterns;i++)
{
delete []ppdErrorTrainingInputs[i];
}
delete []ppdErrorTrainingInputs;
delete []pdErrorTrainingTargets;
TRACE("Training error distribution model...\n");
unsigned long ulIteration=0;
//This do-while loop trains the conditional distribution model. It continually calls the distribution's
//training function until the measured performance is adequate. The process typically requires
//many tens or hundred of thousands of steps and can last several hours. In fact, the trained model provided
//on the CD was produced by training over night using an Intel Celeron 500MHz processor.
do
{
//To perform a training step, tell the model how many patterns (examples) there are
//in the example data and pass it pointers to it.
pErrorDistribution->dTrainingStep(
ulNumberOfConditionalPatterns,
ppdConditionalTrainingInputs,
pdConditionalTrainingTargets
);
//Every hundred training steps provide some feedback on the progress of the model's
//learning (if in debug mode)
if(ulIteration%100==0)
{
TRACE("\n\tIteration: %9u\tTraining Error: %+12.6e\tStep Size: %12.6e",
ulIteration,
pErrorDistribution->dGetPerformance(),
pErrorDistribution->dStepSize);
}
//Keep a count of the number of steps so far
ulIteration++;
}
while(
pErrorDistribution->dGetPerformance()>dErrorModelTerminationError
);
TRACE("\nsuccessful.\n");
//Once we've finished training, we don't need the processed versions of the exemplar data
//so we can delete them
for(i=0;i<ulNumberOfConditionalPatterns;i++)
{
delete []ppdConditionalTrainingInputs[i];
}
delete []ppdConditionalTrainingInputs;
delete []pdConditionalTrainingTargets;
//Train the unconditional distribution
pUnconditionalErrorDistribution->dTrainingStep(ulNumberOfUnconditionalPatterns,pdUnconditionalTrainingTargets);
//Delete the unconditional exemplar data
delete []pdUnconditionalTrainingTargets;
}
TRACE("---------------------------------------------------------------------------------\n");
TRACE("Game starting.\n");
TRACE("---------------------------------------------------------------------------------\n");
}
CTanksDoc::~CTanksDoc()
{
//Deallocate memory:
TRACE("---------------------------------------------------------------------------------\n");
TRACE("Game finishing.\n");
TRACE("---------------------------------------------------------------------------------\n");
//If the scaling information exists, delete it
if(pdMin)
{
delete []pdMin;
}
if(pdMax)
{
delete []pdMax;
}
if(pdErrorInputMin)
{
delete []pdErrorInputMin;
}
if(pdErrorInputMax)
{
delete []pdErrorInputMax;
}
//The neural networks
delete pMLP;
delete pErrorDistribution;
delete pUnconditionalErrorDistribution;
//And the game world
TRACE("Deleting world...\n");
delete pWorld;
TRACE("successful.\n");
//That's it, we've finished!
TRACE("---------------------------------------------------------------------------------\n");
TRACE("Finished.\n");
TRACE("---------------------------------------------------------------------------------\n");
}
BOOL CTanksDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CTanksDoc serialization
void CTanksDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CTanksDoc diagnostics
#ifdef _DEBUG
void CTanksDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CTanksDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTanksDoc commands
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -