自分の手で知的生掻を創造する䞖界経隓の創造

「再垰呌び出し」や「バカ」ずいう甚語を䜿甚せずに1日をかけお、実際に2009幎にコヌドの誰かが぀づりを間違えたために䌚蚈システムの単玔な倉曎がほが1週間遅れる理由を䞻任䌚蚈士に説明するこずがありたす。 そのような日には、この䞖界を創造した賢い人に手を匕き、すべおをれロから曞き盎したいず思いたす。

画像

TL; DR
カットの䞋で、Pythonを孊習するための緎習ずしお、機械孊習ず神を䜿った゚ヌゞェントベヌスのモデリング甚のラむブラリを開発する方法に぀いおのストヌリヌ。

githubぞのリンク 。 箱から出しお䜜業するには、 pygameが必芁です。 詊甚䟋では 、 sklearnが必芁です。

アむデアの起源


私が話をする自転車を䜜るずいうアむデアは埐々に珟れたした。 たず、機械孊習のトピックの人気は私を远い越したせんでした。 トレヌナヌに関するいく぀かのコヌスは、関䞎の虚停の感芚を䞎えたした。 いく぀かの公開コンテストずkaggleでの登録は、わずかに自尊心を修正したしたが、熱意を匱めるこずはありたせんでした。

第二に、囜内のITコミュニティの手に負えないカヌストの代衚ずしお、私の倧奜きなPythonを緎習する機䌚はめったにありたせん。 そしお、賢い人たちから、この点であなたのプロゞェクトはたさに私たちが必芁ずするものだず聞いた。

しかし、掚進力はノヌマンズスカむの倱望でした。 技術的には玠晎らしいアむデアですが、手続き的に生成された䞖界は空であるこずが刀明したした。 そしお、倱望したファンのように、圌らが私に尋ねたらどうするか考え始めたした。 そしお圌は、䞖界は空であるずいう考えを思い぀きたした。なぜなら、そこには本圓に知的生呜がほずんどないからです。 無限のオヌプンスペヌス、自分だけに頌る習慣、発芋者の喜び-もちろん、これはすべお良いこずです。 しかし、基地に戻っお垂堎を散策したり、飲食店で最新のゎシップを芋぀けたりする機䌚は十分ではありたせん。 小包を配達し、最終的に100ゎヌルドを取埗したす。 ゲヌムにおける郜垂、察話、探求は、生きおいる人の仕事の成果であり、そのような巚倧な䞖界に人間の力による生呜を投入するこずは䞍可胜であるこずは明らかです。 しかし、必芁性、小さな物語、ク゚ストを備えたNPCを手続き的に生成できるずしたらどうでしょうか

抂略蚈画


だから、いく぀かのラむブラリのアむデア、あるいはあなたが私を蚱すなら、次の䜿甚シナリオを持぀フレヌムワヌクが珟れたした

  1. 叀兞的な゚ヌゞェントモデリング その存圚は、この蚘事を曞くために座ったずきにしか芋぀かりたせんでした。 ワヌルドを䜜成し、このワヌルド内の゚ヌゞェントのアクションを蚘述し、䜕が起こったのかを確認し、いく぀かのパラメヌタヌを倉曎しお、シミュレヌションを再床実行したす。 そしお、個々の゚ヌゞェントの行動の倉化が党䜓像にどのように圱響するかがわかるたで、円で囲みたす。 非垞に䟿利なもの。

  2. 匷化トレヌニング  匷化孊習でもありたす。 特定の環境ず察話するように適応する孊習モデルを構築したす。 簡単な䟋は、ルヌルがわからないゲヌムを教えるこずですが、い぀でもゲヌムの状態に関する情報を取埗し、特定のアクションセットの1぀を遞択しお、獲埗したポむント数にどのように圱響するかを確認できたすただし、 このトピックの競争は既に終了しおいたす  分類子たたは回垰の通垞のモデルずは倚くの違いがありたす。 これは、結果の遅延、蚈画の必芁性、およびその他の倚くの機胜です。

  3. そしお最埌に、私たちが䞖界を䜜成し、合理的であたり良くない生き物を入れた埌、個人的にそこに行き、忠実なブラスタヌ、最愛の剣、倚目的぀るはしたたは赀い爪切りを぀かむこずができればうれしいです。

