游戏编程中的人工智能技术-神经网络入门(二)

     上一节介绍了代码的第一个部分:神经网络部分。那么光有神经网络就可以工作了吗?还不行,因为还没有设计神经网络的训练方法,即还没有设计神经网络权重的更新方法。在传统的有监督的神经网络中,先给一个训练集让神经网络进行训练。

    等等,啥叫训练集?啥叫训练?举个例子,你首先告诉神经网络1+1=2,1+2=3,1+3=4,这个就是训练集,你不仅告诉了神经网络问题,你还把结果也告诉它了,神经网络会根据问题更新权重来达到已知的结果,也就是说神经网络在输入1+1的情况下不断更新自己的权重,最终能输出2,这个就叫训练。当训练结束后,神经网络就可以自己计算未知的算式了,比如2+5=?,这个不在训练集内,也就是这个算式答案是未知的,但是神经网络经过训练以后,已经可以举一反三,算出结果了。不信?请参考LSTM-RNN。你也可以试试。

     只可惜这个世界上本来很多东西就是未知的,从哪来的训练集?所以,在这里我们着重研究第二种:无监督的神经网络。

     等等,有监督的神经网络好歹还有个训练集让其训练更新权重,现在连训练集都没了你让神经网络盲人摸象呀?别慌,在没有训练集的情况下,另一个利器:适应度函数就出现了。神经网络通过不断的更新权重使得适应度函数逐步优化。当适应度函数满足某个条件后,就算训练完成了。而如何设计适应度函数,以及适应度函数如何优化呢?这就得靠我们的老朋友:遗传算法了。

    言归正传,现在介绍代码中的第二个部分,遗传算法部分:CGenAlg。

CGenAlg类:

class CGenAlg
{
private:
	
	//this holds the entire population of chromosomes
	vector <SGenome>	 m_vecPop;

	//size of population
	int m_iPopSize;
	
	//amount of weights per chromo
	int m_iChromoLength;

	//total fitness of population
	double m_dTotalFitness;

	//best fitness this population
	double m_dBestFitness;

	//average fitness
	double m_dAverageFitness;

	//worst
	double m_dWorstFitness;

	//keeps track of the best genome
	int		m_iFittestGenome;

	//probability that a chromosones bits will mutate.
	//Try figures around 0.05 to 0.3 ish
	double m_dMutationRate;

	//probability of chromosones crossing over bits
	//0.7 is pretty good
	double m_dCrossoverRate;

	//generation counter
	int	  m_cGeneration;


	void    Crossover(const vector<double> &mum,
                    const vector<double> &dad,
                    vector<double>       &baby1,
                    vector<double>       &baby2);
	

	void    Mutate(vector<double> &chromo);
	
	SGenome	GetChromoRoulette();

	void	  GrabNBest(int	            NBest,
	                  const int       NumCopies,
	                  vector<SGenome>	&vecPop);

	void	  FitnessScaleRank();

	void	  CalculateBestWorstAvTot();

	void	  Reset();



public:
		
	CGenAlg(int 		popsize,
			    double	MutRat,
			    double	CrossRat,
			    int	  	numweights);

	//this runs the GA for one generation.
	vector<SGenome>	Epoch(vector<SGenome> &old_pop);


	//-------------------accessor methods
	vector<SGenome>	GetChromos()const{return m_vecPop;}
	double			    AverageFitness()const{return m_dTotalFitness / m_iPopSize;}
	double		    	BestFitness()const{return m_dBestFitness;}
	//double		    	RealBestFitness()const{return m_dBestFitness/m_iTicks;}

	
};
这个在遗传算法入门里已经说明了,所以不再详述。唯一要注意的有两个函数:CalculateBestWorstAvTot()和GrabNBest()。

void CGenAlg::CalculateBestWorstAvTot()//用于计算种群中的最大适应度,最小适应度,平均适应度,以及适应度总和
{
	m_dTotalFitness = 0;
	
	double HighestSoFar = 0;
	//2016-07-17 qx
	double HighestSoFarReal = 0;
	double LowestSoFar  = 9999999;
	//2016-07-17 qx
	double LowestSoFarReal  = 9999999;
	
	for (int i=0; i<m_iPopSize; ++i)
	{
		//update fittest if necessary
		if (m_vecPop[i].dFitness > HighestSoFar)//最大适应度计算
		{
			HighestSoFar	 = m_vecPop[i].dFitness;
			
			m_iFittestGenome = i;

			m_dBestFitness	 = HighestSoFar;
		}
		//2016-07-17 qx
/*			if (m_vecPop[i].dFitness/m_iTicks> HighestSoFarReal)
		{
			HighestSoFarReal	 = m_vecPop[i].dFitness/m_iTicks;
			
			//m_iFittestGenome = i;

			m_dBestFitnessReal	 = HighestSoFarReal;
		}
*/
		//update worst if necessary
		if (m_vecPop[i].dFitness < LowestSoFar)//最小适应度计算
		{
			LowestSoFar = m_vecPop[i].dFitness;
			
			m_dWorstFitness = LowestSoFar;
		}
		
		m_dTotalFitness	+= m_vecPop[i].dFitness;//适应度总和计算
		
		
	}//next chromo
	
	m_dAverageFitness = m_dTotalFitness / m_iPopSize;//平均适应度计算
}

void CGenAlg::GrabNBest(int	            NBest,
                        const int	      NumCopies,
                        vector<SGenome>	&Pop)
{
  //add the required amount of copies of the n most fittest 
	//to the supplied vector
	while(NBest--)
	{
		for (int i=0; i<NumCopies; ++i)
		{
			Pop.push_back(m_vecPop[(m_iPopSize - 1) - NBest]);//特别注意,使用精英选择法之前一定要对m_vecPop的适应度
															//进行从小到大的排序,这里没有排序是因为在别的地方排过序了。
	  }
	}
}

其他请参见“遗传算法入门”内容



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值