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

📄 cconditionaldistribution.cpp

📁 C人工智能游戏开发的一些实例源代码 C Game development in artificial intelligence source code of some examples
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//Tanks
//Copyright John Manslow
//29/09/2001

////////////////////////////////////////////////////
//Remove this include if not compiling under windows
#include "stdafx.h"
#define new DEBUG_NEW
#define false FALSE
////////////////////////////////////////////////////
#include "CConditionalDistribution.h"
#include "stdlib.h"
#include "math.h"
#include "stdio.h"
#include "assert.h"
#include "fstream.h"
#include "time.h"

//Where backups will be made during training (guards against crashes, fires, etc.)
#define FileForBackupSaves "ErrorTrainingBackup.cdm"

CConditionalDistribution::CConditionalDistribution(
			const unsigned long ulNewNumberOfInputs,
			const unsigned long ulNewNumberOfHiddenNodes,
			const unsigned long ulNewNumberOfOutputs
			)
{
	TRACE("\t\tCreating conditional distribution...");

	//Record the structure (number of inputs, hidden neurons, and bins) of the model
	ulNumberOfInputs=ulNewNumberOfInputs;
	ulNumberOfHiddenNodes=ulNewNumberOfHiddenNodes;
	ulNumberOfOutputs=ulNewNumberOfOutputs;

	//Allocate memory to store the model's structure
	AllocateMemory();

	//Reset the learning procedure
	Reset();

	//Set these character pointers to NULL so we know they're not used yet
	pTrainingStartTime=NULL;
	pTrainingStartDate=NULL;

	TRACE("successful.\n");
}

void CConditionalDistribution::AllocateMemory(void)
{
	unsigned long i;

	//Allocate memory to store the current values of the input to hidden layer weights 
	//of the neural network component of the model and their best values
	ppdwih=new double*[ulNumberOfHiddenNodes];
	ppdBestwih=new double*[ulNumberOfHiddenNodes];
	assert(ppdwih && ppdBestwih);
	for(i=0;i<ulNumberOfHiddenNodes;i++)
	{
		ppdwih[i]=new double[ulNumberOfInputs+1];
		ppdBestwih[i]=new double[ulNumberOfInputs+1];
		assert(ppdwih[i] && ppdBestwih[i]);
	}

	//Do the same for the hidden to output layer weights
	ppdwho=new double*[ulNumberOfOutputs];
	ppdBestwho=new double*[ulNumberOfOutputs];
	assert(ppdwho && ppdBestwho);
	for(i=0;i<ulNumberOfOutputs;i++)
	{
		ppdwho[i]=new double[ulNumberOfHiddenNodes+1];
		ppdBestwho[i]=new double[ulNumberOfHiddenNodes+1];
		assert(ppdwho[i] && ppdBestwho[i]);
	}
}

void CConditionalDistribution::DeallocateMemory(void)
{
	//Deallocate the storage used for current and best weight values.
	unsigned long i;
	for(i=0;i<ulNumberOfHiddenNodes;i++)
	{
		delete []ppdwih[i];
		delete []ppdBestwih[i];
	}
	delete []ppdwih;
	delete []ppdBestwih;
	for(i=0;i<ulNumberOfOutputs;i++)
	{
		delete []ppdwho[i];
		delete []ppdBestwho[i];
	}
	delete []ppdwho;
	delete []ppdBestwho;

	//If we've recorded the time and date of the start of training, delete them too.
	if(pTrainingStartTime)
	{
		delete []pTrainingStartTime;
	}
	if(pTrainingStartDate)
	{
		delete []pTrainingStartDate;
	}
}

CConditionalDistribution::~CConditionalDistribution()
{
	TRACE("\t\tDestroying conditional distribution...");
	DeallocateMemory();
	TRACE("successful.\n");
}

void CConditionalDistribution::Reset(void)
{
	unsigned long i,j;

	//Give the neural network component of the model weights random values between -1 and +1.
	//Since this effectively resets training the best recorded weights (stored in ppdBest...) are set 
	//to the new random values.
	for(i=0;i<ulNumberOfHiddenNodes;i++)
	{
		for(j=0;j<ulNumberOfInputs+1;j++)
		{
			ppdwih[i][j]=2.0*(double(rand())/double(RAND_MAX)-0.5);
			ppdBestwih[i][j]=ppdwih[i][j];
		}
	}

	//Do the same for the hidden to output layer weights
	for(i=0;i<ulNumberOfOutputs;i++)
	{
		for(j=0;j<ulNumberOfHiddenNodes+1;j++)
		{
			ppdwho[i][j]=2.0*(double(rand())/double(RAND_MAX)-0.5);
			ppdBestwho[i][j]=ppdwho[i][j];
		}
	}

	//Reset the best recorded error to an impossible value (error is always positive) to indicate
	//that no training has taken place with the current values of the weights.
	dBestError=-1.0;

	//Reset the step size to a conservative value.
	dStepSize=0.001;
}