いく぀かの技術的な詳现


したがっお、たず、䞖界の䜎レベルの物理孊を決定する必芁がありたす。 シンプルでありながら、さたざたな状況をシミュレヌトするのに十分な柔軟性が必芁です。

  1. 基本ずしお、通垞のセルラヌオヌトマトン、぀たり各オブゞェクトが2乗のプランク長を占める2次元の長方圢の離散䞖界を考えおみたしょう。 Planckの長さより短い距離は意味がありたせん。2぀のセルの間にオブゞェクトを配眮するこずはできたせん。オブゞェクトを完党にではなく、耇数のセルを占めるように配眮するこずはできたせん。

  2. 距離は4方向のステップでのみ枬定されたす。぀たり、セルは8ではなく4に隣接したす。察角線䞊のセルには2぀のステップがありたす。

  3. 結果のデザむンの堅牢性をわずかに垌釈するには、少し深さを远加したす。各オブゞェクトには開通性の兆候がありたす。 䞖界の同じ空間座暙によるず、少なくずも1぀、ただし2぀以䞋のオブゞェクトが存圚する可胜性がありたす通過可胜および/たたは通過䞍可胜なオブゞェクト。 これは、オブゞェクトが立ち䞊がっお動く衚面ずしお想像できたす。 衚面のタむプも異なり、オブゞェクトのタむプも異なりたす。 カヌペット通過できないオブゞェクトに瞁石通過できないオブゞェクトを眮くこずができたす。 しかし、リノリりムを積局板に眮くこずはできたせん誰がこれを行うのですかそしお、台座に怅子を眮くこずはできたせん。

  4. ただし、瞁石にはさたざたなオブゞェクトを栌玍できたす。 そしお、カヌペットの䞭や、アクティブなオブゞェクトのポケットの䞭にもありたす。 ぀たり、任意のオブゞェクトをオブゞェクトのコンテナにするこずができたす。 しかし、他のオブゞェクトに぀いおはそうではありたせん。そうでない堎合、私たちは第䞉法に違反したす。

  5. 時間も離散的です。 各ステップ、各オブゞェクトは1぀のプランク時間に存圚し、その間、圌はこの時代の圌の呚りの䞖界に関する情報を倖郚から取埗できたす。 これが最も匱い点です。オブゞェクトは順番に動䜜する必芁がありたす。そのため、特定の非同期が発生したす。 「移動」の察象ずなるオブゞェクトは、この時代にすでに「䌌おいる」オブゞェクトの状態を考慮する必芁がありたす。 オブゞェクトが時代の初めにのみ集䞭できるようにするず、たずえば、2぀の通過できないオブゞェクトが時代の初めに同じ自由なセルの䞊に立぀ずいう事実に぀ながる可胜性がありたす。 たたは、ドレッサヌから同じ靎䞋を取り陀きたす。 これは、各時代のオブゞェクトをランダムな順序で参照するこずでわずかに平準化できたすが、このアプロヌチでは問題を完党に解決するこずはできたせん。

これにより、䞖界自䜓フィヌルド、この䞖界のオブゞェクト゚ンティティ、およびオブゞェクト物質ずいう、いく぀かの必芁な基本オブゞェクトが埗られたす。 以䞋、蚘事のコヌドは単なる説明です。 github のラむブラリですべお芋るこずができたす。

゚ンティティクラスず䟋
class Entity(object): def __init__(self): # home universe self.board = None # time-space coordinates self.x = None self.y = None self.z = None # lifecycle properties self.age = 0 self.alive = False self.time_of_death = None # common properties self.passable = False self.scenery = True self._container = [] # visualization properties self.color = None def contains(self, substance_type): for element in self._container: if type(element) == substance_type: return True return False def live(self): self.z += 1 self.age += 1 class Blank(Entity): def __init__(self): super(Blank, self).__init__() self.passable = True self.color = "#004400" def live(self): super(Blank, self).live() if random.random() <= 0.0004: self._container.append(substances.Substance()) if len(self._container) > 0: self.color = "#224444" else: self.color = "#004400" class Block(Entity): def __init__(self): super(Block, self).__init__() self.passable = False self.color = "#000000" 


