はじめに:あの「謎の図」の正体
AIや機械学習の記事を読むと、必ずと言っていいほど出てくる「丸い粒がつながった図(ニューラルネットワーク図)」を見たことがありませんか?
左から右へ線が伸びているあの図です。 「なんとなくカッコいいから貼ってある」と思われがちですが、実は ML-Agents のプログラムは、あの図の通りに動いています。
今回は、C#のコードが、あの図の 「Input(入力)」 と 「Output(出力)」 のどこに突き刺さっているのか、具体的に定義します。
1. Input(入力層)の正体 = Observations
図の左側にある 「Input Layer(入力層)」。 これの正体は、C#側で定義する CollectObservations の中身そのもの です。
【定義】Observations(観測)とは何か?
Walker(歩行ロボット)の場合、具体的には以下の「数字のリスト」のことです。
- 腰(Hips)の情報
- 地面からの高さ(Y座標)
- 体の傾き(回転 X, Y, Z, W)
- 移動スピード(速度 X, Y, Z)
- 各手足(Joint)の情報
- 今の関節の角度
- 関節が動いている速度
- 足が地面についているか(0 または 1)
C#のコードで sensor.AddObservation(...) と書くたびに、このリストに数字が追加されていきます。
図との対応
もし、上記のような情報を全部あわせて「50個」の数字を送ったとします。 そうすると、ニューラルネットワーク図の 一番左にある「Input」の丸い粒は、縦に50個並ぶ ことになります。
つまり…
- Input: ロボットの「今の姿勢」を表す数字の列
- 対応コード:
Agent.CollectObservations()
2. Output(出力層)の正体 = Actions
図の右側にある 「Output Layer(出力層)」。 これの正体は、AIがはじき出した 「関節を動かすパワー(トルク)」 です。C#側では OnActionReceived で受け取ります。
【定義】Actions(行動)とは何か?
Walkerの場合、Outputとして出てくる数字は、各関節モーターへの指令値です。
- Continuous Actions(連続値)のリスト
- … (腕や頭など、動かしたい関節の数だけ続く)
図との対応
もしWalkerに動く関節が「15個」あるなら、ニューラルネットワーク図の 一番右にある「Output」の丸い粒は、縦に15個並びます。
つまり…
- Output: ロボットの「次の動き」を決める数字の列
- 対応コード:
Agent.OnActionReceived()
3. 全体像を整理しよう
これらを合わせると、ML-Agentsの通信(1ステップ)は以下のように翻訳できます。
【図解:データの流れ】
- Unity (C#)
CollectObservationsで「今の姿勢(Input)」を50個の数字にする。- Pythonへ送信! ➞ ➞ ➞
- Python (Neural Network)
- Input層: 50個の数字を受け取る。
- Hidden層:
config.yamlで設定したhidden_units: 512の数だけニューロンが発火し、複雑な計算を行う(ここが思考)。 - Output層: 計算結果として、「関節の強さ」を表す15個の数字を出す。
- Unityへ返信! ➞ ➞ ➞
- Unity (C#)
OnActionReceivedで「関節の強さ(Output)」を受け取る。- 物理エンジンで実際にロボットを動かす。
まとめ:エラーの原因が見えてくる
この対応関係がわかると、よくあるエラーの意味が理解できるようになります。
- エラー例:
Vector Observation Sizeが合っていません。- 意味: 「Inputの丸い粒の数」の設定ミスです。C#で送っているデータの数と、Unityエディタ上で設定した数がズレています。
- エラー例:
Continuous Action Sizeが足りません。- 意味: 「Outputの丸い粒の数」の設定ミスです。動かしたい関節が15個あるのに、AIの出口が10個しか用意されていません。
「なんとなく動かしていたコード」が、「AIの入口と出口を作っていた」という感覚に変われば、あなたはもう初心者卒業です!

