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

来源:互联网 发布:网络硬件设备 编辑:程序博客网 时间:2024/06/08 17:05

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

    等等,啥叫训练集?啥叫训练?举个例子,你首先告诉神经网络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 chromosomesvector <SGenome> m_vecPop;//size of populationint m_iPopSize;//amount of weights per chromoint m_iChromoLength;//total fitness of populationdouble m_dTotalFitness;//best fitness this populationdouble m_dBestFitness;//average fitnessdouble m_dAverageFitness;//worstdouble m_dWorstFitness;//keeps track of the best genomeintm_iFittestGenome;//probability that a chromosones bits will mutate.//Try figures around 0.05 to 0.3 ishdouble m_dMutationRate;//probability of chromosones crossing over bits//0.7 is pretty gooddouble m_dCrossoverRate;//generation counterint  m_cGeneration;void    Crossover(const vector<double> &mum,                    const vector<double> &dad,                    vector<double>       &baby1,                    vector<double>       &baby2);void    Mutate(vector<double> &chromo);SGenomeGetChromoRoulette();void  GrabNBest(int            NBest,                  const int       NumCopies,                  vector<SGenome>&vecPop);void  FitnessScaleRank();void  CalculateBestWorstAvTot();void  Reset();public:CGenAlg(int popsize,    doubleMutRat,    doubleCrossRat,    int  numweights);//this runs the GA for one generation.vector<SGenome>Epoch(vector<SGenome> &old_pop);//-------------------accessor methodsvector<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 qxdouble HighestSoFarReal = 0;double LowestSoFar  = 9999999;//2016-07-17 qxdouble LowestSoFarReal  = 9999999;for (int i=0; i<m_iPopSize; ++i){//update fittest if necessaryif (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 necessaryif (m_vecPop[i].dFitness < LowestSoFar)//最小适应度计算{LowestSoFar = m_vecPop[i].dFitness;m_dWorstFitness = LowestSoFar;}m_dTotalFitness+= m_vecPop[i].dFitness;//适应度总和计算}//next chromom_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 vectorwhile(NBest--){for (int i=0; i<NumCopies; ++i){Pop.push_back(m_vecPop[(m_iPopSize - 1) - NBest]);//特别注意,使用精英选择法之前一定要对m_vecPop的适应度//进行从小到大的排序,这里没有排序是因为在别的地方排过序了。  }}}

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



0 0
原创粉丝点击