Skip to content

Integrate BrainParameters with ActionSpec, update BrainParametersDrawer #4718

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Dec 12, 2020

Conversation

dongruoping
Copy link
Contributor

Proposed change(s)

  • Add an ActionSpec in BrainParameters, replace old fields in BrainParameters with corresponding fields in ActionSpec and deprecate the old fields
  • Add serialization callbacks to propagate ActionSpec fields from the old fields
  • Update BrainParametersDrawer to allow specifying hybrid actions in editor
  • ActionSpec is modified to be not read-only

Useful links (Github issues, JIRA tickets, ML-Agents forum threads etc.)

JIRA: MLA-1320

Types of change(s)

  • Bug fix
  • New feature
  • Code refactor
  • Breaking change
  • Documentation update
  • Other (please describe)

Checklist

  • Added tests that prove my fix is effective or that my feature works
  • Updated the changelog (if applicable)
  • Updated the documentation (if applicable)
  • Updated the migration guide (if applicable)

Other comments

@dongruoping dongruoping changed the title [WIP] Integrate BrainParameters with ActionSpec, update BrainParametersDrawer Integrate BrainParameters with ActionSpec, update BrainParametersDrawer Dec 8, 2020
@dongruoping
Copy link
Contributor Author

This change can go into hybrid staging or directly into master if staging is too huge

/// The size of the action space.
/// The specification of the Action space for the BrainParameters.
/// </summary>
public ActionSpec VectorActionSpec = new ActionSpec(0, 0, new int[] { });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept this simply because public ActionSpec ActionSpec = new ActionSpec(); looks a bit confusing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it okay to add new public fields to BrainParameters?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you can always add new public fields and methods.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do it in a few other places like this:

public abstract ActionSpec ActionSpec { get; }

and
public ActionSpec ActionSpec { get; }

I think it's better to have a slightly confusing declaration and simplify how people use it.


/// <summary>
/// Get the total number of Discrete Actions that can be taken by calculating the Sum
/// of all of the Discrete Action branch sizes.
/// </summary>
public int SumOfDiscreteBranchSizes { get; }
public int SumOfDiscreteBranchSizes { get { return m_SumOfDiscreteBranchSizes; } set { m_SumOfDiscreteBranchSizes = value; } }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably out of scope, but why is this public and not internal? I feel like ActionSpec should be only nContinuous and DiscreteBranchSizes...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed m_SumOfDiscreteBranchSizes and m_NumDiscreteActions, and derive them from branch sizes.

/// <param name="numDiscreteActions">Number of Discrete Actions</param>
/// <param name="branchSizes">The array of branch sizes for the discrete action space. Each index
/// contains the number of actions available for that branch.</param>
public void SetDiscrete(int numDiscreteActions, int[] branchSizes)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can SetDiscrete only take a single branchSizes argument ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I understand this question.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think he means public void SetDiscrete(int[] branchSizes).
This makes sense to me; only m_NumContinuousActions and m_DiscreteBranchSizes is necessary in ActionSpec for all information.

/// The size of the action space.
/// The specification of the Action space for the BrainParameters.
/// </summary>
public ActionSpec VectorActionSpec = new ActionSpec(0, 0, new int[] { });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it okay to add new public fields to BrainParameters?

@@ -72,16 +72,17 @@ static string BuildIntArrayLabel(SerializedProperty actionSizeProperty)
/// </summary>
void MakeActionsProperty(SerializedProperty property)
{
var actSizeProperty = property.FindPropertyRelative("VectorActionSize");
var actSpaceTypeProp = property.FindPropertyRelative("VectorActionSpaceType");
var actSpecProperty = property.FindPropertyRelative("VectorActionSpec");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move all of our strings to constants? Feels ripe for typo bugs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved them all to const strings

@surfnerd
Copy link
Contributor

surfnerd commented Dec 9, 2020

please run some yamato tests on this branch before merging.

@delete-merged-branch delete-merged-branch bot deleted the branch master December 9, 2020 22:13
/// Set action size fields related to continuous actions.
/// </summary>
/// <param name="numContinuousActions">Number of Continuous Actions</param>
public void SetContinuous(int numContinuousActions)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal?

If you keep this public, I think it should m_BranchSizes to null. As long it's only used in the one or two places that it currently is, it's probably OK as is.

Copy link
Contributor Author

@dongruoping dongruoping Dec 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it internal.

Add: Originally this is for safely setting discrete fields since there're multiple fields related to discrete spec. Now that there's only one (branch sizes) it's not necessary anymore. I might just remove it.

/// <param name="numDiscreteActions">Number of Discrete Actions</param>
/// <param name="branchSizes">The array of branch sizes for the discrete action space. Each index
/// contains the number of actions available for that branch.</param>
public void SetDiscrete(int[] branchSizes)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as SetContinuous

@@ -61,7 +68,8 @@ public class BrainParameters
/// For the discrete action space: the number of branches in the action space.
/// </value>
[FormerlySerializedAs("vectorActionSize")]
public int[] VectorActionSize = new[] { 1 };
[FormerlySerializedAs("VectorActionSize")]
public int[] VectorActionSizeDeprecated = new[] { 1 };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are public fields on a public class, so we can't rename them.

I think (@surfnerd correct me if I'm wrong) we can do something like

[FormerlySerializedAs("vectorActionSize")]
[FormerlySerializedAs("VectorActionSize")]
private int[] m_VectorActionSizeDeprecated; // or maybe internal

int[] VectorActionSize { 
  get { /* do something with ActionSpec */ } 
  set { /* do something with ActionSpec */ } 
}

(and similar for VectorActionSpaceType). The make sure to use the m_* fields (not the properties) in the OnBeforeSerialize methods.

/// </summary>
public int NumActions
public int NumActionsDeprecated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't rename. We can mark as [Obsolete] to discourage access though.

/// <summary>
/// Called by Unity immediately before serializing this object.
/// </summary>
/// <remarks>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent has a lot of boilerplate here since it's the main class and users will inherit from it. That shouldn't be the case for BrainParameters, so I think we can trim this down here.

/// </example>
public void OnAfterDeserialize()
{
if (!hasUpgradedBrainParametersWithActionSpec)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment on the docstring.

Can we move the logic here and in OnBeforeSerialize to a private UpdateToActionSpec() method?

@@ -32,24 +32,24 @@ public void WriteDiscreteActionMask(IDiscreteActionMask actionMask)
public void TestConstruct()
{
var ar = new TestActionReceiver();
var va = new VectorActuator(ar, new[] { 1, 2, 3 }, SpaceType.Discrete, "name");
var va = new VectorActuator(ar, ActionSpec.MakeDiscrete(new int[] { 1, 2, 3 }), "name");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var va = new VectorActuator(ar, ActionSpec.MakeDiscrete(new int[] { 1, 2, 3 }), "name");
var va = new VectorActuator(ar, ActionSpec.MakeDiscrete(1, 2, 3), "name");

MakeDiscrete uses [params](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/params) so you can skip the new int[] and just pass them like multiple args. Not a requirement, just some syntactic sugar.

@@ -423,7 +426,7 @@ def sac_entropy_loss(
)
# We update all the _cont_ent_coef as one block
entropy_loss += -1 * ModelUtils.masked_mean(
_cont_ent_coef * target_current_diff, loss_masks
torch.mean(_cont_ent_coef) * target_current_diff, loss_masks
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad merge? Looks like this is undoing #4725

@dongruoping dongruoping reopened this Dec 10, 2020
"Unknown enum value.");
}
ActionSpec = actionSpec;
string suffix = $"-Continuous-{actionSpec.NumContinuousActions}-Discrete-{actionSpec.NumDiscreteActions}";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically a behavior change. Not sure if there's any observable difference, though - maybe in how the actuators are sorted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed it back and only use that with hybrid action

/// </summary>
public ActionSpec ActionSpec
{
get { return new ActionSpec(m_NumContinuousActions, m_DiscreteBranchSizes); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this means that someone could do something like

myBrainParams.ActionSpec.NumContinuousActions = 4;

which would compile are run, but it would set NumContinuousActions on the new ActionSpec that gets returned here, but it wouldn't propagate to m_NumContinuousActions.

@surfnerd is there a better pattern for this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ActionSpec is a value type, so 'new' is redundant here I believe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without 'new' there will be compile error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the deprecated fields can be synced with corresponding new field, it's actually easier to just bring back ActionSpec and sync with ActionSpec fields to solve this problem.

{
m_ActionSpec.NumContinuousActions = value.NumContinuousActions;
m_ActionSpec.BranchSizes = value.BranchSizes;
if (m_ActionSpec.NumContinuousActions == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can this block be replaced with SyncDeprecatedActionFields()?

@@ -10,11 +10,10 @@ and this project adheres to
## [Unreleased]
### Major Changes
#### com.unity.ml-agents (C#)
- Agent with both continuous and discrete actions is now supported. You can specify
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This is still a minor change from semantic versioning point of view. We'll list it as "major" for the release notes though.

Also, please keep the old PR# (#4702) and add this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was following the python changelog. Is the python changes also minor?

@dongruoping dongruoping merged commit 4a8de9e into master Dec 12, 2020
@delete-merged-branch delete-merged-branch bot deleted the develop-hybrid-brainparameters2 branch December 12, 2020 07:21
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants