游戏编程中的人工智能技术-神经网络入门(二)
2016-07-19 12:46
477 查看
上一节介绍了代码的第一个部分:神经网络部分。那么光有神经网络就可以工作了吗?还不行,因为还没有设计神经网络的训练方法,即还没有设计神经网络权重的更新方法。在传统的有监督的神经网络中,先给一个训练集让神经网络进行训练。
等等,啥叫训练集?啥叫训练?举个例子,你首先告诉神经网络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;//平均适应度计算
}
其他请参见“遗传算法入门”内容
等等,啥叫训练集?啥叫训练?举个例子,你首先告诉神经网络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的适应度 //进行从小到大的排序,这里没有排序是因为在别的地方排过序了。 } } }
其他请参见“遗传算法入门”内容
相关文章推荐
- 职责链模式(Chain Of Responsibility)
- 硅谷再次拥抱人工智能,真的是新纪元的开始?
- Error: Failed to load plugin angular: Cannot find module 'eslint-plugin-angular'
- 设置Grails中的domain的字段默认是否允许为空
- 游戏AI设计经验分享——行为树的研究
- main(int argc,char* argv[ ])
- 线程间通信方式(wait和notify的使用)
- 使用aidl的项目结构以及小的注意事项
- ubuntu14.04安装pycurl报错: __main__.ConfigurationError: Could not run curl-config: [Errno 2] No such file or directory
- IntelliJ 创建main函数快捷
- AIX查看sshd状态 启动sshd 关闭sshd
- Handler new Handler()和new Handler(Looper.getMainLooper())的区别
- leetcode--011 Container With Most Water
- hdoj1702ACboy needs your help again!(栈和队列)
- Solaris与AIX操作系统syslog配置
- 朴素贝叶斯学习笔记
- 百度吴恩达:人工智能技术融入业务的两个途径
- Mailserver能发不能收的故障处理
- Kali dpkg-source: warning: failed to verify signature on xxx
- Error Domain=com.alamofire.error.serialization.response Code=-1016 "