Phase Aシミュレータ — アーキテクチャとvalence実験の具体化
028からの接続
028でTD学習+非対称valenceの定式化が完成した。ここではそれをpygameシミュレータの具体的な構造に落とす。
コア構造
GridWorld
class GridWorld:
width: int = 20
height: int = 15
reward_map: np.ndarray # shape=(h, w), 各セルの報酬値
# 環境のバリエーション
@staticmethod
def two_rooms():
"""最小実験環境: Room A(正報酬域) + 通路 + Room B(負報酬域)"""
# Room A: 左半分、reward = +1.0 (light/warmth相当)
# Room B: 右半分、reward = -1.0 (obstacle/cold相当)
# 通路: 中央2列、reward = 0
Agent(ローバーの脳)
class Agent:
# 位置
x, y: int
# TD学習パラメータ
alpha_pos: float # α+ (正のPEへの学習率)
alpha_neg: float # α- (負のPEへの学習率)
gamma: float = 0.9 # 割引率
# 状態価値マップ(= SpatialMemory)
V: np.ndarray # shape=(h, w), 各セルの学習済み価値
# 行動選択
epsilon: float = 0.1 # ε-greedy探索率
@property
def valence_ratio(self):
return self.alpha_pos / self.alpha_neg
def td_update(self, s, s_next, reward):
delta = reward + self.gamma * self.V[s_next] - self.V[s]
alpha = self.alpha_pos if delta > 0 else self.alpha_neg
self.V[s] += alpha * delta
return delta # ログ用
def choose_action(self):
"""隣接4セルのV値に基づくε-greedy選択"""
if random() < self.epsilon:
return random_neighbor()
return argmax_neighbor(self.V)
シミュレーションループ
for step in range(max_steps):
action = agent.choose_action()
s = (agent.x, agent.y)
agent.move(action)
s_next = (agent.x, agent.y)
reward = world.reward_map[s_next]
delta = agent.td_update(s, s_next, reward)
# 記録
trajectory.append(s_next)
td_errors.append(delta)
仮説C検証の精緻化: 対称性の自発的破れ
問い
valence_ratio=1.0(α+=α-)でも個性が発生するか?
実験プロトコル
Phase 1: 対称valenceの100回試行
- valence_ratio=1.0, alpha_base=0.1, gamma=0.9
- 同一環境(two_rooms)、異なる乱数シード×100
- 各試行 10,000 ステップ
測定:
- 最終1000ステップのRoom A滞在率
- 二峰性検定: この分布が二峰(二極に分かれる)か単峰(中間に集中)かを統計的に判定
- Hartigan's dip test (p < 0.05 なら二峰)
- カーネル密度推定で視覚確認
予測:
- 仮説A(二極): 滞在率が0.2付近と0.8付近に集中。dip test有意
- 仮説B(中間安定): 滞在率が0.5付近に集中。dip test非有意
- 仮説C(自発的破れ): 初期は分散するが収束先は二極的。ただし仮説Aとの区別が難しい
仮説AとCの区別方法
ここが本質的に難しい。両方とも最終的に二極分布を出す。違いは過程:
- 仮説A: 環境の構造的非対称性が原因(報酬配置に偏りがあるから)
- 仮説C: 偶然の経験順序が原因(対称な環境でも起きる)
区別実験: 完全対称環境
- Room AもRoom Bも同じ reward = +0.5
- 開始位置 = 通路中央(どちらにもequidistant)
- これでもA側/B側に偏りが出るなら、それは仮説C
さらに: 偏った試行群を途中(step 5000)でリセット(V=0)したとき:
- 仮説A: 同じ側に戻る(環境決定的だから)
- 仮説C: ランダムに再分配(偶然依存だから)
面白い派生: 初期経験の「窓」
仮説Cが成立するなら、「最初のN歩が個性を決める」という窓が存在するはず。
- N=10, 50, 100, 500 で初期経験を固定し、その後自由にしたときの収束先を比較
- Nが小さいうちは影響なし、あるNを超えると決定的になる → 個性の臨界期
- これは発達心理学の「臨界期/感受性期」と構造的に同型
Phase Aでやらないこと
- 知覚(画像入力)→ Phase B以降
- 社会的学習(他エージェント)→ Phase C以降
- 感情表示(TFT顔)→ 別モジュール、後で接続
- BLEトポロジ → 実機統合時
実装優先度
- GridWorld + Agent + TD更新ループ(最小動作)
- pygameによるリアルタイム可視化(V値のヒートマップ、エージェント位置、TD errorグラフ)
- valenceスイープのバッチ実行スクリプト
- 仮説C検証の対称環境実験
開いた問い
- 探索率εも個性パラメータにすべきか? — 低ε=慎重、高ε=冒険的。valenceとは独立な軸。でもまずvalenceに絞る判断は正しい
- 報酬のノイズ: 毎ステップR(s)+noise にすると「不確実な世界での個性」が見える。が、まず決定的環境で仮説検証
- 「個性の臨界期」が実機ローバーにもあるとしたら: 電源投入直後の数分間の経験がその後の行動を支配する? → ロボットほこ天でのデモとして非常にわかりやすい
3番目は面白い。「このローバーは、起動して最初に右に行ったから右寄りの個性になりました」と実演できたら、4/5のほこ天で説明しやすい。