0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MacBook Proで世界モデルDreamerV3を動かす

0
Posted at

はじめに

注意
本記事で書かれているコードはAIと対話しながら作成したものです。
自身の学習のためにまとめているため、不正確な記述がある可能性があります。
誤りがあれば指摘いただけると幸いです。

世界モデルというと、内部(潜在空間)でシミュレーションを行うため計算コストが高いイメージがありますが、簡単なものであればローカルでも実行が可能です。

⚠️ しかし後述するように、ローカルで実行できる試行回数では、性能向上はみられませんでした。

今回はMacBook Proを使用します。
AIモデルを動かす場合は、NvidiaのGPUが搭載されたPC(ゲーミングPCなど)やサーバーが必要となりますが、軽量なものであればMacBook Proでも実行可能です。

今回は世界モデルのなかでも有名なモデルの1つであるDreamerV3を使って、CrafterというAIの学習用につくられた2DのMinecraft風のゲーム上で検証します。

今回の検証にあたって参照した主要なリソースはこちらです。

DreamerV3に関する情報

また検証対象であるCrafterの解説については以下の論文やサイトがあります。

論文 (https://arxiv.org/abs/2109.06780)
PyPI (https://pypi.org/project/crafter/)



想定読者

本記事は、以下のような読者を想定して書いています。

  • AIについて概念的なところはなんとなく知っているけど、実装はほとんどやったことがない人
  • 世界モデルについて聞いたことあるけど、もっと実装レベルで具体的に理解したい人

なお世界モデル、およびDreamerV3の理論的な内容はこの記事では扱っておらず、あくまで動かせることを目的としています。



検証環境(Macのスペック)

まずは環境を整えていきます。

世界モデル「DreamerV3」の動作確認を行ったマシンのスペックは以下の通りです。

項目 スペック
モデル MacBook Pro (14インチ, 2021)
チップ (CPU/GPU) Apple M1 Pro (10コアCPU / 16コアGPU)
メモリ (RAM) 32 GB
OS macOS Sequoia (Version 15.0)

Macのスペックは、左上のリンゴマーク>このMacについてから確認することができます。



📦 ステップ1: Minicondaのインストール

まずは、今回の開発環境の土台となる Conda(コンダ) を準備します。

💡 Conda(Miniconda)とは?
Pythonの「バージョン」や「使いたいライブラリ(JAXなど)」を、PC内の他のプロジェクトと干渉させずに丸ごと別々に管理・保存できる「仮想環境マネージャー」です。

Conda環境が入っていない状態からスタートする場合は、以下のコマンドをターミナル上で実行してください。

ターミナル
# 1. ターミナルを開き、Apple Silicon Mac向けのMinicondaインストーラーをダウンロード
curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh

# 2. インストーラーの実行(利用規約やインストール先確認には Enter や yes で回答)
sh Miniconda3-latest-MacOSX-arm64.sh

⚠️ 完了後は設定を反映させるため、ターミナルアプリを一度完全に終了(Cmd + Q)させてから再起動してください。



📂 ステップ2: 作業フォルダの準備

次に、今回のDreamerV3をインストールし実行するための作業フォルダを準備します。

これからの作業は全てこのフォルダ内で行われるため、不要になったり、やり直したくなった際はこのフォルダを消してしまえば全て元通りです。

なお作業フォルダはHome直下に作成されます。
Finderからも確認(初期設定ではHome直下は隠されています)できるので、GUI上で削除も可能です。

ターミナル
# 1. ホームディレクトリ直下に専用の作業フォルダを作成
mkdir -p \~/dreamer\_workspace

# 2. 作成したフォルダの中に移動
cd \~/dreamer\_workspace



🧬 ステップ3: 仮想環境の作成と規約同意

最近のCondaは、コマンドを実行すると最初に利用規約への同意が求められます。あらかじめ同意しておきましょう。

ターミナル
# 1. Anaconda公式チャンネルの利用規約に事前に同意
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r

次に、DreamerV3を実行する仮想環境を作成します。

ターミナル
# 2. Python 3.11 を指定して「dreamer」環境を作成
conda create -n dreamer python=3.11 -y

# 3. 作成した仮想環境を有効化
conda activate dreamer



補足

誤って仮想環境を作成した場合は、まず仮想環境から抜け出したあと、仮想環境の削除を行なってください。

ターミナル
# 1. 仮想環境から抜け出す
conda deactivate

# 2. 仮想環境「dreamer」をフォルダごと一括で完全削除
conda remove -n dreamer --all -y



🕹️ ステップ4: 動作確認(任意)

これからDreamerV3を導入してCrafter上で学習していくわけですが、ものは試しに自分でもCrafterで遊んでみましょう。

⚠️ このステップで実行する内容は、後の実装には関係ないため、スキップしても構いません。

ターミナルから以下のコマンドを実行することで、Crafterの画面が開き、プレイすることができます。

ターミナル
# 1. 念のため作業フォルダに移動
cd \~/dreamer\_workspace

# 2. 仮想環境 dreamer を有効化(すでにターミナルの左端に (dreamer) と出ていれば不要です)
conda activate dreamer

# 3. pygameをインストール(どのディレクトリから実行しても dreamer 環境にインストールされます)
pip install pygame

# 4. 人間プレイ用GUIを起動!
python -m crafter.run\_gui

dreamerv3_crafter.png

プレイするための基本操作は以下の通りです。
これらの高度な作業を行うことでスコアがあがっていきます。


1. 移動と基本行動 🏃‍♂️
キー 割り当てアクション
W A S D エージェントを上下左右へ移動させる
SPACE 目の前の素材を収集する(木、石など)、湖から水を飲む、敵に攻撃する
TAB 避難所で眠る(体力を回復するが、夜ゾンビに襲われない安全な場所が必要)

2. オブジェクトの設置 🧱
キー 設置するオブジェクト 必要素材
T 作業台を設置する 木材
R 石を設置する(敵を閉じ込める壁などにする) 石材
F かまどを設置する(鉄を溶かすのに必要) 石炭 + 石材
P 植物を植える(将来リンゴが実る) 苗木

3. ツールや武器の作成 ⚒️

⚠️ 作成には、手元に「作業台」や「かまど」が設置されている必要があります。

キー 作成するツール
1 木のピッケルをクラフトする
2 石のピッケルをクラフトする
3 鉄のピッケルをクラフトする
4 木の剣をクラフトする
5 石の剣をクラフトする
6 鉄の剣をクラフトする

実際にプレイすると、人間でも慣れるには時間がかかりますね。



🧱 ステップ5: DreamerV3の取得とMac向け依存関係のインストール

ここまででDreamerV3を実行するための箱ができた状態となります。

以後はPythonのコードをガリガリ書いていくことになるため、ターミナル上ではなく、.pyファイルや、.ipynbファイルを新規に作成して実施していきます。

本記事ではVScode上でipynbファイルを使って作業を行なっていきます。VScodeのインストールはすでに済んでいる前提で進めていきます。

先ほど作成したdreamer\_workspaceフォルダの中に、.ipynbファイルを新規に作成します。

その前に.ipynbファイルから仮想環境を読み込めるよう、先ほどのターミナル上で以下を実行しておきます。

ターミナル
# 1. 仮想環境内にJupyter用のカーネル管理ツール(ipykernel)を導入
pip install ipykernel

# 2. 現在の「dreamer」環境をJupyterに登録
python -m ipykernel install --user --name dreamer --display-name "dreamer"

次に.ipynbファイル上で、先ほど作成した仮想環境がカーネルとして指定されているか確認します。

VSCode
# 📌 現在のJupyter環境が「dreamer」仮想環境を指しているか確認
import sys
import os

print("🐍 現在アクティブなPython実行環境:")
print(sys.executable)

if 'dreamer' in sys.executable:
    print("✅ 正しい仮想環境(dreamer)が選択されています!このまま進めてください。")
else:
    print("⚠️ 警告: 別の環境が選択されている可能性があります。VS Code右上のカーネル選択で「dreamer」を選択し直してください。")

ここで警告が表示された場合、異なるカーネルを選択してしまっていると思われます。

VSCodeの右上のアイコンから、別のカーネルを選択>Jupyter Kernel...から先ほど作成した仮想環境「dreamer」を選択して、再度上記のコードを実行して確認してください。

📂 ファイルの保存場所について
これからJupyter Notebook上でGitHubからコードをダウンロード(クローン)し、DreamerV3を動かすのに必要なリソースを取ってきます。
コマンドを実行すると、今作成した .ipynb ファイルと同じフォルダ(ディレクトリ)の直下に、dreamerv3 という名前のフォルダが自動的に作成され、その中に大量のプログラムファイル(main.py など)がダウンロードされます。

フォルダの階層は以下の通りです。

📁 フォルダの構成イメージ
dreamer\_workspace/           <-- VS Codeの作業フォルダ
 ├── dreamer\_study.ipynb     <-- 作成中のノートブック
 └── dreamerv3/              <-- この後自動生成されるフォルダ(main.pyなどが入る)
      ├── main.py         <-- 学習を起動するメインプログラム
      ├── requirements.txt
      └── ... (大量のファイル)

次にMacでは動かないNVIDIA GPU関連のパッケージを排除し、互換性を維持したバージョンを指定してセットアップします。

VSCode
# リポジトリのクローンとMac専用ライブラリのインストール
# 1. GitHubからDreamerV3リポジトリをクローンして、そのディレクトリへ移動
!git clone https://github.com/danijar/dreamerv3.git
# ノートブック全体の作業ディレクトリを dreamerv3 に固定
%cd dreamerv3

# 2. requirements.txtからNVIDIA/CUDA関連を除外したMac専用設定ファイルを生成
!grep -ivE "jax|nvidia|cuda|triton" requirements.txt > requirements\_mac.txt

# 3. 現在アクティブな「dreamer」環境のpipを使用して、基本的なライブラリ群をインストール
import sys
print("📦 基本的なライブラリ群をインストール中...")
!{sys.executable} -m pip install -r requirements\_mac.txt

# 4. Mac向けのJAX(CPU版・安定動作バージョン 0.4.26)を直接インストール
print("⚡ Mac向けJAX(CPU版 0.4.26)をインストール中...")
!{sys.executable} -m pip install "jax\[cpu]==0.4.26"

print("🎉 セットアップがすべて正常に完了しました!次のセルへ進んでください。")

⚠️ なぜここでバージョンを固定するのか?
Macで安定して動作するJAX 0.4.26に対して、最新の周辺ライブラリ(OptaxやChex)を入れると、内部仕様の不一致により ImportError などのバグを引き起こしてしまいます。
そのため、ここではあえてこれらを少し古いバージョン(Optaxは0.2.3未満、Chexは0.1.87未満)にダウングレードすることで、Mac上でJAXと完全に整合させ、動作を100%安定させます。

VSCode
# 📌 周辺パッケージのバージョン微調整とコアライブラリのインストール

import sys

# 5. JAXのバージョン(0.4.26)と競合しない周辺パッケージを個別にインストール
# (OptaxとChexのバージョンをダウングレードして整合性を保つ)
print("🔧 JAXと整合する周辺パッケージ (optax, chex) の導入中...")
!{sys.executable} -m pip install "optax<0.2.3" "chex<0.1.87"

# 6. 不足していたDreamerV3のコアライブラリをインストール
# (Crafter環境や、ベースとなるninjax、elementsなどを一括導入)
print("🧱 DreamerV3のコアライブラリおよびCrafter環境の導入中...")
!{sys.executable} -m pip install ninjax elements crafter gym ruamel.yaml

print("🎉 すべての依存パッケージの整合性が確保されました!")



🚀 ステップ6: 実行(CPU強制フラグ指定)

JAXのバックエンドエラーを防ぐため、CPUプラットフォームの指定オプションをつけて実行します。

例えば今回は1000回ほど学習をさせてみましょう。

VSCode
# DreamerV3の学習起動(動作テスト用: 1,000ステップ)
# JAXにCPUの使用を強制し、作成した仮想環境のPythonでメインスクリプトを実行
!JAX_PLATFORMS=cpu {sys.executable} main.py \
  --logdir ~/dreamer_workspace/logdir/dreamer_test \
  --configs crafter \
  --jax.platform cpu \
  --run.train_ratio 16 \
  --run.steps 1000

今回の環境であれば1分以内で完了します。
試行回数を増やしたい場合は、run.stepsの値を変更します。
5,000試行だと37分、10,000試行は143分、30,000試行だと半日~程度かかりました(途中スリープしたので計測できず)。



📊 ステップ7: 評価

試行が終わったら、結果を確認します。
実行中の記録は、logdirというフォルダの中のファイルに記載されています。

まずはログデータを加工します。

VSCode
# 📌 ワークスペース内のログフォルダから成績を集計
import pandas as pd
import json
import os

# ログを保存するパスを指定
raw\_path = '\~/dreamer\_workspace/logdir/dreamer\_test/scores.jsonl'
scores\_path = os.path.expanduser(raw\_path) 

if os.path.exists(scores\_path):
    with open(scores\_path, 'r') as f:
        data = \[json.loads(line) for line in f]
    df\_scores = pd.DataFrame(data)
    
    # 存在するキーを自動マッピング
    step\_col = next((c for c in df\_scores.columns if 'step' in c), None)
    score\_col = next((c for c in df\_scores.columns if 'score' in c), None)
    length\_col = next((c for c in df\_scores.columns if 'length' in c or 'duration' in c), None)
    
    # マッピング結果に基づいてデータフレームを構築
    summary\_cols = {}
    if step\_col:
        summary\_cols\['累積学習ステップ'] = df\_scores\[step\_col]
    if score\_col:
        summary\_cols\['獲得スコア (実績数)'] = df\_scores\[score\_col]
    if length\_col:
        summary\_cols\['生存ステップ数 (生存時間)'] = df\_scores\[length\_col]
        
    df\_summary = pd.DataFrame(summary\_cols)
    df\_summary.index.name = 'エピソード番号 (試行回数)'
    df\_summary.index = df\_summary.index + 1
    
    print(f"📊 【実行結果】全 {len(df\_scores)} エピソードのサバイバル成績")
    display(df\_summary)
    
    # 平均値の表示
    print("\\n📈 平均パフォーマンス:")
    if '生存ステップ数 (生存時間)' in df\_summary.columns:
        print(f"  - 平均生存ステップ: {df\_summary\['生存ステップ数 (生存時間)'].mean():.1f} steps")
    if '獲得スコア (実績数)' in df\_summary.columns:
        print(f"  - 平均獲得スコア:   {df\_summary\['獲得スコア (実績数)'].mean():.2f}")
else:
    print(f"❌ ログファイルが見つかりません。パスを確認してください: {scores\_path}")

続いて加工したデータを描画して、改善しているかチェックをします。

VSCode
# 📌 ワークスペース内のログから生存ステップを自動計算して描画
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import json
import os

# 日本語フォント設定
plt.rcParams\['font.sans-serif'] = \['Hiragino Sans', 'Arial Unicode MS', 'sans-serif']
plt.rcParams\['axes.unicode\_minus'] = False
sns.set\_theme(style="whitegrid", font='Hiragino Sans')

# パスを確実にワークスペース内の場所に修正
raw\_path = '\~/dreamer\_workspace/logdir/dreamer\_test/scores.jsonl'
scores\_path = os.path.expanduser(raw\_path)

if os.path.exists(scores\_path):
    with open(scores\_path, 'r') as f:
        data = \[json.loads(line) for line in f]
    df = pd.DataFrame(data)
    
    # 累積ステップ数から各エピソードの生存時間を算出
    df\['生存ステップ数'] = df\['step'].diff().fillna(df\['step']).astype(int)
    df\['episode'] = df.index + 1
    
    fig, axes = plt.subplots(1, 2, figsize=(14, 5))
    
    # 左側:生存ステップ数
    sns.lineplot(ax=axes\[0], data=df, x='episode', y='生存ステップ数', marker='o', color='forestgreen', linewidth=2.5)
    axes\[0].set\_title('🕒 生存ステップ数の推移(生存時間)', fontsize=13, fontweight='bold')
    axes\[0].set\_xlabel('エピソード(ゲーム試行回数)')
    axes\[0].set\_ylabel('生存時間(ステップ数)')
    axes\[0].locator\_params(integer=True)
    
    # 右側:総合スコア
    if 'episode/score' in df.columns:
        sns.lineplot(ax=axes\[1], data=df, x='episode', y='episode/score', marker='s', color='royalblue', linewidth=2.5)
        axes\[1].set\_title('🏆 総合スコアの推移(実績解除数)', fontsize=13, fontweight='bold')
        axes\[1].set\_xlabel('エピソード(ゲーム試行回数)')
        axes\[1].set\_ylabel('スコア(獲得ポイント)')
        axes\[1].locator\_params(integer=True)
        
    plt.tight\_layout()
    plt.show()
else:
    print(f"❌ ログファイルが見つかりません: {scores\_path}")

Crafterの実績はテクノロジーツリーになっています。
難易度は5段階で、全部で22種類の実績が存在します。
具体的には、以下のように実績がツリー状に繋がっています。

Crafterの実績
【レベル1: 生存の基本(5つ)】
  ├ 木を伐採する (Collect Wood)
  ├ 水を飲む (Collect Drink)
  ├ 苗木を拾う (Collect Sapling)
  ├ 植物を食べる (Eat Plant)
  └ 眠って起きる (Wake Up)
      │
      ▼
【レベル2: 基礎クラフト(5つ)】※木がないと作れない
  ├ 作業台を置く (Place Table) 
  ├ 木のツルハシを作る (Make Wood Pickaxe)
  ├ 木の剣を作る (Make Wood Sword) 
  ├ 牛を狩る (Eat Cow) 
  └ 苗木を植える (Place Plant)  
      │ 
      ▼ 
【レベル3: 石器時代(6つ)】※木の道具が必要
  ├ 石を掘る (Collect Stone) 
  ├ 石炭を掘る (Collect Coal) 
  ├ 石のツルハシを作る (Make Stone Pickaxe)
  ├ 石の剣を作る (Make Stone Sword) 
  ├ 石の壁を置く (Place Stone) 
  └ ゾンビを倒す (Defeat Zombie) 
      │ 
      ▼ 
【レベル4: 鉄器時代(5つ)】※石と石炭が必要
  ├ かまどを置く (Place Furnace) 
  ├ 鉄を掘る (Collect Iron)
  ├ 鉄のツルハシを作る (Make Iron Pickaxe)
  ├ 鉄の剣を作る (Make Iron Sword)
  └ スケルトンを倒す (Defeat Skeleton)
      │
      ▼
【レベル5: 最深部(1つ)】※鉄のツルハシが必要
  └ ダイヤを掘る (Collect Diamond)  💎 \[全22個目!]

📊 スコア計算のカラクリ

各エピソードで新しい実績を解除するたびに、AIには報酬が与えられ、episode/score: x.x という数値が成長の証拠です。
dreamerv3_eval.png

今回は30,000試行を行なってみましたが、見ての通り生存ステップ、スコアは横ばいでした。
試行が足らないのか、その場合30,000回でも相当時間かかっているので、ローカルでの実行は適切ではないのかもしれません。今後の課題となります。



補足

再度学習を実行する場合、ログファイルは末尾にさらにログが付け足されます。

ログも新しくしたい場合は、一度ログファイルを削除してください。

GUI上(dreamer\_workspace>logdir)で実行するか、.ipynbファイル上であれば以下のコードを実行します。

VSCode
import shutil
import os

log\_path = os.path.expanduser('\~/dreamer\_workspace/logdir')
if os.path.exists(log\_path):
    shutil.rmtree(log\_path)
    print("🗑️ ログフォルダを完全に削除しました!これでクリーンな状態で再学習できます。")
else:
    print("✨ ログフォルダは存在しません。すでにクリーンな状態です。")

まとめ

以上、MacBook ProでDreamerV3を実行してみました。
問題なく実行できることは分かりましたが、性能はイマイチ。
事前に教師あり学習をいれるなど、異なるアプローチも考えてみたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?