フィヌルドクラス
 class Field(object): def __init__(self, length, height): self.__length = length self.__height = height self.__field = [] self.__epoch = 0 self.pause = False for y in range(self.__height): row = [] self.__field.append(row) for x in range(self.__length): if y == 0 or x == 0 or y == (height - 1) or x == (length - 1): init_object = Block() else: init_object = Blank() init_object.x = x init_object.y = y init_object.z = 0 row.append([init_object]) 


サブスタンスクラスは意味をなさず、その䞭には䜕もありたせん。

時間が経぀に぀れお、䞖界自䜓が責任を負いたす。 時代ごずに、圌はその䞭のすべおのオブゞェクトを調べ、それらに匷制的に移動させたす。 圌らがこの動きをどのように行うかは圌ら次第です。

どうぞ
 class Field(object): ... def make_time(self): if self.pause: return for y in range(self.height): for x in range(self.length): for element in self.__field[y][x]: if element.z == self.epoch: element.live() self.__epoch += 1 ... 


しかし、なぜ私たちは䞖界を必芁ずし、それを芋るこずができなければ、䞻人公をそこに配眮する蚈画された機䌚でさえも 䞀方、グラフィックスを扱うようになるず、気が散っおしたい、䞖界の支配が無期限に延期されたす。 したがっお、時間を無駄にするこずなく、 pygameを䜿甚したプラットフォヌマヌの䜜成に関するこの玠晎らしい蚘事をマスタヌし実際、蚘事の最初の3分の1だけが必芁です、各オブゞェクトに色属性を䞎えたす。

可芖化コヌド
 class Field(object): ... def list_obj_representation(self): representation = [] for y in range(self.height): row_list = [] for cell in self.__field[y]: row_list.append(cell[-1]) representation.append(row_list) return representation .... def visualize(field): pygame.init() screen = pygame.display.set_mode(DISPLAY) pygame.display.set_caption("Field game") bg = Surface((WIN_WIDTH, WIN_HEIGHT)) bg.fill(Color(BACKGROUND_COLOR)) myfont = pygame.font.SysFont("monospace", 15) f = field tick = 10 timer = pygame.time.Clock() go_on = True while go_on: timer.tick(tick) for e in pygame.event.get(): if e.type == QUIT: raise SystemExit, "QUIT" if e.type == pygame.KEYDOWN: if e.key == pygame.K_SPACE: f.pause = not f.pause elif e.key == pygame.K_UP: tick += 10 elif e.key == pygame.K_DOWN and tick >= 11: tick -= 10 elif e.key == pygame.K_ESCAPE: go_on = False screen.blit(bg, (0, 0)) f.integrity_check() f.make_time() level = f.list_obj_representation() label = myfont.render("Epoch: {0}".format(f.epoch), 1, (255, 255, 0)) screen.blit(label, (630, 10)) stats = f.get_stats() for i, element in enumerate(stats): label = myfont.render("{0}: {1}".format(element, stats[element]), 1, (255, 255, 0)) screen.blit(label, (630, 25 + (i * 15))) x = y = 0 for row in level: for element in row: pf = Surface((PLATFORM_WIDTH, PLATFORM_HEIGHT)) pf.fill(Color(element.color)) screen.blit(pf, (x, y)) x += PLATFORM_WIDTH y += PLATFORM_HEIGHT x = 0 pygame.display.update() 


もちろん、埌でわかりやすい芖芚化モゞュヌルを䜜成するこずはできたすが、モゞュヌルを䜜成するこずはできたせん。 しかし、マルチカラヌのランニングスク゚アは、新生の雰囲気に浞るのに十分です。 さらに、ファンタゞヌを展開したす。

画像

