人工智能开发,Unity的神经网络+遗传算法(三)

发表于2017-12-19
评论0 2.1k浏览

这次基于上一篇所讲主要讲解一下遗传算法的代码:

      先说一下遗传算法的实现所需要的步骤:

      需要知道这几点:

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();     //繁殖的方法;  
    }  

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引