-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
[MLA-1634] Add ObservationSpec and update ISensor interfaces #5127
Conversation
@@ -2,6 +2,22 @@ | |||
"m_Name": "Settings", | |||
"m_Path": "ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json", | |||
"m_Dictionary": { | |||
"m_DictionaryValues": [] | |||
"m_DictionaryValues": [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what to do with this. It got added in 7718dfe#diff-41dd07c8a0392e1f6c2a7ba1277f3426cdc92aa8258e563912c39db66800ade0 but wasn't computing coverage on the assemblies we care about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I think it's just for local runs of code coverage
@@ -475,14 +475,6 @@ public void ClearPerceptionBuffer() | |||
} | |||
} | |||
|
|||
/// <summary>Gets the shape of the grid observation</summary> | |||
/// <returns>integer array shape of the grid observation</returns> | |||
public int[] GetFloatObservationShape() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was unused.
public override int[] GetObservationShape() | ||
{ | ||
m_Shape = new[] { GridNumSideX, GridNumSideZ, ObservationPerCell }; | ||
return m_Shape; | ||
var shape = m_ObservationSpec.Shape; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the SensorComponent override, not sure if we should change that to return a spec too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would lean toward yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'm going to punt that to a separate PR.
@@ -10,6 +10,7 @@ public interface IDiscreteActionMask | |||
/// <summary> | |||
/// Set whether or not the action index for the given branch is allowed. | |||
/// </summary> | |||
/// <remarks> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not from here, but was broken in staging.
/// This is a value type that does not allocate any additional memory. | ||
/// </summary> | ||
/// <remarks> | ||
/// This does not implement any interfaces such as IList, in order to avoid any accidental boxing allocations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small tradeoff between ergonomics and efficiency. It's small either way, so I'm willing to change this.
/// <param name="lhs"></param> | ||
/// <param name="rhs"></param> | ||
/// <returns>Whether the arrays are equivalent.</returns> | ||
public static bool operator==(InplaceArray<T> lhs, InplaceArray<T> rhs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the recommended way to do operator== and Equals() for a value type? Should the implementation be in Equals() instead?
/// <returns></returns> | ||
public override int GetHashCode() | ||
{ | ||
return Tuple.Create(m_Elem0, m_Elem1, m_Elem2, m_Elem3, Length).GetHashCode(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not currently used anywhere, but I had to add this if I overrode Equals().
/// <summary> | ||
/// The ObservationType enum of the Sensor. | ||
/// </summary> | ||
public enum ObservationType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were made public, but didn't make any other changes to them. We'll remove Reward and Message, and rename Goal later.
/// For example, a sensor that observes the velocity of a rigid body (in 3D) would use [3]. | ||
/// A sensor that returns an RGB image would use [Height, Width, 3]. | ||
/// </summary> | ||
public InplaceArray<int> Shape; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open to discussion on the visibility for these fields, and also the constructor. I think the static helpers (Vector, VariableLength, Visual) are good for all the purposes that we currently support in the trainer, and a user could potentially implement their own trainer that supported different combos of properties (e.g. convolutional 1D or 3D).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to expose the ObservationSpec() constructor, and with that it's flexible enough for users to customize their own and not necessary to expose the fields
We check in the constructor that the length of shape and dimensionProperties match. Users can potentially set shape and dimensionProperties with different length if we expose the fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, you convinced me. I'll make the fields internal and add public get properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
{ | ||
Debug.Assert(cachedShape[j] == sensorShape[j], "Sensor sizes must match."); | ||
} | ||
var cachedSpec = m_SensorShapes[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This got a little simpler (and probably faster)
@@ -1,9 +1,10 @@ | |||
fileFormatVersion: 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you, i saw this before and it was annoying me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it was accidental (but also annoying me).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like what I see
/// </summary> | ||
/// <param name="length"></param> | ||
/// <returns></returns> | ||
public static ObservationSpec Vector(int length) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Vector and Visual, add ObservationType to the static constructors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but make them default to Default? Sure, that sounds reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vincentpierre Any reason to not add that to VariableLength also?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The goal conditioning trainer will not work with VariableLength obs. We can add it though, but the trainer will raise an error or a warning when this happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, removed the variable length.
/// This does not implement any interfaces such as IList, in order to avoid any accidental boxing allocations. | ||
/// </remarks> | ||
/// <typeparam name="T"></typeparam> | ||
public struct InplaceArray<T> where T : struct |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a
public struct ObservationShape : InplaceArray<int> { }
And same for DimensionProperties. Thoughts? Maybe overkill
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the constructors wouldn't work without adding them to ObservationShape too (plus DimensionProperties), which I'd rather not do.
And using ObservationShape = InplaceArray<int>;
is only scoped for the file it's declared in, so wouldn't help any calling code.
var dimInfos = new EventObservationDimensionInfo[shape.Length]; | ||
for (var i = 0; i < shape.Length; i++) | ||
{ | ||
dimInfos[i].Size = shape[i]; | ||
dimInfos[i].Flags = dimProps != null ? (int)dimProps[i] : 0; | ||
dimInfos[i].Flags = (int)dimProps[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dats nice
/// This does not implement any interfaces such as IList, in order to avoid any accidental boxing allocations. | ||
/// </remarks> | ||
/// <typeparam name="T"></typeparam> | ||
public struct InplaceArray<T> where T : struct |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any plans of adding methods for converting between this and barracuda tensorshape?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could do it as an extension method somewhere. Where would it be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's save this for another PR - don't think it'll affect the public API
Proposed change(s)
Note that this does not introduce CompressionSpec or remove ISparseChannelSensor yet; this was getting big, so I'm saving that for a subsequent PR.
I haven't updated the docs or migration guide yet, will do that soon. Test coverage is done though.
Follow-Ups in subsequent PRs
Useful links (Github issues, JIRA tickets, ML-Agents forum threads etc.)
https://jira.unity3d.com/browse/MLA-1634
Alternative to #5076
(Unity internal) design proposal
Types of change(s)
Checklist
Other comments