OpenAIの最新モデル o4


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

出力結果は下記.

Weasel Program を可能な限りリッチな表現を用いたコードで書いて.
その過程をアニメーションとして出力できるようにして.
import random
import string
from dataclasses import dataclass
from typing import List, Callable
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# ─── 個体クラス ──────────────────────────────────────────────
@dataclass
class Individual:
    genes: str

    def fitness(self, target: str) -> int:
        """ターゲット文字列との一致数を返す"""
        return sum(1 for g, t in zip(self.genes, target) if g == t)


# ─── 進化アルゴリズム本体 ────────────────────────────────────
class WeaselEvolution:
    def __init__(
        self,
        target: str,
        pop_size: int = 200,
        mutation_rate: float = 0.05,
        gene_pool: str = string.ascii_uppercase + ' ',
    ) -> None:
        self.target       = target
        self.pop_size     = pop_size
        self.mutation_rate = mutation_rate
        self.gene_pool    = gene_pool
        self.population   = self._init_population()
        self.generation   = 0

    def _init_population(self) -> List[Individual]:
        """ランダムな初期個体群を生成"""
        return [
            Individual(''.join(random.choices(self.gene_pool, k=len(self.target))))
            for _ in range(self.pop_size)
        ]

    def _evaluate(self) -> List[int]:
        """全個体のフィットネスを計算し、ソートして返す"""
        scored = [(ind, ind.fitness(self.target)) for ind in self.population]
        scored.sort(key=lambda x: x[1], reverse=True)
        self.population = [ind for ind, _ in scored]
        return [score for _, score in scored]

    def _select_parent(self, fitnesses: List[int]) -> Individual:
        """ルーレット選択"""
        total = sum(fitnesses)
        pick  = random.uniform(0, total)
        current = 0
        for ind, fit in zip(self.population, fitnesses):
            current += fit
            if current >= pick:
                return ind
        return self.population[0]

    def _mutate(self, parent: Individual) -> Individual:
        """突然変異を施した子個体を返す"""
        child_genes = list(parent.genes)
        for i in range(len(child_genes)):
            if random.random() < self.mutation_rate:
                child_genes[i] = random.choice(self.gene_pool)
        return Individual(''.join(child_genes))

    def next_generation(self) -> str:
        """1世代進化させ、最良個体の文字列を返す"""
        fitnesses = self._evaluate()
        # エリート(最良個体)はそのままキープ
        new_pop = [self.population[0]]
        # 残りは選択→突然変異で再生成
        while len(new_pop) < self.pop_size:
            parent = self._select_parent(fitnesses)
            new_pop.append(self._mutate(parent))
        self.population = new_pop
        self.generation += 1
        return self.population[0].genes


# ─── アニメーション設定 ────────────────────────────────────
def animate_evolution(
    target: str,
    pop_size: int = 200,
    mutation_rate: float = 0.05,
    max_gens: int = 1000,
    interval: int = 200,
) -> None:
    evo = WeaselEvolution(target, pop_size, mutation_rate)

    fig, ax = plt.subplots(figsize=(10, 4))
    text = ax.text(
        0.5, 0.5, '', 
        ha='center', va='center', 
        fontsize=24, family='monospace'
    )
    ax.axis('off')

    def update(frame: int):
        best = evo.next_generation()
        text.set_text(f'Gen {evo.generation:4d}: {best}')
        # 収束したらアニメーション停止
        if best == target:
            anim.event_source.stop()
        return (text,)

    anim = FuncAnimation(
        fig, update, 
        frames=max_gens, 
        blit=True, 
        interval=interval, 
        repeat=False
    )
    plt.show()
    # mp4として保存する場合はこちらを有効化:
    anim.save('weasel_evolution.mp4', writer='ffmpeg', dpi=200)

# ─── 実行例 ────────────────────────────────────────────────
if __name__ == '__main__':
    TARGET = "METHINKS IT IS LIKE A WEASEL"
    animate_evolution(
        target=TARGET,
        pop_size=300,
        mutation_rate=0.05,
        max_gens=500,
        interval=100
    )

o4-mini-highは視覚的に優れた推論を得意とするとうたっているが,確かに出力にクセがある.mp4での保存を提案してきた.

コメントを残す

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