OpenAIの最新モデル o4


先日,OpenAIの最新のモデルとしてo3 のほかにo4-miniが発表された.今回はo3と比較してその性能を試してみたい.o3の時に送ったプロンプトと同じものを使用して差をみてみる.

出力結果は下記.

Weasel Program を可能な限りリッチな表現を用いたコードで書いて.
その過程をアニメーションとして出力できるようにして.
# Weasel Program with Animation in Google Colab
# ===================================================
# 目標フレーズに向かって文字列を「進化」させる過程を、
# matplotlib の FuncAnimation でアニメーション表示します。

import random
import string
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML

# Colab でアニメーションを埋め込む設定
plt.rcParams['animation.embed_limit'] = 2**128  # 大きめに設定

class WeaselProgram:
    """
    Weasel Program:
      - target: 目標フレーズ
      - pop_size: 各世代の個体数
      - mutation_rate: 1文字あたりの突然変異確率 (例: 0.05 は 5%)
      - max_generations: 最大世代数
    """
    def __init__(self,
                 target: str,
                 pop_size: int = 100,
                 mutation_rate: float = 0.05,
                 max_generations: int = 1000):
        self.target = target
        self.pop_size = pop_size
        self.mutation_rate = mutation_rate
        self.max_generations = max_generations
        self.alphabet = string.ascii_uppercase + ' '  # 空白も扱う

    def _random_individual(self) -> str:
        """ランダムな文字列個体を生成"""
        return ''.join(random.choice(self.alphabet) for _ in self.target)

    def _score(self, candidate: str) -> int:
        """目標フレーズとの一致文字数をスコアとする"""
        return sum(1 for c, t in zip(candidate, self.target) if c == t)

    def _mutate(self, parent: str) -> str:
        """突然変異を起こす(文字ごとに mutation_rate でランダム置換)"""
        chars = []
        for c in parent:
            if random.random() < self.mutation_rate:
                chars.append(random.choice(self.alphabet))
            else:
                chars.append(c)
        return ''.join(chars)

    def evolve(self) -> list:
        """
        プログラムを実行して各世代のベスト個体を history として返す。
        history[i] が i世代目の最良文字列。
        """
        # 初期集団の生成
        population = [self._random_individual() for _ in range(self.pop_size)]
        history = []

        for gen in range(self.max_generations):
            # スコア順でソートし、上位10%を親に選出
            scored = [(self._score(ind), ind) for ind in population]
            scored.sort(reverse=True, key=lambda x: x[0])
            best_score, best_ind = scored[0]
            history.append(best_ind)

            # 目標到達したら終了
            if best_ind == self.target:
                print(f"Reached target in generation {gen}!")
                break

            # 上位10%を親プールとし、新集団を生成
            cutoff = max(1, int(self.pop_size * 0.1))
            parents = [ind for _, ind in scored[:cutoff]]
            # 各親から子を複数生成して新集団を構築
            new_pop = []
            for _ in range(self.pop_size):
                parent = random.choice(parents)
                child = self._mutate(parent)
                new_pop.append(child)
            population = new_pop

        return history

# --- 実行部分 ---
if __name__ == "__main__":
    # パラメータ設定
    TARGET_PHRASE = "METHINKS IT IS LIKE A WEASEL"
    POPULATION_SIZE = 200
    MUTATION_RATE = 0.05
    MAX_GENERATIONS = 200

    # プログラム実行
    wp = WeaselProgram(
        target=TARGET_PHRASE,
        pop_size=POPULATION_SIZE,
        mutation_rate=MUTATION_RATE,
        max_generations=MAX_GENERATIONS
    )
    history = wp.evolve()  # 各世代のベスト文字列リスト

    # --- アニメーション表示設定 ---
    fig, ax = plt.subplots(figsize=(12, 2))
    ax.axis('off')

    # 文字ごとの x 座標
    x_positions = np.arange(len(TARGET_PHRASE)) * 0.5

    def update(frame: int):
        ax.clear()
        ax.axis('off')
        candidate = history[frame]
        # 各文字を色分け:一致は緑、不一致は黒
        for idx, char in enumerate(candidate):
            color = 'green' if char == TARGET_PHRASE[idx] else 'black'
            ax.text(x_positions[idx], 0.5, char,
                    color=color,
                    fontsize=24,
                    fontfamily='monospace',
                    ha='center', va='center')
        ax.set_title(f"Generation {frame + 1}/{len(history)}", fontsize=16)

    anim = FuncAnimation(
        fig,
        update,
        frames=len(history),
        interval=200,    # ミリ秒間隔
        repeat=False
    )

    # Colab 上で表示
    plt.close(fig)  # 重複描画を防ぐ
    display(HTML(anim.to_jshtml()))

するとこんな出力が返ってきた.

o4-miniの場合はもう少しプロントを工夫する必要があるかもしれない.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です