//This function trains the conditional distribution model by using a perturbation search (as discussed in the
//book Game Programming Gems 2) to search for weights its neural network component 
//that are most consistent with the exemplar data passed to this function 
double CConditionalDistribution::dTrainingStep(
							const unsigned long ulNumberOfPatternsInTrainingSet,
							double ** const ppdTrainingInputs,
							double * const ppdTrainingTargets
							)
{
	unsigned long i,j;
	double dNewError;

	//If dBestError=-1, this is the first training step so we need to do some initialisation
	if(dBestError==-1.0)
	{
		//Make sure we deallocate memory pointed to by these pointers (if any) before we 
		//reassign them
		if(pTrainingStartTime)
		{
			delete []pTrainingStartTime;
		}
		if(pTrainingStartDate)
		{
			delete []pTrainingStartDate;
		}

		//Record time and date that training started.
		pTrainingStartTime=new char[256];
		_strtime(pTrainingStartTime);
		pTrainingStartDate=new char[256];
		_strdate(pTrainingStartDate);

		//Measure the performance of the model with the weights set to their current values.
		//Since this is the only performance measurement so far, it must be the best. Store it.
		dBestError=dGetPerformance(
									ulNumberOfPatternsInTrainingSet,
									ppdTrainingInputs,
									ppdTrainingTargets
									);
	}

	//Perturb the model's weights by adding a random value between +dStepSize and -StepSize
	//to each one.
	for(i=0;i<ulNumberOfHiddenNodes;i++)
	{
		for(j=0;j<ulNumberOfInputs+1;j++)
		{
			ppdwih[i][j]+=dStepSize*(double(rand())/double(RAND_MAX)-0.5)*2.0;
		}
	}

	//And for the hidden to output layer weights
	for(i=0;i<ulNumberOfOutputs;i++)
	{
		for(j=0;j<ulNumberOfHiddenNodes+1;j++)
		{
			ppdwho[i][j]+=dStepSize*(double(rand())/double(RAND_MAX)-0.5)*2.0;
		}
	}

	//Measure the performance of the model with its new weights
	dNewError=dGetPerformance(
								ulNumberOfPatternsInTrainingSet,
								ppdTrainingInputs,
								ppdTrainingTargets
								);

	//If its performance has deteriorated (the new error is larger)
	if(dNewError>dBestError)
	{
		//Reduce the size of the perturbation a bit - we need to be more conservative!
		dStepSize*=0.9;

		//Restore the weights back to their old values
		for(i=0;i<ulNumberOfHiddenNodes;i++)
		{
			for(j=0;j<ulNumberOfInputs+1;j++)
			{
				ppdwih[i][j]=ppdBestwih[i][j];
			}
		}
		for(i=0;i<ulNumberOfOutputs;i++)
		{
			for(j=0;j<ulNumberOfHiddenNodes+1;j++)
			{
				ppdwho[i][j]=ppdBestwho[i][j];
			}
		}
	}
	else
	{
		//Otherwise the new weights performed at least as well as the old ones, so record the
		//performance of the model with its new weights,
		dBestError=dNewError;

		//Increase the step size a little - we're doing well and can afford to be more 
		//adventurous.
		dStepSize*=1.2;

		//Record the new weights as the best so far discovered
		for(i=0;i<ulNumberOfHiddenNodes;i++)
		{
			for(j=0;j<ulNumberOfInputs+1;j++)
			{
				ppdBestwih[i][j]=ppdwih[i][j];
			}
		}
		for(i=0;i<ulNumberOfOutputs;i++)
		{
			for(j=0;j<ulNumberOfHiddenNodes+1;j++)
			{
				ppdBestwho[i][j]=ppdwho[i][j];
			}
		}

		//Save the model just in case we have a crash (or power failure or something)
		Save(FileForBackupSaves);
	}

	//Tell the calling function what the performance of the model currently is, so it can 
	//decide whether to continue training. This function always leaves the model with the 
	//best weights found so far, so there's no need to restore them externally at the end of 
	//training
	return dBestError;
}

//This function uses the neural network component of the conditional distribution model to calculate
//the probability associated with each bin in the distribution. This is done simply by querying the neural
//network with the distribution inputs because it has one output for each bin
double *CConditionalDistribution::pdGetBinProbabilities(
							const double * const pdInputs
							)
{
	//For detailed comments on querying a neural network, see CMLP.cpp
	unsigned long i,j;

	//Declare storage for the activities of the hidden and output neurons
	double *pdah=new double[ulNumberOfHiddenNodes];
	double *pdao=new double[ulNumberOfOutputs];

	//Declare storage for the amount of stimulation coming onto a neuron
	double dStimulus;

	//Calculate the activity of the network's hidden neurons.
	for(i=0;i<ulNumberOfHiddenNodes;i++)
	{
		dStimulus=ppdwih[i][0];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -