DiscreteBranchesを1、Branch 0 Sizeを3などにしているところを
DiscreteBranchesを3,Branch 0 Sizeを1にすることも(一応)可能です。
この設定では、エージェン トは3つの異なるブランチを持ち、それぞれが1つのアクションを提供する形になります。
-
新しいアクションの構成:
DiscreteBranchesが3、Branch 0 Sizeが1の場合、各ブランチは以下のようなアクションを持つことになります。- ブランチ0: アクション0
- ブランチ1: アクション1
- ブランチ2: アクション2
- 各ブランチからアクションを選択することができ、例えば、左に移動、右に移動、何もしない、などのアクションを分散させることができます。
-
スクリプトの変更:
変更前例 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」と「Buffers」の具体例を以下に示します。
1. アクションの種類(Branch)
移動(Movement)
- 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;
}
力を加える(Applying Force)
- Branch: 力を加えるアクションは、エージェントの動きを加速させたり、特定の方向に押し出したりするためのものです。これには、ジャンプ力を加えるや、ボールを打つ動作などが含まれます。
- Buffers: 力の大きさや方向を決定する情報が格納されます。
// 例: 力を加えるアクション
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);
}
}
2. Buffersの役割
ActionBuffers: これには、選択されたアクションが格納されます。離散アクションを選択することで、移動や力を加える動作を決定します。DiscreteActions: 各アクションは、離散的な整数値として表現されます。これにより、エージェントは与えられた状態に基づいて最適なアクションを選択し、学習します。
さらに追加で例を考えてみる
1. アクションの種類
-
状態変更 (State Changes):
- Branch: エージェントが環境の状態を変更するアクション(例: ドアを開ける、アイテムを拾う)。
- Buffers:
ActionBuffersには、どの状態に遷移するかを示す離散的なアクションが格納されます。
-
攻撃(Attacking):
- Branch: 攻撃動作(例: 近接攻撃、遠距離攻撃、特技の使用)。
- Buffers: 攻撃の種類や強度を選択するための情報を持つことができます。
-
防御(Defending):
- Branch: 防御行動(例: シールドを構える、回避行動)。
- Buffers: どの防御アクションを選択するか、またその効果の強さを格納します。
-
アイテムの使用(Using Items):
- Branch: アイテムを使用するアクション(例: 回復アイテムを使う、弾薬を補充)。
- Buffers: 使用するアイテムの種類や使用方法に関する情報。
2. 具体的な実装例
状態変更の例
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) // 回避行動
{
// 回避のロジック
}
}
3. Buffersの役割
それぞれの「Branch」に関連するアクションを管理するために、ActionBuffers を使用します。このバッファには、エージェントが選択したアクションが格納され、エージェントがそれに基づいて行動を決定します。例えば、DiscreteActions の配列が、どのアクションを選択したかを示す整数を含みます。
まとめ
このように、「Branch」と「Buffers」はエージェントの行動を整理し、学習を促進するための重要な構造です。様々な行動に対応するために、ブランチの設計とバッファの使い方を工夫することで、より複雑でインタラクティブなエージェントを作成することができます。