人工智能开发,Unity的神经网络+遗传算法(三)
发表于2017-12-19
这次基于上一篇所讲主要讲解一下遗传算法的代码:
先说一下遗传算法的实现所需要的步骤:
需要知道这几点:
1、种群:
生物以种群形式进行(这也是游戏中训练的难点,并无法大规模的训练);
2、个体:
组成种群的单个生物;
3、基因:
一个遗传因子(这里我们是单个的权重);
4、染色体:
一组基因(也就是这一组权重);
5、 生存竞争,适者生存:
这里我们需要适应度来决定哪个更能适应这个环境,从而选择NB的基因进行繁殖;适应度低的也就是上一章讲的靠山下的给正义掉;从而选择优秀的基因进行繁殖;
6、 遗传和变异:
新个体会遗传父母双方各一部分的基因,同时有一定的概率发生基因变异。(这个父母双方)这里我们采用一个轮盘赌的算法来决定这对夫妇;
遗传步骤:
1、随机种群基因:因为第一组的是弱智他不知道干什么;这需要在开始的时候初始化;
2、然后开始按照第一部分的基因开始神经网络判定和行为;
3、根据规则的一顿击杀评分来计算出他的适应度,因为这里只讲遗传算法的脚本,SO不多讲;
4、到时间后进行新的一波繁殖,根据适应度;也就是只找到了两只优秀的坦克;
5、繁殖过程需要经过交叉,变异和遗传;
6、第二轮经过优秀的坦克的基因继续进行行为;
下面贴代码:(代码已经在我个人认为的难点和属性做了注释)
using System;
using System.Collections.Generic;
using System.Linq;
public class Geneticalgorithm {
//选择的方法
public int Count;//种群数量
public List<IGizeable> ListIG; //储存种群所有个体
public double Mutation; //变异概率
public static Random _random = new Random();
public Geneticalgorithm(int poCount, double mutate) {
this.Count = poCount;
this.Mutation = mutate;
ListIG = new List<IGizeable>(poCount);
}
private List<IGizeable> GetAThera() { //获取同样种群数量的对数的夫妇来用来繁殖新的群体
var res = new List<IGizeable>(2 * Count);
var sum = ListIG.Sum(
itme => itme.fitness
); //获取这个群体所有适应度的总和
var fitnessgote = new double[Count]; //用来储存每一个 单体生物的适应度概率;
for (var i = 0; i < fitnessgote.Length; i++) fitnessgote[i] = ListIG[i].fitness / sum; //计算每一个适应度的概率
fitnessgote.OrderByDescending(
x => x
);
var counter = 0;
while (counter < Count) {//循环不停的配对 每一对基本上都不一样
var leftGen = RandomIndex(fitnessgote); //获取适应度最好的那个个体下标;
var rightGen = RandomIndex(fitnessgote);//获取另一个 两个不一样
if (leftGen == rightGen) continue;
res.Add(ListIG[leftGen].Reproduce());
res.Add(ListIG[rightGen].Reproduce());
counter ++;
}
return res;
}
public void Cross(IGizeable mom, IGizeable dad) {//交叉
var momW = mom._weightAndBasi;
var dadW = dad._weightAndBasi;
var n = _random.Next(momW.Count);
for (var i = 0; i < momW.Count; i++) {
if (i < n)
momW[i] = dadW[i];
else
dadW[i] = momW[i];
}
mom._weightAndBasi = momW;
dad._weightAndBasi = dadW;
}
private void AllReproduce(List<IGizeable> pairs) {//繁殖新一代群体基因;
ListIG.Clear();
for (var i = 0; i < pairs.Count; i += 2) {
Cross(pairs[i], pairs[i + 1]);
Muta(pairs[i]);
ListIG.Add(pairs[i]);
}
}
public void Evolve(double[] newFitnesses) {//进化
for (var i = 0; i < newFitnesses.Length; i++) ListIG[i].fitness = newFitnesses[i];
AllReproduce(GetAThera());
}
public void Randomlation(double min = -1.0, double max = 1.0) {//随机种群 在训练初始化时调用
for (var i = 0; i < Count; i++)
Randommm(ListIG[i], min, max);
}
private int RandomIndex(IList<double> probs) { //算法返回下标
double top = 0;
var randomValue = _random.NextDouble();
for (var i = 0; i < probs.Count; i++) {
var bot = top;
top += probs[i];
if (randomValue >= bot && randomValue <= top) return i;
}
return 0;
}
public void Muta(IGizeable gen) {//变异
var w = gen._weightAndBasi;
for (var i = 0; i < w.Count; i++)
if (_random.NextDouble() < Mutation) w[i] += _random.NextDouble() * 2 - 1;
gen._weightAndBasi = w;
}
private static void Randommm(IGizeable gen, double min, double max) {
var w = gen._weightAndBasi;
for (var i = 0; i < w.Count; i++) {
w[i] = _random.NextDouble() * (max - min) + min;
}
gen._weightAndBasi = w;
}
}
public interface IGizeable {//优化遗传接口 用来储存继承这个接口的所有个体;
List<double> _weightAndBasi { get; set; } //一组遗传基因(这里也就是这组权重和偏移);
double fitness { get; set; } //适应度 用来决定淘汰的是谁;
IGizeable Reproduce(); //繁殖的方法;
}