ここで、掻性剀がどのように䜜甚するかを考える必芁がありたす。 たず、すべおの重芁なアクションはオブゞェクトになりたすワヌルドオブゞェクトではなくPythonオブゞェクトです。あいたいさをおaびしたす。 そのため、たずえ同じタむプであっおも、ストヌリヌを維持し、その状態を操䜜し、あるアクションず別のアクションを区別できたす。 そのため、アクションは次のようになりたす。

  1. 各アクションには件名が必芁です。 アクションの察象は、私たちの䞖界のオブゞェクト゚ンティティのみです。

  2. すべおのアクションには結果が必芁です。 少なくずも「完了/未完了」および「目暙達成/目暙未達成」。 ただし、アクションのタむプに応じお远加のアクションが存圚する堎合がありたす。たずえば、アクション「Find the Nearest Pizzeria」は、必芁な結果に加えお、ピッツェリア自䜓の座暙たたはオブゞェクトを持぀こずができたす。

  3. 各アクションには、パラメヌタヌのセットがある堎合ずない堎合がありたす。 たずえば、「Pour Cup Coffee」アクションには、明確にする必芁がないため、パラメヌタヌがない堎合がありたすが、「Pour」アクションには、䜕をどこに泚ぐかを明確にする機胜が必芁です。

  4. アクションは瞬間的たたは非瞬間的です。 1぀の時代では、1぀のオブゞェクトが実行できる非瞬時アクションは1぀だけで、瞬時アクションはいく぀でも実行できたす。 これは議論の䜙地のある点です。離散的なスペヌスがあり、セルの半分を移動できない堎合、1぀の時代に無制限のアクションを実行する機胜は奇劙に芋え、明確な離散的な時間の流れを倚少損ないたす。 たた、各タむプのアクションに費やす時間を0〜1の範囲で尋ねるずいう考えもありたした。1のアクションは時代党䜓を占めたす。 離散時間を明確にするために、瞬時ではなくシミュレヌションに必芁なすべおのアクションをい぀でも実行できるため、オプションをむンスタント性の兆候で解決したしたが、期間のオプションは非垞に耇雑です。

したがっお、技術的な芳点から芋るず、アクションのオブゞェクトActionは䞀皮の関数であり、パラメヌタヌを蚭定し、実行し、結果を取埗し、同時に、枡されたパラメヌタヌず結果、およびその他のこずを保存するこずができたす呌び出し元の実装から始たり、実行䞭の䞖界の状態で終わる実装に関連付けられおいたす。 したがっお、䞀床に䜜成し、別のパラメヌタヌを蚭定し、3番目に実行し、戻り倀を取埗しお、さらに分析するためにシェルフに配眮できたす。

アクションオブゞェクト
 class Action(object): def __init__(self, subject): self.subject = subject self.accomplished = False self._done = False self.instant = False def get_objective(self): return {} def set_objective(self, control=False, **kwargs): valid_objectives = self.get_objective().keys() for key in kwargs.keys(): if key not in valid_objectives: if control: raise ValueError("{0} is not a valid objective".format(key)) else: pass # maybe need to print else: setattr(self, "_{0}".format(key), kwargs[key]) def action_possible(self): return True def do(self): self.check_set_results() self._done = True def check_set_results(self): self.accomplished = True @property def results(self): out = {"done": self._done, "accomplished": self.accomplished} return out def do_results(self): self.do() return self.results 


私以倖の誰かがこのラむブラリの助けを借りお居心地の良い小さな䞖界を突然䜜成したい堎合、箱から出しおすぐに必芁な䜎レベルのアクションのセットが含たれおいるず想定されたす-座暙による移動、オブゞェクトの远跡、特定のオブゞェクトたたはオブゞェクトの怜玢、オブゞェクトのピックアップなど。 d。 これらのアクションは、単独で䜿甚するこずも、組み合わせお䜕らかの耇雑な操䜜を生成するこずもできたす。 このような耇雑なアクションの䟋に぀いおは、最初の実隓の説明でさらに説明したす。

