開學了,各種忙起來了…
上一篇介紹了AForge.NET在人工神經網絡上的一點點使用,但是老覺不過癮。matlab用着實在不習慣,就又琢磨了一下進化計算。
進化計算簡介
進化計算算不上新的方法了,已經有大量研究人員作出了努力,這導致了大量的進化計算算法出現。他們不僅研究算法本身,還致力於擴大算法的應用范圍。
眾所周知,現實世界存在大量復雜問題,它們中一部分無法用常規方法在合理的時間內獲得精確解,而另一部分甚至沒有行之有效的解決方案。
最著名的例子就是TSP問題,該問題意在尋求單一旅行者由起點出發,通過所有給定的需求點之后,最后再回到原點的最小路徑成本。
而進化計算可以應用於這些問題,因為大多數情況下這類問題允許我們在合理時間內給出較優解。
進化計算並不能保證找到特定問題的最佳解決方案,但是可以找到一個很好的解決辦法,該方案可能是非常接近的最佳解決方案。
進化算法的分支和運用
進化計算是一些算法的統稱,主要包括Genetic Algorithms (GA遺傳算法), Genetic Programming (GP遺傳規划) 和 Gene Expression Programming (GEP基因表達式編程)。
進化算法主要可以解決以下類別問題:
1.函數優化
2.符號回歸
3.時間序列預測
4.旅行商問題
遺傳算法簡介
Genetic Algorithms(遺傳算法)最早由John Holland基於進化觀點在1960提出。從那時起相關研究不斷進行。
大部分研究成果運用到很多領域,並取得了很好的效果。雖然遺傳算法的歷史悠久,但是目前還是不斷有新的方法被提出,擴寬了運用領域。
遺傳算法基於達爾文的“適者生存”理論和遺傳學機理的生物進化過程。算法作用於每一代的基因,而每個基因都是問題的可能解。
一般遺傳算法的運用有以下4個步驟:
1.隨機選擇個體,並進行交叉
2.變異
3.計算適應度
4.選擇下一個世代的個體
算法的停止條件一般是指定的迭代數目完成或者得到一個可靠解。
交叉算法中最簡單的單點交叉,即隨機選擇兩個基因的一個點,交換兩個基因的一部分。
| 基因1:0 0 0 1 1 0 1 基因2:1 0 0 1 0 0 0 結果 :0 0 0 1 0 0 0 |
還有一種不錯的方式是兩點交叉,隨機選擇兩個基因的兩個點,交換兩個點之間的部分。
變異一般用單點變異
| 基因1:0 1 0 0 1 0 1 結果 :0 1 0 0 0 0 1 |
用Aforge.Net實現遺傳算法
我覺得Aforge.Net的優越就在於不是提供特定的實現,而是重在提供一個可以擴展的框架,方便學習和研究。
我以函數最優化為例。函數我選用:x^0.5+sin(x/23)*30 范圍從0到100
先用matlab估計一下最優值
建立適應度評價函數;
public class MyOwnFunction : OptimizationFunction1D
{
public MyOwnFunction()
: base(new AForge.Range(0, 100))
{
}
public override double OptimizationFunction(double x)
{
return Math.Sqrt(x)+ Math.Sin(x/23)*30;
}
}
遺傳算法主要的類是Population類。它容納了所有的染色體,提供了適應度評價方法、編碼方式和選擇方式。
MyOwnFunction f = new MyOwnFunction();
Population population = new Population(40,new BinaryChromosome(32),f,new EliteSelection());
這段代碼的意思是適應度函數使用自定義的MyOwnFunction,編碼使用二進制編碼,長度為32,每個世代個體數目為40,選擇方式為“精英取舍”。
這個名字很霸氣,其實就是排個序,然后把不好的移除而已,代碼如下;
public class EliteSelection : ISelectionMethod
{
/// <summary>
/// Initializes a new instance of the <see cref="EliteSelection"/> class.
/// </summary>
public EliteSelection( ) { }
/// <summary>
/// Apply selection to the specified population.
/// </summary>
///
/// <param name="chromosomes">Population, which should be filtered.</param>
/// <param name="size">The amount of chromosomes to keep.</param>
///
/// <remarks>Filters specified population keeping only specified amount of best
/// chromosomes.</remarks>
///
public void ApplySelection( List<IChromosome> chromosomes, int size )
{
// sort chromosomes
chromosomes.Sort( );
// remove bad chromosomes
chromosomes.RemoveRange( size, chromosomes.Count - size );
}
}
一般情況可以使用賭輪盤的方式進行下一個世代的選擇。完整代碼:
Console.WriteLine("Start!");
MyOwnFunction f = new MyOwnFunction();
Population population = new Population(40,
new BinaryChromosome(32),f,new EliteSelection());
population.RunEpoch();
double goodX=f.Translate(population.BestChromosome);
Console.WriteLine("Best Chromosome === >{0}", goodX);
Console.WriteLine("Best Result === >{0}", f.OptimizationFunction(goodX));
Console.WriteLine("Over!");
Console.ReadLine();
效果:
基本符合,和matlab估算的值差了0.0002左右。
如果要輸出最后世代的所有結果,可以使用
for (int i = 0; i < population.Size; i++)
{
Console.WriteLine("chromosome{0} == >{1}", i, f.Evaluate(population[i]));
}
寫在最后:
1.個人覺得AForge.NET用着比matlab方便,因為它的整體架構比較統一,而不像matlab是由工具箱提供的,使用風格迥異。
2.AForge.Net的進化計算這塊遠遠比神經網絡部分完整,基本不需要自己實現什么。
3.AForge.Fuzzy中的隸屬度函數的表示實現不夠豐富,只實現了中間型的兩種,我擴寫了其他種類的,等整理好了就發出來。





