用遺傳算法優化垃圾收集策略

2021-01-10 人工智慧遇見磐創

遺傳算法是一個優化技術,在本質上類似於進化過程。這可能是一個粗略的類比,但如果你眯著眼睛看,達爾文的自然選擇確實大致上類似於一個優化任務,其目的是製造出完全適合在其環境中繁衍生息的有機體。

在本文中,我將展示如何在Python中實現一個遺傳算法,在幾個小時內「進化」一個收集垃圾的機器人。

背景

我所遇到的遺傳算法原理最好的教程來自Melanie Mitchell寫的一本關於複雜系統的好書《Complexity: A Guided Tour》。

在其中一個章節中,Mitchell介紹了一個名叫Robby的機器人,他在生活中的唯一目的是撿垃圾,並描述了如何使用GA優化Robby的控制策略。下面我將解釋我解決這個問題的方法,並展示如何在Python中實現該算法。有一些很好的包可以用來構造這類算法(比如DEAP),但是在本教程中,我將只使用基本Python、Numpy和TQDM(可選)。

雖然這只是一個玩具的例子,但GAs在許多實際應用中都有使用。作為一個數據科學家,我經常用它們來進行超參數優化和模型選擇。雖然GAs的計算成本很高,但GAs允許我們並行地探索搜索空間的多個區域,並且在計算梯度時是一個很好的選擇。

問題描述

一個名為Robby的機器人生活在一個充滿垃圾的二維網格世界中,周圍有4堵牆(如下圖所示)。這個項目的目標是發展一個最佳的控制策略,使他能夠有效地撿垃圾,而不是撞牆。

Robby只能看到他周圍上下左右四個方塊以及他所在的方塊,每個方塊有3個選擇,空的,有垃圾,或者是一面牆。因此,Robby有3=243種不同的情況。Robby可以執行7種不同的動作:上下左右的移動(4種)、隨機移動、撿拾垃圾或靜止不動。

因此,Robby的控制策略可以編碼為一個「DNA」字符串,由0到6之間的243位數字組成(對應於Robby在243種可能的情況下應該採取的行動)。

方法

任何GA的優化步驟如下:

生成問題初始隨機解的「種群」個體的「擬合度」是根據它解決問題的程度來評估的最合適的解決方案進行「繁殖」並將「遺傳」物質傳遞給下一代的後代重複第2步和第3步,直到我們得到一組優化的解決方案在我們的任務中,你創建了第一代Robbys初始化為隨機DNA字符串(對應於隨機控制策略)。然後模擬讓這些機器人在隨機分配的網格世界中運行,並觀察它們的性能。

擬合度

機器人的擬合度取決於它在n次移動中撿到多少垃圾,以及它撞到牆上多少次。在我們的例子中,機器人每撿到一塊垃圾就給它10分,每次它撞到牆上就減去5分。然後,這些機器人以它們的擬合度相關的概率進行「交配」(即,撿起大量垃圾的機器人更有可能繁衍後代),新一代機器人誕生了。

交配

有幾種不同的方法可以實現「交配」。在Mitchell的版本中,她將父母的兩條DNA鏈隨機拼接,然後將它們連接在一起,為下一代創造一個孩子。在我的實現中,我從每一個親本中隨機分配每個基因(即,對於243個基因中的每一個,我擲硬幣決定遺傳誰的基因)。

例如使用我的方法,在前10個基因裡,父母和孩子可能的基因如下:

Parent 1: 1440623161Parent 2: 2430661132Child: 2440621161突變

我們用這個算法複製的另一個自然選擇的概念是「變異」。雖然一個孩子的絕大多數基因都是從父母那裡遺傳下來的,但我也建立了基因突變的小可能性(即隨機分配)。這種突變率使我們能夠探索新的可能。

Python實現

第一步是導入所需的包並為此任務設置參數。我已經選擇了這些參數作為起點,但是它們可以調整,我鼓勵你可以嘗試調整。