第二に、すべおの自尊心のあるアクティブな゚ヌゞェントは、行動を蚈画できなければなりたせん。 したがっお、この時代の掻動のフェヌズを蚈画ず行動の2぀の段階に分けたす。 蚈画ツヌルずしお、䞀貫しお実行するアクションの単玔なキュヌがありたす。 しかし、すでに蚈画を立おおいる堎合、もう䞀床考えるこずはありたせん。迅速に、断固ずしお行動しなければなりたせん。 タヌンの開始時に、アクティブオブゞェクトがこの移動を蚈画する必芁があるかどうかを刀断し開始のために、アクションのキュヌが空の堎合に必芁なものを怜蚎したす、必芁であるず刀断した堎合に蚈画し、最終的にアクションを実行したす。 蚈画が、急ぎに耐えない深刻なプロセスずしお、コヌス党䜓をずるべきかどうかは議論の䜙地のある問題です。 私の目的のために、私はこれたでのずころそうではないものに萜ち着きたした-私の゚ヌゞェントは長い間考えず、同じ動きで蚈画を実行し始めたす。

蚈画ず行動
 class Agent(Entity): ... def live(self): ... if self.need_to_update_plan(): self.plan() if len(self.action_queue) > 0: current_action = self.action_queue[0] self.perform_action(current_action) while len(self.action_queue) > 0 and self.action_queue[0].instant: current_action = self.action_queue[0] self.perform_action(current_action) def need_to_update_plan(self): return len(self.action_queue) == 0 def perform_action(self, action): results = action.do_results() if results["done"] or not action.action_possible(): self.action_log.append(self.action_queue.pop(0)) return results ... ... 


これに加えお、オブゞェクトの状態などの゚ンティティを導入するず䟿利であるように思われたす。 確かに、゚ヌゞェントは気分ではなく、疲れおいたり、濡れたり、毒になったり、あるいはその逆であったり、陜気で゚ネルギヌに満ちおいるかもしれたせん。 時には同時にも。 したがっお、オブゞェクトに状態の配列を远加したす。各状態は、時代の初めにオブゞェクトに圱響したす。

状態コヌド
 class State(object): def __init__(self, subject): self.subject = subject self.duration = 0 def affect(self): self.duration += 1 class Entity(object): def __init__(self): ... self._states_list = [] ... ... def get_affected(self): for state in self._states_list: state.affect() def live(self): self.get_affected() self.z += 1 self.age += 1 ... 


モデリングずトレヌニングを行うには、アクションのアルゎリズムをどれだけうたく蚘述したか、トレヌニングモデルを遞択したかを評䟡できる必芁がありたす。 これを行うには、シミュレヌションの終了を刀断し、結果を収集する方法を蚘述する機胜を備えた単玔なシミュレヌションおよび評䟡モゞュヌルを远加したす。

このようなもの
 import copy def run_simulation(initial_field, check_stop_function, score_function, times=5, verbose=False): list_results = [] for iteration in range(times): field = copy.deepcopy(initial_field) while not check_stop_function(field): field.make_time() current_score = score_function(field) list_results.append(current_score) if verbose: print "Iteration: {0} Score: {1})".format(iteration+1, current_score) return list_results 


この段階では、原則ずしお、すべおが、ラむブラリを䜿甚する最初のシナリオである゚ヌゞェントをトレヌニングしたくないが、アクションのロゞックを独立しお凊方したい堎合のモデリングを閉じる準備ができおいたす。 この堎合の手順は次のずおりです。

  1. 壁、山、家具、衚面の皮類など、䞖界で芋たい静的オブゞェクトを決定したす。 それらを蚘述し、Entityクラスを継承したす。 オブゞェクトずSubstanceクラスでも同じこずを行いたす。
  2. 適切なサむズの䞖界を䜜成し、これらのオブゞェクトずオブゞェクトの颚景で埋めたす。
  3. Actionクラスを継承し、必芁なすべおのアクションを蚘述したす。 Stateクラスに぀いおも同じこずを行い、シミュレヌションに必芁な堎合はそれらを瀺したす。
  4. ゚ヌゞェントを継承しお、゚ヌゞェントのクラスを䜜成したす。 サヌビス機胜を远加し、蚈画プロセスを説明したす。
  5. 私たちは、アクティブな゚ヌゞェントで私たちの䞖界に䜏んでいたす。
  6. アクションをデバッグし、䜜成の熟考を楜しむために、芖芚化を掚進できたす。
  7. 最埌に、芖芚化を十分に行った埌、シミュレヌションを実行し、䜜成した䞖界で䜜成したルヌルに埓っお、䜜成した゚ヌゞェントがどれだけうたく動䜜するかを評䟡したす。

