浏览代码

[MLA-1634] Compression spec (#5164)

/check-for-ModelOverriders
GitHub 4 年前
当前提交
1cc30d75
共有 31 个文件被更改,包括 240 次插入192 次删除
  1. 4
      Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/SensorBase.cs
  2. 4
      Project/Assets/ML-Agents/TestScenes/TestCompressedTexture/TestTextureSensor.cs
  3. 14
      com.unity.ml-agents.extensions/Runtime/Match3/Match3Sensor.cs
  4. 4
      com.unity.ml-agents.extensions/Runtime/Sensors/GridSensor.cs
  5. 4
      com.unity.ml-agents.extensions/Runtime/Sensors/PhysicsBodySensor.cs
  6. 8
      com.unity.ml-agents.extensions/Tests/Editor/Match3/Match3SensorTests.cs
  7. 5
      com.unity.ml-agents/CHANGELOG.md
  8. 2
      com.unity.ml-agents/Runtime/Analytics/Events.cs
  9. 42
      com.unity.ml-agents/Runtime/Communicator/GrpcExtensions.cs
  10. 2
      com.unity.ml-agents/Runtime/Policies/HeuristicPolicy.cs
  11. 4
      com.unity.ml-agents/Runtime/Sensors/BufferSensor.cs
  12. 4
      com.unity.ml-agents/Runtime/Sensors/CameraSensor.cs
  13. 24
      com.unity.ml-agents/Runtime/Sensors/ISensor.cs
  14. 4
      com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensor.cs
  15. 4
      com.unity.ml-agents/Runtime/Sensors/Reflection/ReflectionSensorBase.cs
  16. 4
      com.unity.ml-agents/Runtime/Sensors/RenderTextureSensor.cs
  17. 27
      com.unity.ml-agents/Runtime/Sensors/StackingSensor.cs
  18. 4
      com.unity.ml-agents/Runtime/Sensors/VectorSensor.cs
  19. 34
      com.unity.ml-agents/Tests/Editor/Communicator/GrpcExtensionsTests.cs
  20. 4
      com.unity.ml-agents/Tests/Editor/Inference/ParameterLoaderTest.cs
  21. 4
      com.unity.ml-agents/Tests/Runtime/Sensor/FloatVisualSensorTests.cs
  22. 4
      com.unity.ml-agents/Tests/Runtime/Sensor/SensorShapeValidatorTests.cs
  23. 19
      com.unity.ml-agents/Tests/Runtime/Sensor/StackingSensorTests.cs
  24. 4
      com.unity.ml-agents/Tests/Runtime/Utils/TestClasses.cs
  25. 23
      docs/Migrating.md
  26. 109
      com.unity.ml-agents/Runtime/Sensors/CompressionSpec.cs
  27. 3
      com.unity.ml-agents/Runtime/Sensors/CompressionSpec.cs.meta
  28. 30
      com.unity.ml-agents/Tests/Runtime/Sensor/CompressionSpecTests.cs
  29. 3
      com.unity.ml-agents/Tests/Runtime/Sensor/CompressionSpecTests.cs.meta
  30. 20
      com.unity.ml-agents/Runtime/Sensors/ISparseChannelSensor.cs
  31. 11
      com.unity.ml-agents/Runtime/Sensors/ISparseChannelSensor.cs.meta

4
Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/SensorBase.cs


}
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
public virtual CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
}
}

4
Project/Assets/ML-Agents/TestScenes/TestCompressedTexture/TestTextureSensor.cs


public void Reset() { }
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return m_CompressionType;
return CompressionSpec.Default();
}
}

14
com.unity.ml-agents.extensions/Runtime/Match3/Match3Sensor.cs


/// or uncompressed visual observations. Uses AbstractBoard.GetCellType()
/// and AbstractBoard.GetSpecialType() to determine the observation values.
/// </summary>
public class Match3Sensor : ISparseChannelSensor, IBuiltInSensor
public class Match3Sensor : ISensor, IBuiltInSensor
{
private Match3ObservationType m_ObservationType;
private AbstractBoard m_Board;

private int m_Columns;
private int m_NumCellTypes;
private int m_NumSpecialTypes;
private ISparseChannelSensor sparseChannelSensorImplementation;
private int SpecialTypeSize
{

{
}
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
internal SensorCompressionType GetCompressionType()
{
return m_ObservationType == Match3ObservationType.CompressedVisual ?
SensorCompressionType.PNG :

/// <inheritdoc/>
public string GetName()
public CompressionSpec GetCompressionSpec()
return m_Name;
return new CompressionSpec(GetCompressionType(), m_SparseChannelMapping);
public int[] GetCompressedChannelMapping()
public string GetName()
return m_SparseChannelMapping;
return m_Name;
}
/// <inheritdoc/>

4
com.unity.ml-agents.extensions/Runtime/Sensors/GridSensor.cs


}
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
public virtual CompressionSpec GetCompressionSpec()
return CompressionType;
return new CompressionSpec(CompressionType);
}
/// <inheritdoc/>

4
com.unity.ml-agents.extensions/Runtime/Sensors/PhysicsBodySensor.cs


public void Reset() { }
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
/// <inheritdoc/>