"""導入包"""import numpy as npfrom tqdm.notebook import tqdm"""設置參數"""# 仿真設置pop_size = 200 # 每一代機器人的數量num_breeders = 100 # 每一代能夠交配的機器人數量num_gen = 400 # 總代數iter_per_sim = 100 # 每個機器人垃圾收集模擬次數moves_per_iter = 200 # 機器人每次模擬可以做的移動數# 網格設置rubbish_prob = 0.5 # 每個格子中垃圾的概率grid_size = 10 # 0網格大小(牆除外)# 進化設置wall_penalty = -5 # 因撞到牆上而被扣除的擬合點no_rub_penalty = -1 # 在空方塊撿垃圾被扣分rubbish_score = 10 # 撿垃圾可獲得積分mutation_rate = 0.01 # 變異的概率接下來,我們為網格世界環境定義一個類。我們用標記「o」、「x」和「w」來表示每個單元,分別對應一個空單元、一個帶有垃圾的單元和一個牆。

class Environment: """ 類,用於表示充滿垃圾的網格環境。每個單元格可以表示為: 'o': 空 'x': 垃圾 'w': 牆 """ def __init__(self, p=rubbish_prob, g_size=grid_size): self.p = p # 單元格是垃圾的概率 self.g_size = g_size # 不包括牆 # 初始化網格並隨機分配垃圾 self.grid = np.random.choice(['o','x'], size=(self.g_size+2,self.g_size+2), p=(1 - self.p, self.p)) # 設置外部正方形為牆壁 self.grid[:,[0,self.g_size+1]] = 'w' self.grid[[0,self.g_size+1], :] = 'w' def show_grid(self): # 以當前狀態列印網格 print(self.grid) def remove_rubbish(self,i,j): # 從指定的單元格(i,j)清除垃圾 if self.grid[i,j] == 'o': # 單元格已經是空 return False else: self.grid[i,j] = 'o' return True def get_pos_string(self,i,j): # 返回一個字符串,表示單元格(i,j)中機器人「可見」的單元格 return self.grid[i-1,j] + self.grid[i,j+1] + self.grid[i+1,j] + self.grid[i,j-1] + self.grid[i,j]接下來,我們創建一個類來表示我們的機器人。這個類包括執行動作、計算擬合度和從一對父機器人生成新DNA的方法。