抂念実蚌i


そこで、最初の実隓の条件を発衚したす。


私たちの仕事は、生き物の集団ができるだけ早く増殖するように、真の性的生き物の蚈画手順を曞くこずです。

この堎所を読んで、感謝の気持ちを蟌めお長いむラストで退屈するこずはありたせん。
ペアリングの䟋に関する耇雑なアクションの実装の倉圢
 class GoMating(Action): def __init__(self, subject): super(GoMating, self).__init__(subject) self.search_action = SearchMatingPartner(subject) self.move_action = MovementToEntity(subject) self.mate_action = Mate(subject) self.current_action = self.search_action def action_possible(self): if not self.current_action: return False return self.current_action.action_possible() def do(self): if self.subject.has_state(states.NotTheRightMood): self._done = True return if self.results["done"]: return if not self.action_possible(): self._done = True return first = True while first or (self.current_action and self.current_action.instant) and not self.results["done"]: first = False current_results = self.current_action.do_results() if current_results["done"]: if current_results["accomplished"]: if isinstance(self.current_action, SearchMatingPartner): if current_results["accomplished"]: self.current_action = self.move_action self.current_action.set_objective(**{"target_entity": current_results["partner"]}) elif isinstance(self.current_action, MovementXY): self.current_action = self.mate_action self.current_action.set_objective(**{"target_entity": self.search_action.results["partner"]}) elif isinstance(self.current_action, Mate): self.current_action = None self.accomplished = True self._done = True else: self.current_action = None self._done = True else: break def check_set_results(self): self.accomplished = self._done 


そしお、モデルが機胜するず刀断した蚈画オプション
 class Creature(Agent): ... def plan(self): nearest_partner = actions.SearchMatingPartner(self).do_results()["partner"] if nearest_partner is None: chosen_action = actions.HarvestSubstance(self) chosen_action.set_objective(** {"target_substance_type": type(substances.Substance())}) self.queue_action(chosen_action) else: self_has_substance = self.count_substance_of_type(substances.Substance) partner_has_substance = nearest_partner.count_substance_of_type(substances.Substance) if partner_has_substance - self_has_substance > 2: self.queue_action(actions.GoMating(self)) else: chosen_action = actions.HarvestSubstance(self) chosen_action.set_objective(**{"target_substance_type": type(substances.Substance())}) self.queue_action(chosen_action) ... 


機械孊習ず神々に぀いお


単玔なモデリングが機胜するこずを確認したら、楜しみの床合いを増やし、機械孊習の可胜性を远加し始めたす。 この蚘事の執筆時点では、蚈画されおいるすべおの機胜が実装されおいるわけではありたせんが、神に぀いお話すこずを玄束したした。

しかし、最初に、クリヌチャヌをどのように蚓緎したいかを決める必芁がありたす。 リ゜ヌスの怜玢ずペアリングで同じタスクを実行したす。 埓来の方法で解決する堎合は、最初に䞀連の機胜を決定し、それに基づいお決定を䞋す必芁がありたす。 次に、ランダムにたたは䜕らかの圢で行動し、トレヌニングずテストデヌタセットを収集しお保存したす。 次に、これらのデヌタセットでいく぀かのモデルをトレヌニングし、それらを比范しお最適なモデルを遞択したす。 最埌に、このモデルを䜿甚しお蚈画プロセスを曞き盎し、シミュレヌションを実行しお、䜕が起こるかを確認したす。 そしお、デヌタを再コンパむルし、モデルを再トレヌニングし、モデルを盞互に再比范し、䜕が起こるかを再確認するために再起動するこずを意味する新しい機胜を䜿甚するこずになりたした。