8
com.unity.ml-agents.extensions/Tests/Editor/Match3/Match3SensorTests.cs


Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
Assert.AreEqual(SensorCompressionType.None, sensor.GetCompressionType());
Assert.AreEqual(SensorCompressionType.None, sensor.GetCompressionSpec().SensorCompressionType);
var expectedObs = new float[]
{

Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
Assert.AreEqual(SensorCompressionType.None, sensor.GetCompressionType());
Assert.AreEqual(SensorCompressionType.None, sensor.GetCompressionSpec().SensorCompressionType);
var expectedObs = new float[]
{

Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
Assert.AreEqual(SensorCompressionType.PNG, sensor.GetCompressionType());
Assert.AreEqual(SensorCompressionType.PNG, sensor.GetCompressionSpec().SensorCompressionType);
var pngData = sensor.GetCompressedObservation();
if (WritePNGDataToFile)

Assert.AreEqual(expectedShape, sensorComponent.GetObservationShape());
Assert.AreEqual(InplaceArray<int>.FromList(expectedShape), sensor.GetObservationSpec().Shape);
Assert.AreEqual(SensorCompressionType.PNG, sensor.GetCompressionType());
Assert.AreEqual(SensorCompressionType.PNG, sensor.GetCompressionSpec().SensorCompressionType);
var concatenatedPngData = sensor.GetCompressedObservation();
var pathPrefix = "match3obs_special";

5
com.unity.ml-agents/CHANGELOG.md


`WriteMask(int branch, IEnumerable<int> actionIndices)` was replaced with
`SetActionEnabled(int branch, int actionIndex, bool isEnabled)`. (#5060)
- IActuator now implements IHeuristicProvider. (#5110)
- `ISensor.GetObservationShape()` was removed, and `GetObservationSpec()` was added. (#5127)
- `ISensor.GetObservationShape()` was removed, and `GetObservationSpec()` was added. The `ITypedSensor`
and `IDimensionPropertiesSensor` interfaces were removed. (#5127)
- `ISensor.GetCompressionType()` was removed, and `GetCompressionSpec()` was added. The `ISparseChannelSensor`
interface was removed. (#5164)
#### ml-agents / ml-agents-envs / gym-unity (Python)

2
com.unity.ml-agents/Runtime/Analytics/Events.cs


return new EventObservationSpec
{
SensorName = sensor.GetName(),
CompressionType = sensor.GetCompressionType().ToString(),
CompressionType = sensor.GetCompressionSpec().SensorCompressionType.ToString(),
BuiltInSensorType = (int)builtInSensorType,
DimensionInfos = dimInfos,
};

42
com.unity.ml-agents/Runtime/Communicator/GrpcExtensions.cs


var obsSpec = sensor.GetObservationSpec();
var shape = obsSpec.Shape;
ObservationProto observationProto = null;
var compressionType = sensor.GetCompressionType();
var compressionSpec = sensor.GetCompressionSpec();
var compressionType = compressionSpec.SensorCompressionType;
// Check capabilities if we need to concatenate PNGs
if (compressionType == SensorCompressionType.PNG && shape.Length == 3 && shape[2] > 3)
{

if (compressionType != SensorCompressionType.None && shape.Length == 3 && shape[2] > 3)
{
var trainerCanHandleMapping = Academy.Instance.TrainerCapabilities == null || Academy.Instance.TrainerCapabilities.CompressedChannelMapping;
var isTrivialMapping = IsTrivialMapping(sensor);
var isTrivialMapping = compressionSpec.IsTrivialMapping();
if (!trainerCanHandleMapping && !isTrivialMapping)
{
if (!s_HaveWarnedTrainerCapabilitiesMapping)

throw new UnityAgentsException(
$"GetCompressedObservation() returned null data for sensor named {sensor.GetName()}. " +
"You must return a byte[]. If you don't want to use compressed observations, " +
"return SensorCompressionType.None from GetCompressionType()."
"return CompressionSpec.Default() from GetCompressionSpec()."
CompressionType = (CompressionTypeProto)sensor.GetCompressionType(),
CompressionType = (CompressionTypeProto)sensor.GetCompressionSpec().SensorCompressionType,
var compressibleSensor = sensor as ISparseChannelSensor;
if (compressibleSensor != null)
if (compressionSpec.CompressedChannelMapping != null)
observationProto.CompressedChannelMapping.AddRange(compressibleSensor.GetCompressedChannelMapping());
observationProto.CompressedChannelMapping.AddRange(compressionSpec.CompressedChannelMapping);
}
}

VariableLengthObservation = rlCaps.VariableLengthObservation,
MultiAgentGroups = rlCaps.MultiAgentGroups,
};
}
internal static bool IsTrivialMapping(ISensor sensor)
{
var compressibleSensor = sensor as ISparseChannelSensor;
if (compressibleSensor is null)
{
return true;
}
var mapping = compressibleSensor.GetCompressedChannelMapping();
if (mapping == null)
{
return true;
}
// check if mapping equals zero mapping
if (mapping.Length == 3 && mapping.All(m => m == 0))
{
return true;
}
// check if mapping equals identity mapping
for (var i = 0; i < mapping.Length; i++)
{
if (mapping[i] != i)
{
return false;
}
}
return true;
}
#region Analytics

2
com.unity.ml-agents/Runtime/Policies/HeuristicPolicy.cs


{
foreach (var sensor in sensors)
{
if (sensor.GetCompressionType() == SensorCompressionType.None)
if (sensor.GetCompressionSpec().SensorCompressionType == SensorCompressionType.None)
{
m_ObservationWriter.SetTarget(m_NullList, sensor.GetObservationSpec(), 0);
sensor.Write(m_ObservationWriter);

4
com.unity.ml-agents/Runtime/Sensors/BufferSensor.cs


}
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
/// <inheritdoc/>

4
com.unity.ml-agents/Runtime/Sensors/CameraSensor.cs


public void Reset() { }
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return m_CompressionType;
return new CompressionSpec(m_CompressionType);
}
/// <summary>

24
com.unity.ml-agents/Runtime/Sensors/ISensor.cs


namespace Unity.MLAgents.Sensors
{
/// <summary>
/// The compression setting for visual/camera observations.
/// </summary>
public enum SensorCompressionType
{
/// <summary>
/// No compression. Data is preserved as float arrays.
/// </summary>
None,
/// <summary>
/// PNG format. Data will be stored in binary format.
/// </summary>
PNG
}
/// <summary>
/// The Dimension property flags of the observations
/// </summary>
[System.Flags]

void Reset();
/// <summary>
/// Return the compression type being used. If no compression is used, return
/// <see cref="SensorCompressionType.None"/>.
/// Return information on the compression type being used. If no compression is used, return
/// <see cref="CompressionSpec.Default()"/>.
/// <returns>Compression type used by the sensor.</returns>
SensorCompressionType GetCompressionType();
/// <returns>CompressionSpec used by the sensor.</returns>
CompressionSpec GetCompressionSpec();
/// <summary>
/// Get the name of the sensor. This is used to ensure deterministic sorting of the sensors

4
com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensor.cs


}
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
/// <inheritdoc/>

4
com.unity.ml-agents/Runtime/Sensors/Reflection/ReflectionSensorBase.cs


public void Reset() { }
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
/// <inheritdoc/>

4
com.unity.ml-agents/Runtime/Sensors/RenderTextureSensor.cs


public void Reset() { }
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return m_CompressionType;
return new CompressionSpec(m_CompressionType);
}
/// <inheritdoc/>

27
com.unity.ml-agents/Runtime/Sensors/StackingSensor.cs


/// Internally, a circular buffer of arrays is used. The m_CurrentIndex represents the most recent observation.
/// Currently, observations are stacked on the last dimension.
/// </summary>
public class StackingSensor : ISparseChannelSensor, IBuiltInSensor
public class StackingSensor : ISensor, IBuiltInSensor
{
/// <summary>
/// The wrapped sensor.

m_StackedObservations[i] = new float[m_UnstackedObservationSize];
}
if (m_WrappedSensor.GetCompressionType() != SensorCompressionType.None)
if (m_WrappedSensor.GetCompressionSpec().SensorCompressionType != SensorCompressionType.None)
{
m_StackedCompressedObservations = new byte[numStackedObservations][];
m_EmptyCompressedObservation = CreateEmptyPNG();

{
Array.Clear(m_StackedObservations[i], 0, m_StackedObservations[i].Length);
}
if (m_WrappedSensor.GetCompressionType() != SensorCompressionType.None)
if (m_WrappedSensor.GetCompressionSpec().SensorCompressionType != SensorCompressionType.None)
{
for (var i = 0; i < m_NumStackedObservations; i++)
{

return outputBytes;
}
/// <inheritdoc/>
public int[] GetCompressedChannelMapping()
public CompressionSpec GetCompressionSpec()
return m_CompressionMapping;
}
/// <inheritdoc/>
public SensorCompressionType GetCompressionType()
{
return m_WrappedSensor.GetCompressionType();
var wrappedSpec = m_WrappedSensor.GetCompressionSpec();
return new CompressionSpec(wrappedSpec.SensorCompressionType, m_CompressionMapping);
}
/// <summary>

}
/// <summary>
/// Constrct stacked CompressedChannelMapping.
/// Construct stacked CompressedChannelMapping.
/// </summary>
internal int[] ConstructStackedCompressedChannelMapping(ISensor wrappedSenesor)
{

int[] wrappedMapping = null;
int wrappedNumChannel = m_WrappedSpec.Shape[2];
var sparseChannelSensor = m_WrappedSensor as ISparseChannelSensor;
if (sparseChannelSensor != null)
{
wrappedMapping = sparseChannelSensor.GetCompressedChannelMapping();
}
wrappedMapping = wrappedSenesor.GetCompressionSpec().CompressedChannelMapping;
if (wrappedMapping == null)
{
if (wrappedNumChannel == 1)

4
com.unity.ml-agents/Runtime/Sensors/VectorSensor.cs


}
/// <inheritdoc/>
public virtual SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
/// <inheritdoc/>

34
com.unity.ml-agents/Tests/Editor/Communicator/GrpcExtensionsTests.cs


public void Reset() { }
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return CompressionType;
return new CompressionSpec(CompressionType);
}
}
class DummySparseChannelSensor : DummySensor, ISparseChannelSensor
{
public int[] Mapping;
internal DummySparseChannelSensor()
{
}
public int[] GetCompressedChannelMapping()
{
return Mapping;
}
}

}
[Test]
public void TestIsTrivialMapping()
{
Assert.AreEqual(GrpcExtensions.IsTrivialMapping(new DummySensor()), true);
var sparseChannelSensor = new DummySparseChannelSensor();
sparseChannelSensor.Mapping = null;
Assert.AreEqual(GrpcExtensions.IsTrivialMapping(sparseChannelSensor), true);
sparseChannelSensor.Mapping = new[] { 0, 0, 0 };
Assert.AreEqual(GrpcExtensions.IsTrivialMapping(sparseChannelSensor), true);
sparseChannelSensor.Mapping = new[] { 0, 1, 2, 3, 4 };
Assert.AreEqual(GrpcExtensions.IsTrivialMapping(sparseChannelSensor), true);
sparseChannelSensor.Mapping = new[] { 1, 2, 3, 4, -1, -1 };
Assert.AreEqual(GrpcExtensions.IsTrivialMapping(sparseChannelSensor), false);
sparseChannelSensor.Mapping = new[] { 0, 0, 0, 1, 1, 1 };
Assert.AreEqual(GrpcExtensions.IsTrivialMapping(sparseChannelSensor), false);
}
[Test]
public void TestDefaultTrainingEvents()
{

4
com.unity.ml-agents/Tests/Editor/Inference/ParameterLoaderTest.cs


public void Update() { }
public void Reset() { }
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
public string GetName()

4
com.unity.ml-agents/Tests/Runtime/Sensor/FloatVisualSensorTests.cs


public void Update() { }
public void Reset() { }
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
}

4
com.unity.ml-agents/Tests/Runtime/Sensor/SensorShapeValidatorTests.cs


public void Update() { }
public void Reset() { }
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return SensorCompressionType.None;
return CompressionSpec.Default();
}
}

19
com.unity.ml-agents/Tests/Runtime/Sensor/StackingSensorTests.cs


SensorTestHelper.CompareObservation(sensor, new[] { 0f, 0f, 0f, 0f, 5f, 6f });
}
class Dummy3DSensor : ISparseChannelSensor
class Dummy3DSensor : ISensor
{
public SensorCompressionType CompressionType = SensorCompressionType.PNG;
public int[] Mapping;

public void Reset() { }
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return CompressionType;
return new CompressionSpec(CompressionType, Mapping);
}
public string GetName()

public int[] GetCompressedChannelMapping()
{
return Mapping;
}
}
[Test]

var cameraSensor = new CameraSensor(new Camera(), 64, 64,
true, "grayscaleCamera", SensorCompressionType.PNG);
var stackedCameraSensor = new StackingSensor(cameraSensor, 2);
Assert.AreEqual(stackedCameraSensor.GetCompressedChannelMapping(), new[] { 0, 0, 0, 1, 1, 1 });
Assert.AreEqual(stackedCameraSensor.GetCompressionSpec().CompressedChannelMapping, new[] { 0, 0, 0, 1, 1, 1 });
Assert.AreEqual(stackedRenderTextureSensor.GetCompressedChannelMapping(), new[] { 0, 1, 2, 3, 4, 5 });
Assert.AreEqual(stackedRenderTextureSensor.GetCompressionSpec().CompressedChannelMapping, new[] { 0, 1, 2, 3, 4, 5 });
// Test mapping with number of layers not being multiple of 3
var dummySensor = new Dummy3DSensor();

Assert.AreEqual(stackedDummySensor.GetCompressedChannelMapping(), new[] { 0, 1, 2, 3, -1, -1, 4, 5, 6, 7, -1, -1 });
Assert.AreEqual(stackedDummySensor.GetCompressionSpec().CompressedChannelMapping, new[] { 0, 1, 2, 3, -1, -1, 4, 5, 6, 7, -1, -1 });
// Test mapping with dummy layers that should be dropped
var paddedDummySensor = new Dummy3DSensor();

Assert.AreEqual(stackedPaddedDummySensor.GetCompressedChannelMapping(), new[] { 0, 1, 2, 3, -1, -1, 4, 5, 6, 7, -1, -1 });
Assert.AreEqual(stackedPaddedDummySensor.GetCompressionSpec().CompressedChannelMapping, new[] { 0, 1, 2, 3, -1, -1, 4, 5, 6, 7, -1, -1 });
}
[Test]