class Robot: """ 用於表示垃圾收集機器人 """ def __init__(self, p1_dna=None, p2_dna=None, m_rate=mutation_rate, w_pen=wall_penalty, nr_pen=no_rub_penalty, r_score=rubbish_score): self.m_rate = m_rate # 突變率 self.wall_penalty = w_pen # 因撞到牆上而受罰 self.no_rub_penalty = nr_pen # 在空方塊撿垃圾的處罰 self.rubbish_score = r_score # 撿垃圾的獎勵 self.p1_dna = p1_dna # 父母2的DNA self.p2_dna = p2_dna # 父母2的DNA # 生成字典來從場景字符串中查找基因索引 con = ['w','o','x'] # 牆,空,垃圾 self.situ_dict = dict() count = 0 for up in con: for right in con: for down in con: for left in con: for pos in con: self.situ_dict[up+right+down+left+pos] = count count += 1 # 初始化DNA self.get_dna() def get_dna(self): # 初始化機器人的dna字符串 if self.p1_dna is None: # 沒有父母的時候隨機生成DNA self.dna = ''.join([str(x) for x in np.random.randint(7,size=243)]) else: self.dna = self.mix_dna() def mix_dna(self): # 從父母的DNA生成機器人的DNA mix_dna = ''.join([np.random.choice([self.p1_dna,self.p2_dna])[i] for i in range(243)]) #添加變異 for i in range(243): if np.random.rand() > 1 - self.m_rate: mix_dna = mix_dna[:i] + str(np.random.randint(7)) + mix_dna[i+1:] return mix_dna def simulate(self, n_iterations, n_moves, debug=False): # 仿真垃圾收集 tot_score = 0 for it in range(n_iterations): self.score = 0 # 擬合度分數 self.envir = Environment() self.i, self.j = np.random.randint(1,self.envir.g_size+1, size=2) # 隨機分配初始位置 if debug: print('before') print('start position:',self.i, self.j) self.envir.show_grid() for move in range(n_moves): self.act() tot_score += self.score if debug: print('after') print('end position:',self.i, self.j) self.envir.show_grid() print('score:',self.score) return tot_score / n_iterations # n次迭代的平均得分 def act(self): # 根據DNA和機器人位置執行動作 post_str = self.envir.get_pos_string(self.i, self.j) # 機器人當前位置 gene_idx = self.situ_dict[post_str] # 當前位置DNA的相關索引 act_key = self.dna[gene_idx] # 從DNA中讀取行動 if act_key == '5': # 隨機移動 act_key = np.random.choice(['0','1','2','3']) if act_key == '0': self.mv_up() elif act_key == '1': self.mv_right() elif act_key == '2': self.mv_down() elif act_key == '3': self.mv_left() elif act_key == '6': self.pickup() def mv_up(self): # 向上移動 if self.i == 1: self.score += self.wall_penalty else: self.i -= 1 def mv_right(self): # 向右移動 if self.j == self.envir.g_size: self.score += self.wall_penalty else: self.j += 1 def mv_down(self): # 向下移動 if self.i == self.envir.g_size: self.score += self.wall_penalty else: self.i += 1 def mv_left(self): # 向左移動 if self.j == 1: self.score += self.wall_penalty else: self.j -= 1 def pickup(self): # 撿垃圾 success = self.envir.remove_rubbish(self.i, self.j) if success: # 成功撿到垃圾 self.score += self.rubbish_score else: # 當前方塊沒有撿到垃圾 self.score += self.no_rub_penalty最後是運行遺傳算法的時候了。在下面的代碼中,我們生成一個初始的機器人種群,讓自然選擇來運行它的過程。我應該提到的是,當然有更快的方法來實現這個算法(例如利用並行化),但是為了本教程的目的,我犧牲了速度來實現清晰。

# 初始種群pop = [Robot() for x in range(pop_size)]results = []# 執行進化for i in tqdm(range(num_gen)): scores = np.zeros(pop_size) # 遍歷所有機器人 for idx, rob in enumerate(pop): # 運行垃圾收集模擬並計算擬合度 score = rob.simulate(iter_per_sim, moves_per_iter) scores[idx] = score results.append([scores.mean(),scores.max()]) # 保存每一代的平均值和最大值 best_robot = pop[scores.argmax()] # 保存最好的機器人 # 限制那些能夠交配的機器人的數量 inds = np.argpartition(scores, -num_breeders)[-num_breeders:] # 基於擬合度得到頂級機器人的索引 subpop = [] for idx in inds: subpop.append(pop[idx]) scores = scores[inds] # 平方並標準化 norm_scores = (scores - scores.min()) ** 2 norm_scores = norm_scores / norm_scores.sum() # 創造下一代機器人 new_pop = [] for child in range(pop_size): # 選擇擬合度優秀的父母 p1, p2 = np.random.choice(subpop, p=norm_scores, size=2, replace=False) new_pop.append(Robot(p1.dna, p2.dna)) pop = new_pop雖然最初大多數機器人不撿垃圾,總是撞到牆上,但幾代人之後,我們開始看到一些簡單的策略(例如「如果與垃圾在一起,就撿起來」和「如果挨著牆,就不要移到牆裡」)。經過幾百次的反覆,我們只剩下一代不可思議的垃圾收集天才!

結果

下面的圖表表明,我們能夠在400代機器人種群中「進化」出一種成功的垃圾收集策略。