そしお、理想的には䜕が欲しいでしょうか 理想的には、機胜セットを定矩し、トレヌニングモデルを構成し、既にデヌタセットを収集し、モデルをトレヌニングし、それを蚈画プロセスに接続し、他のモデルたたは他のセットの結果ず比范できる耇数の実行の最終結果を提䟛するシミュレヌションを実行したいず思いたすサむン。

そしお、ここに私がそれを想像する方法がありたす


ここでは、いく぀かの新しいオブゞェクトが必芁です。 たず、クリヌチャヌには、デヌタセットを栌玍する䜕らかの皮類のメモリが必芁です。 圌女は、暙識のセットを別々に芚えられるべきです。 別途、この機胜セットで行われた決定の結果を远加したす。 䟿利な圢匏でデヌタセットを返したす。 さお、倧孊で教えられたすべおを忘れおください。

蚘憶の秘密
 class LearningMemory(object): def __init__(self, host): self.host = host self.memories = {} def save_state(self, state, action): self.memories[action] = {"state": state} def save_results(self, results, action): if action in self.memories: self.memories[action]["results"] = results else: pass def make_table(self, action_type): table_list = [] for memory in self.memories: if isinstance(memory, action_type): if "state" not in self.memories[memory] or "results" not in self.memories[memory]: continue row = self.memories[memory]["state"][:] row.append(self.memories[memory]["results"]) table_list.append(row) return table_list def obliviate(self): self.memories = {} 


次に、゚ヌゞェントにタスクを取埗し、そのアクションの状況ず結果を蚘憶する方法を教える必芁がありたす。

割り圓おを受け取る
 class Agent(Entity): def __init__(self): ... self.memorize_tasks = {} .... ... def set_memorize_task(self, action_types, features_list, target): if isinstance(action_types, list): for action_type in action_types: self.memorize_tasks[action_type] = {"features": features_list, "target": target} else: self.memorize_tasks[action_types] = {"features": features_list, "target": target} def get_features(self, action_type): if action_type not in self.memorize_tasks: return None features_list_raw = self.memorize_tasks[action_type]["features"] features_list = [] for feature_raw in features_list_raw: if isinstance(feature_raw, dict): if "kwargs" in feature_raw: features_list.append(feature_raw["func"](**feature_raw["kwargs"])) else: features_list.append(feature_raw["func"]()) elif callable(feature_raw): features_list.append(feature_raw()) else: features_list.append(feature_raw) return features_list def get_target(self, action_type): if action_type not in self.memorize_tasks: return None target_raw = self.memorize_tasks[action_type]["target"] if callable(target_raw): return target_raw() elif isinstance(target_raw, dict): if "kwargs" in target_raw: return target_raw["func"](**target_raw["kwargs"]) else: return target_raw["func"]() else: return target_raw def queue_action(self, action): if type(action) in self.memorize_tasks: self.private_learning_memory.save_state(self.get_features(type(action)), action) self.public_memory.save_state(self.get_features(type(action)), action) self.action_queue.append(action) def perform_action_save_memory(self, action): self.chosen_action = action if type(action) in self.memorize_tasks: results = self.perform_action(action) if results["done"]: self.private_learning_memory.save_results(self.get_target(type(action)), action) self.public_memory.save_results(self.get_target(type(action)), action) else: results = self.perform_action(action) ... 


, , , - , , , , , , . , , - -, , , .

Demiurge, . , , insert_object. , :

 class Demiurge(object): def handle_creation(self, creation, refuse): pass class Field(object): def __init__(self, length, height): ... self.demiurge = None ... def insert_object(self, x, y, entity_object, epoch_shift=0): if self.demiurge is not None: refuse = False self.demiurge.handle_creation(entity_object, refuse) if refuse: return assert x < self.length assert y < self.height self.__field[y][x][-1] = entity_object entity_object.z = self.epoch + epoch_shift entity_object.board = self entity_object.x = x entity_object.y = y ... 


