游戏编程中的人工智能技术
.(连载之六)
{ vector<int> SplitPoints; int WeightCounter = 0; // 对每一层 for (int i=O; i<m_NumHiddenLayers + 1; ++i) { // 对每一个神经细胞 for (int j=O; j<m_vecLayers[i].m_NumNeurons; ++j) { // 对每一个权重 for (int k=O; k<m_vecLayers[i].m_vecNeurons[j].m_NumInputs; ++k) { ++WeightCounter; } } } } { // 如果超过了杂交率,就不再进行杂交,把2个上代作为2个子代输出 // 如果2个上辈相同,也把它们作为2个下辈输出 if ( (RandFloat() > m_dCrossoverRate) || (mum == dad)) { baby1 = mum; baby2 = dad; } int index1 = RandInt(0, m_vecSplitPoints.size()-2); { if ( (i<cp1) || (i>=cp2) ) { babyl.push_back(mum[i]); baby2.push_back(dad[i]); } { baby1.push_back(dad[1]); baby2.push_back(mum[1]); } } }
根据我的经验,我已发现,在进行杂交时,把神经细胞当作一个不可分割的单位,比在染色体长度上任意一点分裂基因组,能得到更好的结果。
把点积和Vec2Dsign二者联合起来,就能把输入的精华提纯出来,使网络只需接受一个输入就行了。下面就是新的CMinesweeper::Update函数有关段落的代码形式: // 计算到最邻近地雷的向量 // 将它规范化 //计算扫雷机视线向量和它到最邻近地雷的向量的点积。它给出了我们要面对最邻近地雷所需转动的角度 // 计算正负号 运行一下光盘Chapter7/Smart Sweepers v1.1目录下的可执行程序executable,你就知道经过以上2个改进,能为演化过程提速多少。 需要注意的一桩重要事情是,带有4个输入的网络要花很长时间进行演化,因为它必须在各输入数据之间找出更多的关系才能确定它应如何行动。事实上,网络实际就是在学习怎么做点积并确定它的正负极性。因此,当你设计自己的网络时,你应仔细权衡一下,是由你自己预先来计算许多输入数据好呢(它将使CPU负担增加,但导致进化时间加快)还是让网络来找输入数据之间的复杂关系好(它将使演化时间变长,但能使CPU减少紧张)? 5 结束语(last words) 我希望你已享受到了你第一次攻入神经网络这一奇妙世界的快乐。我打赌你一定在为如此简单就能使用它们而感到惊讶吧,对吗?我想我是猜对了。 在下面几章里我将要向你介绍更多的知识,告诉你一些新的训练手段和演绎神经网络结构的更多的方法。但首先请你利用本章下面的提示去玩一下游戏是有意义的。
6 练习题 (Stuff to Try) 1。 在v1.0中,不用look-at向量作为输入,而改用旋转角度θ作为输入,由此就可以使网络的输入个数减少成为1个。请问这对神经网络的演化有什么影响?你对此的看法怎样? 2。 试以扫雷机的位置(x1,y1)、和扫雷机最接近的地雷的位置(x2,y2)、以及扫雷机前进方向的向量(x3,y3)等6个参数作为输入,来设计一个神经网络,使它仍然能够演化去寻找地雷。 3。 改变激励函数的响应。试用O.1 - O.3 之间的低端值,它将产生和阶跃函数非常相像的一种激励函数。然后再试用高端值,它将给出较为平坦的响应曲线。考察这些改变对演化进程具有什么影响? 4。 改变神经网络的适应性函数,使得扫雷机不是去扫除地雷,而是要演化它,使它能避开地雷。 5。 理一理清楚有关遗传算法的各种不同设置和运算中使你感到模糊的东西! 6。 加入其他的对象类型,比如人。给出一个新环境来演化扫雷机,使它能避开人,但照样能扫除地 雷。(这可能没有你想象那么容易!)
(第7章完。但下面还有一篇是【下栽软件】篇) |
|