為了評估進化控制策略的質量,我手動創建了一個基準策略,其中包含一些直觀合理的規則:

如果垃圾在當前方塊,撿起來如果在相鄰的方塊上可以看到垃圾,移到那個方塊如果靠近牆,則向相反方向移動否則,隨意移動平均而言,這一基準策略達到了426.9的擬合度,但我們最終的「進化」機器人的平均擬合度為475.9。

戰略分析

這種優化方法最酷的一點是,你可以找到反直覺的解決方案。機器人不僅能夠學習人類可能設計的合理規則,而且還自發地想出了人類可能永遠不會考慮的策略。一種先進的技術出現了,就是使用「標記物」來克服近視和記憶不足。

例如,如果一個機器人現在在一個有垃圾的方塊上,並且可以看到東西方方塊上的垃圾,那麼一個天真的方法就是立即撿起當前方塊上的垃圾,然後移動到那個有垃圾的方塊。這種策略的問題是,一旦機器人移動(比如向西),他就無法記住東邊還有1個垃圾。為了克服這個問題,我們觀察了我們的進化機器人執行以下步驟:

向西移動(在當前方塊留下垃圾作為標記)撿起垃圾往東走(它可以看到垃圾作為標記)把垃圾撿起來,搬到東邊去撿起最後一塊垃圾

從這種優化中產生的另一個反直覺策略的例子如下所示。OpenAI使用強化學習(一種更複雜的優化方法)教代理玩捉迷藏。我們看到,這些代理一開始學習「人類」策略,但最終學會了新的解決方案。

結論

遺傳算法以一種獨特的方式將生物學和計算機科學結合在一起,雖然不一定是最快的算法,但在我看來,它們是最美麗的算法之一。

本文中介紹的所有代碼都可以在我的Github上找到,還有一個演示Notebook:https://github.com/andrewjkuo/robby-robot-genetic-algorithm。