4
com.unity.ml-agents/Tests/Runtime/Utils/TestClasses.cs


return new byte[] { 0 };
}
public SensorCompressionType GetCompressionType()
public CompressionSpec GetCompressionSpec()
return compressionType;
return new CompressionSpec(compressionType);
}
public string GetName()

23
docs/Migrating.md


- The `IActuator` interface now implements `IHeuristicProvider`. Please add the corresponding `Heuristic(in ActionBuffers)`
method to your custom Actuator classes.
- The `ISensor.GetObservationShape()` method was removed, and `GetObservationSpec()` was added. You can use
- The `ISensor.GetObservationShape()` method and `ITypedSensor`
and `IDimensionPropertiesSensor` interfaces were removed, and `GetObservationSpec()` was added. You can use
`ObservationSpec.Vector()` or `ObservationSpec.Visual()` to generate `ObservationSpec`s that are equivalent to
the previous shape. For example, if your old ISensor looked like:

public override ObservationSpec GetObservationSpec()
{
return ObservationSpec.Visual(m_Height, m_Width, m_NumChannels);
}
```
- The `ISensor.GetCompressionType()` method and `ISparseChannelSensor` interface was removed,
and `GetCompressionSpec()` was added. You can use `CompressionSpec.Default()` or
`CompressionSpec.Compressed()` to generate `CompressionSpec`s that are equivalent to
the previous values. For example, if your old ISensor looked like:
```csharp
public virtual SensorCompressionType GetCompressionType()
{
return SensorCompressionType.None;
}
```
the equivalent code would now be
```csharp
public CompressionSpec GetCompressionSpec()
{
return CompressionSpec.Default();
}
```

109
com.unity.ml-agents/Runtime/Sensors/CompressionSpec.cs


using System.Linq;
namespace Unity.MLAgents.Sensors
{
/// <summary>
/// The compression setting for visual/camera observations.
/// </summary>
public enum SensorCompressionType
{
/// <summary>
/// No compression. Data is preserved as float arrays.
/// </summary>
None,
/// <summary>
/// PNG format. Data will be stored in binary format.
/// </summary>
PNG
}
/// <summary>
/// A description of the compression used for observations.
/// </summary>
/// <remarks>
/// Most ISensor implementations can't take advantage of compression,
/// and should return CompressionSpec.Default() from their ISensor.GetCompressionSpec() methods.
/// Visual observations, or mulitdimensional categorical observations (for example, image segmentation
/// or the piece types in a match-3 game board) can use PNG compression reduce the amount of
/// data transferred between Unity and the trainer.
/// </remarks>
public struct CompressionSpec
{
internal SensorCompressionType m_SensorCompressionType;
/// <summary>
/// The compression type that the sensor will use for its observations.
/// </summary>
public SensorCompressionType SensorCompressionType
{
get => m_SensorCompressionType;
}
internal int[] m_CompressedChannelMapping;
/// The mapping of the channels in compressed data to the actual channel after decompression.
/// The mapping is a list of integer index with the same length as
/// the number of output observation layers (channels), including padding if there's any.
/// Each index indicates the actual channel the layer will go into.
/// Layers with the same index will be averaged, and layers with negative index will be dropped.
/// For example, mapping for CameraSensor using grayscale and stacking of two: [0, 0, 0, 1, 1, 1]
/// Mapping for GridSensor of 4 channels and stacking of two: [0, 1, 2, 3, -1, -1, 4, 5, 6, 7, -1, -1]
public int[] CompressedChannelMapping
{
get => m_CompressedChannelMapping;
}
/// <summary>
/// Return a CompressionSpec indicating possible compression.
/// </summary>
/// <param name="sensorCompressionType">The compression type to use.</param>
/// <param name="compressedChannelMapping">Optional mapping mapping of the channels in compressed data to the
/// actual channel after decompression.</param>
public CompressionSpec(SensorCompressionType sensorCompressionType, int[] compressedChannelMapping = null)
{
m_SensorCompressionType = sensorCompressionType;
m_CompressedChannelMapping = compressedChannelMapping;
}
/// <summary>
/// Return a CompressionSpec indicating no compression. This is recommended for most sensors.
/// </summary>
/// <returns></returns>
public static CompressionSpec Default()
{
return new CompressionSpec
{
m_SensorCompressionType = SensorCompressionType.None,
m_CompressedChannelMapping = null
};
}
/// <summary>
/// Return whether the compressed channel mapping is "trivial"; if so it doesn't need to be sent to the
/// trainer.
/// </summary>
/// <returns></returns>
internal bool IsTrivialMapping()
{
var mapping = CompressedChannelMapping;
if (mapping == null)
{
return true;
}
// check if mapping equals zero mapping
if (mapping.Length == 3 && mapping.All(m => m == 0))
{
return true;
}
// check if mapping equals identity mapping
for (var i = 0; i < mapping.Length; i++)
{
if (mapping[i] != i)
{
return false;
}
}
return true;
}
}
}

3
com.unity.ml-agents/Runtime/Sensors/CompressionSpec.cs.meta


fileFormatVersion: 2
guid: 0ddff1d1b7ad4170acb1a10272d4a8c2
timeCreated: 1616006929

30
com.unity.ml-agents/Tests/Runtime/Sensor/CompressionSpecTests.cs


using NUnit.Framework;
using Unity.MLAgents.Sensors;
namespace Unity.MLAgents.Tests
{
[TestFixture]
public class CompressionSpecTests
{
[Test]
public void TestIsTrivialMapping()
{
Assert.IsTrue(CompressionSpec.Default().IsTrivialMapping());
var spec = new CompressionSpec(SensorCompressionType.PNG, null);
Assert.AreEqual(spec.IsTrivialMapping(), true);
spec = new CompressionSpec(SensorCompressionType.PNG, new[] { 0, 0, 0 });
Assert.AreEqual(spec.IsTrivialMapping(), true);
spec = new CompressionSpec(SensorCompressionType.PNG, new[] { 0, 1, 2, 3, 4 });
Assert.AreEqual(spec.IsTrivialMapping(), true);
spec = new CompressionSpec(SensorCompressionType.PNG, new[] { 1, 2, 3, 4, -1, -1 });
Assert.AreEqual(spec.IsTrivialMapping(), false);
spec = new CompressionSpec(SensorCompressionType.PNG, new[] { 0, 0, 0, 1, 1, 1 });
Assert.AreEqual(spec.IsTrivialMapping(), false);
}
}
}

3
com.unity.ml-agents/Tests/Runtime/Sensor/CompressionSpecTests.cs.meta


fileFormatVersion: 2
guid: cd0990de0eb646b0b0531b91c840c9da
timeCreated: 1616030728

20
com.unity.ml-agents/Runtime/Sensors/ISparseChannelSensor.cs


namespace Unity.MLAgents.Sensors
{
/// <summary>
/// Sensor interface for sparse channel sensor which requires a compressed channel mapping.
/// </summary>
public interface ISparseChannelSensor : ISensor
{
/// <summary>
/// Returns the mapping of the channels in compressed data to the actual channel after decompression.
/// The mapping is a list of interger index with the same length as
/// the number of output observation layers (channels), including padding if there's any.
/// Each index indicates the actual channel the layer will go into.
/// Layers with the same index will be averaged, and layers with negative index will be dropped.
/// For example, mapping for CameraSensor using grayscale and stacking of two: [0, 0, 0, 1, 1, 1]
/// Mapping for GridSensor of 4 channels and stacking of two: [0, 1, 2, 3, -1, -1, 4, 5, 6, 7, -1, -1]
/// </summary>
/// <returns>Mapping of the compressed data</returns>
int[] GetCompressedChannelMapping();
}
}

11
com.unity.ml-agents/Runtime/Sensors/ISparseChannelSensor.cs.meta


fileFormatVersion: 2
guid: 63bb76c1e31c24fa5b4a384ea0edbfb0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存