在Ignite中使用遺傳算法 頂 原

本系列共6篇文章,會通過一些代碼示例,講解如何在Ignite中使用機器學習庫。

在第二篇中主要講解遺傳算法,這個算法是今年早些時候(2018)捐贈給Apache基金會的。

遺傳算法是一種通過模擬生物進化過程來解決優化問題的一種方法。 非常適合於以最優的方式檢索大量複雜的數據集,在現實世界中,遺傳算法的典型應用場景包括:

  • 汽車設計
  • 計算機遊戲
  • 機器人技術
  • 金融投資
  • 物流配送

遺傳算法中通常使用生物學術語。比如,一個種羣染色體組成。染色體是解決問題的可能方法。染色體由基因組成。基因可以結合以獲得新的染色體,等等。一個完整的詞彙表可以在Apache Ignite 遺傳算法文檔中找到。

遺傳算法中,有幾個主要的操作,稱爲適應度計算交叉變異,染色體包含適應度得分,用於比較不同的解。結合基因產生新染色體的過程稱爲交叉。變異是染色體內某些基因被更新以產生新特性的過程,如圖1所示: 遺傳算法使用ComputeTask執行操作,並且注意圖1和Ignite的計算網格之間的相似度,如圖2所示: 在Ignite中,遺傳算法是更大的機器學習庫的一部分。

在圖3中,可以看到遺傳算法中各個操作的執行順序: 在圖3中會看到有一個終止步驟,這對整個過程至關重要。

通常的編程示例中,都會有一個“Hello World”應用,Ignite的遺傳算法中,也有這樣一個應用,下面就一步步看看這個應用,看看它是如何工作的。

"Hello World"示例

這個示例的目標是產生"HELLO WORLD"這樣的輸出,注意這裏都是大寫字母。

下面的部分會遵循圖3中的步驟,通過一些小的代碼片段來聚焦,完整的代碼在GitHub上,這也是整個Ignite機器學習庫的一部分。

初始化

首先,執行一些初始化操作:

ignite = Ignition.start("examples/config/example-ignite.xml");
gaConfig = new GAConfiguration();

在上面的代碼中,可以通過GAConfiguration()來對遺傳算法的行爲進行配置。

下一步,需要定義一個基因池,如下所示:

List<Gene> genes = getGenePool();

"HELLO WORLD"這個目標短語由A-Z和空格字符組成,因此,將每個基因建模爲字符,然後創建大小爲27的基因池,然後像下面這樣對基因池進行初始化:

private static List<Gene> getGenePool() {
   List<Gene> list = new ArrayList();

   char[] chars = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
      'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
      'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' '};

   for (int i = 0; i < chars.length; i++) {
      Gene gene = new Gene(new Character(chars[i]));
      list.add(gene);
   }
   return list;
}

之前已經提過,染色體是一個優化解,由若干基因組成。在本示例中,這個優化解是短語“HELLO WORLD”,它由11個基因組成,因此可以將染色體的長度設定爲11,如下所示:

gaConfig.setChromosomeLength(11);

適應度計算

要比較各個不同的解然後找到最優解,需要爲每個染色體確定一個適應度得分,下面的代碼可以做到這一點:

public class HelloWorldFitnessFunction implements IFitnessFunction {
    private String targetString = "HELLO WORLD";

    public double evaluate(List<Gene> genes) {

        double matches = 0;

        for (int i = 0; i < genes.size(); i++) {
            if (((Character)(genes.get(i).getValue())).equals(targetString.charAt(i))) {
                matches = matches + 1;
            }
        }
        return matches;
    }
}

可以看到,目標染色體爲“HELLO WORLD”,然後代碼一個個基因進行檢查,來確認其是否匹配目標值。

終止條件

本示例中,當染色體匹配"HELLO WORLD"時,就會發現已經找到了最優解,這時代碼會檢查這個條件,如下所示:

boolean isTerminate = true;

...

if (!(fittestChromosome.getFitnessScore() > 10)) {
   isTerminate = false;
}

return isTerminate;

交叉和變異

最後一步是種羣的進化,如下所示:

Chromosome fittestChromosome = gaGrid.evolve();

運行遺傳算法

最後,可以運行下代碼,大概輸出如下:

##########################################################################################
Generation: 255
Fittest is Chromosome Key: Chromosome [fitnessScore=11.0, id=131, genes=[8, 5, 12, 12, 15, 27, 23, 15, 18, 12, 4]]
Chromosome: Chromosome [fitnessScore=11.0, id=131, genes=[8, 5, 12, 12, 15, 27, 23, 15, 18, 12, 4]]
HELLO WORLD
Avg Chromosome Fitness: 5.668
##########################################################################################

Web控制檯

也可以通過Ignite的Web控制檯執行一些遺傳算法的查詢,怎麼弄呢?可以通過命令行或者IDE啓動一個集羣節點,節點啓動之後,啓動Ignite的Web代理,圖4中顯示了Web代理正在運行: 下一步,使用一個Web瀏覽器接入http://console.gridgain.com,登錄之後,轉到Queries > Create new notebook,命名並且創建新的記事本之後,就有了一個執行SQL查詢的接口,如圖5所示: 在遺傳算法的文檔中提到:

通過添加自定義的SQL函數來改進遺傳優化結果,遺傳算法改進了知識的發現。結果集中的列是由單個遺傳樣本的染色體大小動態驅動的。

下面的SQL函數可以使用:

  • getSolutionsDesc():根據適應度得分降序獲取優化解;
  • getSolutionsAsc():根據適應度得分升序獲取優化解;
  • getSolutionById(key):通過染色體主鍵獲取優化解。

可以嘗試下下面的示例:

select * from "geneCache".getSolutionsDesc();

產生的輸出如圖6所示: 通過輸出可以看出,第一個解最優,適應度得分爲11。

總結

通過模擬生物進化的過程,遺傳算法爲解決一些複雜的問題提供了一個強大的機制,通過一個簡單的示例,可以看到可以運行的遺傳算法,如果想更進一步,具體的代碼示例可以從Ignite的機器學習庫獲得。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章