NO IMAGE

貼上(二)的地址:第二章

這次基於上一章所講主要講解一下遺傳演算法的程式碼:

   先說一下遺傳演算法的實現所需要的步驟:

   需要知道這幾點:

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

因為我這裡都在分開講,最後會結合在一起講,其他細節先不需要考慮 ,主要理解遺傳