Pythonで学ぶAIの概念

Pythonで学ぶ探索とゲームAI:A*とミニマックス

古典的AIは、起こりうる状態を探索して問題を解きます。A*はここまでのコストと残りコストの見積もりを足して最も安い経路を見つけ、ミニマックスは相手が最善を尽くすと仮定して二人対戦ゲームの手を選びます。

やさしい言葉で概念を理解する

古典的AIは、起こりうる状態を探索して問題を解きます。A*はここまでのコストと残りコストの見積もりを足して最も安い経路を見つけ、ミニマックスは相手が最善を尽くすと仮定して二人対戦ゲームの手を選びます。

A*探索でグリッド上の最短経路を見つけ、ミニマックスでゲームの最善手を選びます。

重要なポイント

  • 見積もり(ヒューリスティック)が実際のコストを決して超えなければ、A*は最良の経路を見つけます。
  • ミニマックスは、決まった深さかゲームの終わりまでゲーム木を探索します。
  • アルファベータ枝刈りは、判断を変えられない枝をスキップします。
  • 遺伝的アルゴリズムは別の方法で探索し、候補解の集団を進化させます。

どのような場面で使う?

  • ニューラルネットワークやAIライブラリの内部で何が起きているかを理解する。
  • 対応するチャレンジで実装する前に考え方をつかむ。
  • 機械学習の講座、面接、プロジェクトに備える。

動かして理解する

再生を押すとA*がグリッドを探索します。セルをクリックすると壁を追加・削除できます。ゲーム木では葉をクリックしてスコアを変えられます。

サンプルコード

コードを実行 →
main.py
import heapq

# A* finds the cheapest path using cost so far + a guess of the cost left.
grid = ["S..#",
        ".#..",
        "...G"]
start, goal = (0, 0), (2, 3)
guess = lambda r, c: abs(r - goal[0]) + abs(c - goal[1])   # Manhattan distance

frontier = [(guess(*start), 0, start, [start])]
seen = set()
while frontier:
    _, cost, (r, c), path = heapq.heappop(frontier)
    if (r, c) == goal:
        print("path:", path, "cost:", cost)
        break
    if (r, c) in seen:
        continue
    seen.add((r, c))
    for dr, dc in ((0, 1), (1, 0), (0, -1), (-1, 0)):
        nr, nc = r + dr, c + dc
        if 0 <= nr < 3 and 0 <= nc < 4 and grid[nr][nc] != "#":
            heapq.heappush(frontier, (cost + 1 + guess(nr, nc), cost + 1, (nr, nc), path + [(nr, nc)]))

# Minimax: the maximizer assumes the opponent always picks the worst for it.
def minimax(node, maximizing):
    if isinstance(node, int):
        return node
    values = [minimax(child, not maximizing) for child in node]
    return max(values) if maximizing else min(values)

tree = [[3, 5], [2, 9], [0, 7]]   # our move, then the opponent's reply
print("best guaranteed score:", minimax(tree, True))

期待される出力

path: [(0, 0), (0, 1), (0, 2), (1, 2), (1, 3), (2, 3)] cost: 5
best guaranteed score: 3

仕組み

優先度付きキューは常に「コスト + 見積もり」が最小のマスを展開します。見積もりはゴールまでのマンハッタン距離なので、A*は壁を回り込んで5ステップでGに到達します。minimax()は自分の手番では最大値、相手の手番では最小値を取ります。最初の手は3を保証し、これは3つの最悪ケースの中で最も良い値です。

値を変更し、PythonをインストールせずにCodeUtilityオンラインPythonコンパイラで実行できます。

練習問題

入力値と境界ケースを変更し、より大きなデータでも動作を確認してください。

  1. 入力や重みを変えて、実行前に出力を予想してみましょう。
  2. 途中の値を出力して、計算の各ステップを追いましょう。
  3. 下のリンクのチャレンジを解いて、自分でアイデアを実装しましょう。
Python IDEで実行 →

チャレンジで練習する

このレッスンの内容を使って実際の問題を解きましょう。各チャレンジはブラウザで動き、すぐにテストされ、AI のレビューも受けられます。

すべてのチャレンジ