相關焦點

  • 淺析基於優化算法的能量管理控制策略(二)
    做新能源汽車相關研究,能量管理控制策略是一個繞不開的話題,特別是基於優化算法的能量管理控制策略。,NN)滑模控制(Sliding ModeControl,SMC)無導數優化算法——模擬退火(Simulated Annealing,SA)無導數優化算法——遺傳算法(Genetic Algorithm,GA)無導數優化算法——粒子群算法(Particle Swarm Optimization,PSO)無導數優化算法——DIRECT
  • NeurIPS2020|用遺傳探索指導深層分子優化
    特別地,作者設計了一個額外的遺傳專家策略框架,它生成神經學徒策略的模仿學習目標,即DNN。該方法的主要思想是將專家策略作為遺傳改良算子應用於學徒策略;這允許我們通過模仿更好的專家策略來引導學徒策略生5子x的組合優化,使回報(期望的性質) r(x) 最大化。為了解決這個問題,作者在整個學習過程中,從神經學徒策略 和遺傳專家策略 中收集高回報值的分子。
  • 利用遺傳算法優化GANs
    遺傳算法是根據大自然中生物體進化規律而設計提出的,是根據大自然中生物體進化規律而設計提出的。是模擬達爾文生物進化論的自然選擇和遺傳學機理的生物進化過程的計算模型,是一種通過模擬自然進化過程搜索最優解的方法。在本片文章中,我們嘗試使用遺傳算法來對訓練GANs進行優化,我們的訓練模型是生成手寫數字。什麼是遺傳算法?
  • 遺傳算法的發展
    • 1975年,De.Jong在其博士論文中結合模式定理進行了大量的純數值函數優化計 算實驗,樹立了遺傳算法的工作框架,得到了一些重要且具有指導意義的結論。 • 1987年,美國D.Lawrence總結人們長期從事遺傳算法的經驗,公開出版《遺傳 算法和模擬退火(Genetic Algorithm and Simulated Annealing)》一書,以論文 集形式用大量實例介紹遺傳算法。
  • 遺傳算法原理以及在量化投資的應用
    什麼是遺傳算法 1.介紹遺傳算法的概念 遺傳算法是一種進化策略的算法,模擬生物基因遺傳。遵循物競天擇,適者生存,劣者淘汰的自然規律進化。每個步驟的優化都會影響到遺傳算法整體的優化結果。 其他選擇算法 還有其他的擴展的選擇算法,例如隨機競爭選擇、期望值選擇,排擠策略等。
  • 基於遺傳算法的工廠AGV路徑優化研究
    遺傳算法是模仿自然界生物進化機制發展起來的隨機全局搜索優化方法,具有算法效率高、魯棒性強、可實現並行搜索等特點 [3] ,被廣泛用於解決路徑規劃等領域的問題。G.Jeon [4] 和William [5] 等人用混合遺傳算法求解車輛路徑規劃問題;李青欣 [6] 進行了AGV路徑規劃的遺傳算法研究,根據運行環境信息複雜度和數量的不同分別分析了幾種不同類型的路徑規劃。
  • 矩形平面陣列天線旁瓣電平優化的遺傳算法
    優化,通過提出新的自適應變異算子改進了算法的收斂性能,良好的計算結果表明遺傳算法是目前求解此類問題的有效方法.;近年來一種模擬自然進化的遺傳算法開始應用於計算電磁學領域[1,2],該算法只要求待解問題是可計算的,並無可微性等其它限制,同時,由於該算法採用了優化的隨機搜索技術,能以較大的概率和較快的速率求得全局最優解.本文運用遺傳算法對一個具有1024個陣元的矩形平面陣列的陣元間距及饋電流幅值進行了優化,使該方陣的最大相對旁瓣電平由均勻方陣的-13.27dB降至-34.56dB
  • 前沿| 利用遺傳算法優化神經網絡:Uber提出深度學習訓練新方式
    許多人認為,SGD 算法有效計算梯度的能力對於這種訓練能力而言至關重要。但是,Uber 近日發布的五篇論文表明,神經進化(neuroevolution)這種利用遺傳算法的神經網絡優化策略,也是訓練深度神經網絡解決強化學習(RL)問題的有效方法。
  • 【優化】遺傳算法介紹
    [2]葛繼科,邱玉輝,吳春明,蒲國林.遺傳算法研究綜述[J].計算機應用研究,2008(10):2911-2916.[3]雷德明.多維實數編碼遺傳算法[J].控制與決策,2000(02):239-241.[4]臧文科. DNA遺傳算法的集成研究與應用[D].山東師範大學,2018.
  • 遺傳算法:組合優化算法,按照進化論的方式啟發搜索尋優解
    遺傳算法是由美國密西根大學的 Holland教授創立於20世紀六七十年代,受達爾文「進化論」思想的啟發而設計實現。遺傳算法不是通過暴力搜索解的方法,而是通過模擬種群的基因交叉和突變,經過種群一代一代的適者生存的方式尋找問題優解的方法,這在解決組合優化時解空間組合爆炸中應用廣泛。
  • 基於遺傳算法的高頻標籤天線的優化設計
    而標籤天線作為射頻識別系統實現的關鍵部件,它的優化設計對於降低本錢, 減小體積起到重要的作用。低頻和高頻頻段標籤天線的主要形式是線圈。在低頻頻段減小天 線體積的方法主要是在線圈中插進具有高磁導率的鐵氧體材料,這樣就可以進步天線的磁導 率,即可在等效面積變小的情況下得到足夠的開路電壓。高頻頻段主要是採用將天線集成到 晶片上的方法來實現減小體積,降低本錢的目的。
  • 詳解遺傳算法
    遺傳算法是受達爾文的進化論的啟發,借鑑生物進化過程而提出的一種啟發式搜索算法。因此在介紹遺傳算法前有必要簡單的介紹生物進化知識。 遺傳算法有3個最基本的操作:選擇,交叉,變異。   選擇選擇一些染色體來產生下一代。一種常用的選擇策略是 「比例選擇」,也就是個體被選中的概率與其適應度函數值成正比。
  • 基於多島遺傳算法的新能源叉車轉向橋優化設計
    因此,將多學科優化方法與多體運動學分析工具相結合,採用改進遺傳算法進行平衡和優化可較好地解決上述問題[10,11]。本文運用空間機構運動學,以某款新能源叉車橫置液壓缸式轉向橋為研究對象,對其轉向機構進行運動規律分析,並以轉向機構的轉角誤差值最小為目標函數搭建了橫置液壓缸式轉向橋的運動學模型。
  • 配電網絡重構的改進混合遺傳算法
    一個大型的配網包含眾多的節點和支路,因此圖中支撐樹的組合數目極大,若窮舉所有的樹,算法將非常的低效。  遺傳算法具有全局收斂性、無可微性要求、具有很好的魯棒性等優點,特別適合於求解組合優化問題。另外,與一般的隨機搜索方法進行的盲目無向搜索不同,遺傳算法進行的是高效有向的全局搜索,能夠逐步地逼近並收斂於全局最優解。因此,遺傳算法在配網重構中得到越來越廣泛的應用。
  • 人工智慧之遺傳算法(GA),搜索最優解的方法
    遺傳算法(GA)是一類借鑑生物界的進化規律演化而來的隨機化搜索方法。 今天我們重點探討一下遺傳算法(GA)。^_^ 人們一提到遺傳算法(GA),就會聯想到達爾文的生物進化論。遺傳算法(GA)是一類借鑑生物界的進化規律演化而來的隨機化搜索方法。它是由美國的J.Holland教授1975年首先提出。目前,遺傳算法(GA)已成為進化計算研究的一個重要分支。
  • 莊鎮泉——中國科學技術大學——神經網絡,遺傳算法等計算智能方法...
    所在院校: 中國科學技術大學       所在院系: 電子科學與技術系 職稱: 教授       招生專業: 研究領域: 神經網絡,遺傳算法等計算智能方法及其在圖象處理
  • 改進遺傳算法的支持向量機特徵選擇解決方案
    遺傳算法作為一種魯棒性極強的智能識別方法,直接對尋優對象進行操作,不存在特定數學條件的限定,具有極好的全局尋優能力和並行性;而由於遺傳算法採用概率化的尋優方法,所以在自動搜索的過程中可以自主獲取與尋優有關的線索,並在加以學習之後可以自適應地調整搜索方向,不需要確定搜索的規則。因此遺傳算法被廣泛應用在知識發現、組合優化、機器學習、信號處理、自適應控制和人工生命等領域。
  • 即時配送的訂單分配策略:從建模和優化
    即時配送大數據平臺實現對騎手軌跡數據、配送業務數據、特徵數據、指標數據的全面管理和監控,並通過模型平臺、特徵平臺支持相關算法策略的快速迭代和優化。訂單——騎手的匹配優化如果說上述建模過程的目標是構建和實際業務吻合的解空間,優化算法的作用則是在我們構建的解空間裡找到最優的策略。配送調度問題屬於典型的NP-Hard類離散系統優化問題,解空間巨大。
  • 什麼是遺傳算法?怎樣繪製遺傳算法流程圖
    遺傳算法是一種通過模擬自然進化過程搜索最優解的操作方法,遺傳算法有三個基本算子選擇、交叉和變異。對於遺傳算法我們也可以使用流程圖對其整個過程進行總結歸納,那要怎樣繪製遺傳算法流程圖呢?下面是分享的簡單操作方法,希望可以幫助大家。
  • 變壓器之遺傳算法(Genetic Algorithm)的具體實現過程
    遺傳算法(Genetic Algorithm)是一類借鑑生物界的進化規律(適者生存,優勝劣汰遺傳機制)演化而來的隨機化搜索方法。