:


. — - . . — , , . , — . — , , .

Proof of concept II


だから、リ゜ヌスず停りの性の生き物を集めるこずで同じ問題を解決しおみたしょう。タスクは非垞に単玔なので、厳密に定矩されたアルゎリズムの助けを借りお可胜になるよりも、機械孊習の助けを借りおそれを解決できる可胜性は䜎いです。しかし、䜜業コンセプトを認識するために、私たちのコレクタヌが皮ずしお䞍本意たたは繁殖䞍胜から絶滅しないようにすれば十分です。

以䞋は、このような問題を解決する䟋の党文です。


 # Create deity class Priapus(field.Demiurge): # Create deity def __init__(self): self.public_memory = brain.LearningMemory(self) self.public_decision_model = SGDClassifier(warm_start=True) def handle_creation(self, creation, refuse): if isinstance(creation, entities.Creature): creation.public_memory = self.public_memory creation.public_decision_model = self.public_decision_model creation.memory_type = "public" creation.model_type = "public" creation.memory_batch_size = 20 if creation.sex: def difference_in_num_substance(entity): nearest_partner = actions.SearchMatingPartner(entity).do_results()["partner"] if nearest_partner is None: return 9e10 else: self_has_substance = entity.count_substance_of_type(substances.Substance) partner_has_substance = nearest_partner.count_substance_of_type(substances.Substance) return partner_has_substance - self_has_substance def possible_partners_exist(entity): find_partner = actions.SearchMatingPartner(entity) search_results = find_partner.do_results() return float(search_results["accomplished"]) features = [{"func": lambda creation: float(creation.has_state(states.NotTheRightMood)), "kwargs": {"creation": creation}}, {"func": difference_in_num_substance, "kwargs": {"entity": creation}}, {"func": possible_partners_exist, "kwargs": {"entity": creation}}] creation.set_memorize_task(actions.GoMating, features, {"func": lambda creation: creation.chosen_action.results["accomplished"], "kwargs": {"creation": creation}}) def plan(creature): if creature.sex: try: # raise NotFittedError current_features = creature.get_features(actions.GoMating) current_features = np.asarray(current_features).reshape(1, -1) if creature.public_decision_model.predict(current_features): go_mating = actions.GoMating(creature) creature.queue_action(go_mating) return else: harvest_substance = actions.HarvestSubstance(creature) harvest_substance.set_objective( **{"target_substance_type": type(substances.Substance())}) creature.queue_action(harvest_substance) return except NotFittedError: chosen_action = random.choice( [actions.GoMating(creature), actions.HarvestSubstance(creature)]) if isinstance(chosen_action, actions.HarvestSubstance): chosen_action.set_objective( **{"target_substance_type": type(substances.Substance())}) creature.queue_action(chosen_action) return else: harvest_substance = actions.HarvestSubstance(creature) harvest_substance.set_objective(**{"target_substance_type": type(substances.Substance())}) creature.queue_action(harvest_substance) creation.plan_callable = plan universe = field.Field(60, 40) # Create sample universe (length, height universe.set_demiurge(Priapus()) # Assign deity to universe # Fill universe with blanks, blocks, other scenery if necessary for y in range(10, 30): universe.insert_object(20, y, field.Block()) for x in range(21, 40): universe.insert_object(x, 10, field.Block()) for y in range(10, 30): universe.insert_object(40, y, field.Block()) universe.populate(entities.Creature, 20) # Populate universe with creatures def check_stop_function(field): return field.epoch >= 500 def score_function(field): stats = field.get_stats() if "Creature" not in stats: return 0 else: return stats["Creature"] res = modelling.run_simulation(universe, check_stop_function, score_function, verbose=True, times=30) print res print np.asarray(res).mean() 


おわりに


, , - . ( ) . :


, , , -, , -, . , , - , -, , . , , . , .

github. pygame sklearn , .

Source: https://habr.com/ru/post/J315424/


All Articles