DiscreteBranchesを1、Branch 0 Sizeを3などにしているところを
DiscreteBranchesを3,Branch 0 Sizeを1にすることも(一応)可能です。
この設定では、エージェントは3つの異なるブランチを持ち、それぞれが1つのアクションを提供する形になります。
DiscreteBranches
が3、Branch 0 Size
が1の場合、各ブランチは以下のようなアクションを持つことになります。
変更前例 4-5 セルフプレイから抜粋
public override void OnActionReceived(ActionBuffers actionBuffers)
{
// PingPongAgentの移動
float dir = (agentId == 0) ? 1.0f : -1.0f;
int action = actionBuffers.DiscreteActions[0];
Vector3 pos = this.transform.localPosition;
if (action == 1)
{
pos.x -= 0.2f * dir;
}
else if (action == 2)
{
pos.x += 0.2f * dir;
}
if (pos.x < -4.0f) pos.x = -4.0f;
if (pos.x > 4.0f) pos.x = 4.0f;
this.transform.localPosition = pos;
}
actionBuffers.DiscreteActions[0]
のみに依存しており、1つのアクションに基づいてパドルの移動を制御しています。新しい設定に合わせるためには、すべてのブランチからのアクションを処理するようにスクリプトを変更する必要があります。以下のようにスクリプトを変更することが考えられます:
public override void OnActionReceived(ActionBuffers actionBuffers)
{
// PingPongAgentの移動
float dir = (agentId == 0) ? 1.0f : -1.0f;
Vector3 pos = this.transform.localPosition;
// 各ブランチのアクションを取得
int actionBranch0 = actionBuffers.DiscreteActions[0]; // Branch 0
int actionBranch1 = actionBuffers.DiscreteActions[1]; // Branch 1
int actionBranch2 = actionBuffers.DiscreteActions[2]; // Branch 2
// 各アクションに基づいて移動
if (actionBranch0 == 1) // 例えば、左に移動
{
pos.x -= 0.2f * dir;
}
if (actionBranch1 == 1) // 例えば、右に移動
{
pos.x += 0.2f * dir;
}
// actionBranch2など、追加のアクションを必要に応じて処理
// 位置制限
if (pos.x < -4.0f) pos.x = -4.0f;
if (pos.x > 4.0f) pos.x = 4.0f;
this.transform.localPosition = pos;
}
移動や力を加えるアクションを考える際に、強化学習エージェントの「Branch」と「Buffers」の具体例を以下に示します。
Branch 1
Buffers 3
// 例: 移動アクション
public override void OnActionReceived(ActionBuffers actionBuffers)
{
int action = actionBuffers.DiscreteActions[0];
Vector3 pos = transform.localPosition;
// アクションに応じた移動
if (action == 0) // 何もしない
{
// 位置は変更しない
}
else if (action == 1) // 左に移動
{
pos.x -= 0.2f;
}
else if (action == 2) // 右に移動
{
pos.x += 0.2f;
}
// 位置を更新
transform.localPosition = pos;
}
// 例: 力を加えるアクション
public override void OnActionReceived(ActionBuffers actionBuffers)
{
int action = actionBuffers.DiscreteActions[0];
Rigidbody rb = GetComponent<Rigidbody>();
// アクションに応じた力の加え方
if (action == 0) // 力を加えない
{
// 何もしない
}
else if (action == 1) // 上にジャンプ
{
rb.AddForce(Vector3.up * 5f, ForceMode.Impulse);
}
else if (action == 2) // 前に押す
{
rb.AddForce(Vector3.forward * 5f, ForceMode.Impulse);
}
}
ActionBuffers
: これには、選択されたアクションが格納されます。離散アクションを選択することで、移動や力を加える動作を決定します。DiscreteActions
: 各アクションは、離散的な整数値として表現されます。これにより、エージェントは与えられた状態に基づいて最適なアクションを選択し、学習します。ActionBuffers
には、どの状態に遷移するかを示す離散的なアクションが格納されます。public override void OnActionReceived(ActionBuffers actionBuffers)
{
int action = actionBuffers.DiscreteActions[0];
if (action == 0) // ドアを開ける
{
// ドアを開けるロジック
}
else if (action == 1) // アイテムを拾う
{
// アイテムを拾うロジック
}
}
public override void OnActionReceived(ActionBuffers actionBuffers)
{
int action = actionBuffers.DiscreteActions[0];
if (action == 0) // 近接攻撃
{
// 近接攻撃のロジック
}
else if (action == 1) // 遠距離攻撃
{
// 遠距離攻撃のロジック
}
}
public override void OnActionReceived(ActionBuffers actionBuffers)
{
int action = actionBuffers.DiscreteActions[0];
if (action == 0) // シールドを構える
{
// シールドのロジック
}
else if (action == 1) // 回避行動
{
// 回避のロジック
}
}
それぞれの「Branch」に関連するアクションを管理するために、ActionBuffers
を使用します。このバッファには、エージェントが選択したアクションが格納され、エージェントがそれに基づいて行動を決定します。例えば、DiscreteActions
の配列が、どのアクションを選択したかを示す整数を含みます。
このように、「Branch」と「Buffers」はエージェントの行動を整理し、学習を促進するための重要な構造です。様々な行動に対応するために、ブランチの設計とバッファの使い方を工夫することで、より複雑でインタラクティブなエージェントを作成することができます。