浏览代码

[MLA-1783] built-in actuator type (#4950)

/release_13_branch
GitHub 3 年前
当前提交
d1f0fc4c
共有 15 个文件被更改,包括 225 次插入27 次删除
  1. 12
      com.unity.ml-agents.extensions/Runtime/Input/InputActionActuator.cs
  2. 9
      com.unity.ml-agents.extensions/Runtime/Match3/Match3Actuator.cs
  3. 8
      com.unity.ml-agents/Runtime/Actuators/VectorActuator.cs
  4. 21
      com.unity.ml-agents/Runtime/Agent.cs
  5. 31
      com.unity.ml-agents/Runtime/Analytics/Events.cs
  6. 18
      com.unity.ml-agents/Runtime/Analytics/InferenceAnalytics.cs
  7. 17
      com.unity.ml-agents/Runtime/Analytics/TrainingAnalytics.cs
  8. 10
      com.unity.ml-agents/Runtime/Policies/BarracudaPolicy.cs
  9. 6
      com.unity.ml-agents/Runtime/Policies/BehaviorParameters.cs
  10. 10
      com.unity.ml-agents/Runtime/Policies/RemotePolicy.cs
  11. 2
      com.unity.ml-agents/Runtime/Sensors/IBuiltInSensor.cs
  12. 18
      com.unity.ml-agents/Tests/Editor/Analytics/InferenceAnalyticsTests.cs
  13. 38
      com.unity.ml-agents/Tests/Editor/Analytics/TrainingAnalyticsTest.cs
  14. 49
      com.unity.ml-agents/Runtime/Actuators/IBuiltInActuator.cs
  15. 3
      com.unity.ml-agents/Runtime/Actuators/IBuiltInActuator.cs.meta

12
com.unity.ml-agents.extensions/Runtime/Input/InputActionActuator.cs


/// <see cref="Agent"/>'s <see cref="BehaviorParameters"/> indicate that the Agent is running in Heuristic Mode,
/// this Actuator will write actions from the <see cref="InputSystem"/> to the <see cref="ActionBuffers"/> object.
/// </summary>
public class InputActionActuator : IActuator, IHeuristicProvider
public class InputActionActuator : IActuator, IHeuristicProvider, IBuiltInActuator
{
readonly BehaviorParameters m_BehaviorParameters;
readonly InputAction m_Action;

/// <param name="adaptor">The <see cref="IRLActionInputAdaptor"/> that will convert data between ML-Agents
/// and the <see cref="InputSystem"/>.</param>
public InputActionActuator(InputDevice inputDevice, BehaviorParameters behaviorParameters,
InputAction action,
IRLActionInputAdaptor adaptor)
InputAction action,
IRLActionInputAdaptor adaptor)
{
m_BehaviorParameters = behaviorParameters;
Name = $"InputActionActuator-{action.name}";

Profiler.BeginSample("InputActionActuator.Heuristic");
m_InputAdaptor.WriteToHeuristic(m_Action, actionBuffersOut);
Profiler.EndSample();
}
/// <inheritdoc/>
public BuiltInActuatorType GetBuiltInActuatorType()
{
return BuiltInActuatorType.InputActionActuator;
}
}
}

9
com.unity.ml-agents.extensions/Runtime/Match3/Match3Actuator.cs


/// Actuator for a Match3 game. It translates valid moves (defined by AbstractBoard.IsMoveValid())
/// in action masks, and applies the action to the board via AbstractBoard.MakeMove().
/// </summary>
public class Match3Actuator : IActuator, IHeuristicProvider
public class Match3Actuator : IActuator, IHeuristicProvider, IBuiltInActuator
{
protected AbstractBoard m_Board;
protected System.Random m_Random;

/// <inheritdoc/>
public void ResetData()
{
}
/// <inheritdoc/>
public BuiltInActuatorType GetBuiltInActuatorType()
{
return BuiltInActuatorType.Match3Actuator;
}
IEnumerable<int> InvalidMoveIndices()

{
return 1;
}
}
}

8
com.unity.ml-agents/Runtime/Actuators/VectorActuator.cs


/// <summary>
/// IActuator implementation that forwards calls to an <see cref="IActionReceiver"/> and an <see cref="IHeuristicProvider"/>.
/// </summary>
internal class VectorActuator : IActuator, IHeuristicProvider
internal class VectorActuator : IActuator, IHeuristicProvider, IBuiltInActuator
{
IActionReceiver m_ActionReceiver;
IHeuristicProvider m_HeuristicProvider;

/// <inheritdoc />
public string Name { get; }
/// <inheritdoc />
public virtual BuiltInActuatorType GetBuiltInActuatorType()
{
return BuiltInActuatorType.VectorActuator;
}
}
}

21
com.unity.ml-agents/Runtime/Agent.cs


}
/// <summary>
/// Simple wrapper around VectorActuator that overrides GetBuiltInActuatorType
/// so that it can be distinguished from a standard VectorActuator.
/// </summary>
internal class AgentVectorActuator : VectorActuator
{
public AgentVectorActuator(IActionReceiver actionReceiver,
IHeuristicProvider heuristicProvider,
ActionSpec actionSpec,
string name = "VectorActuator"
) : base(actionReceiver, heuristicProvider, actionSpec, name)
{ }
public override BuiltInActuatorType GetBuiltInActuatorType()
{
return BuiltInActuatorType.AgentVectorActuator;
}
}
/// <summary>
/// An agent is an actor that can observe its environment, decide on the
/// best course of action using those observations, and execute those actions
/// within the environment.

// Support legacy OnActionReceived
// TODO don't set this up if the sizes are 0?
var param = m_PolicyFactory.BrainParameters;
m_VectorActuator = new VectorActuator(this, this, param.ActionSpec);
m_VectorActuator = new AgentVectorActuator(this, this, param.ActionSpec);
m_ActuatorManager = new ActuatorManager(attachedActuators.Length + 1);
m_LegacyActionCache = new float[m_VectorActuator.TotalNumberOfActions()];
m_LegacyHeuristicCache = new float[m_VectorActuator.TotalNumberOfActions()];

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


public int InferenceDevice;
public List<EventObservationSpec> ObservationSpecs;
public EventActionSpec ActionSpec;
public List<EventActuatorInfo> ActuatorInfos;
public int MemorySize;
public long TotalWeightSizeBytes;
public string ModelHash;

NumContinuousActions = actionSpec.NumContinuousActions,
NumDiscreteActions = actionSpec.NumDiscreteActions,
BranchSizes = branchSizes,
};
}
}
/// <summary>
/// Information about an actuator.
/// </summary>
[Serializable]
internal struct EventActuatorInfo
{
public int BuiltInActuatorType;
public int NumContinuousActions;
public int NumDiscreteActions;
public static EventActuatorInfo FromActuator(IActuator actuator)
{
BuiltInActuatorType builtInActuatorType = Actuators.BuiltInActuatorType.Unknown;
if (actuator is IBuiltInActuator builtInActuator)
{
builtInActuatorType = builtInActuator.GetBuiltInActuatorType();
}
var actionSpec = actuator.ActionSpec;
return new EventActuatorInfo
{
BuiltInActuatorType = (int)builtInActuatorType,
NumContinuousActions = actionSpec.NumContinuousActions,
NumDiscreteActions = actionSpec.NumDiscreteActions
};
}
}

public string BehaviorName;
public List<EventObservationSpec> ObservationSpecs;
public EventActionSpec ActionSpec;
public List<EventActuatorInfo> ActuatorInfos;
/// <summary>
/// This will be the same as TrainingEnvironmentInitializedEvent if available, but

18
com.unity.ml-agents/Runtime/Analytics/InferenceAnalytics.cs


/// <param name="inferenceDevice">Whether inference is being performed on the CPU or GPU</param>
/// <param name="sensors">List of ISensors for the Agent. Used to generate information about the observation space.</param>
/// <param name="actionSpec">ActionSpec for the Agent. Used to generate information about the action space.</param>
/// <param name="actuators">List of IActuators for the Agent. Used to generate information about the action space.</param>
/// <returns></returns>
public static void InferenceModelSet(
NNModel nnModel,

ActionSpec actionSpec
ActionSpec actionSpec,
IList<IActuator> actuators
)
{
// The event shouldn't be able to report if this is disabled but if we know we're not going to report

return;
}
var data = GetEventForModel(nnModel, behaviorName, inferenceDevice, sensors, actionSpec);
var data = GetEventForModel(nnModel, behaviorName, inferenceDevice, sensors, actionSpec, actuators);
//Debug.Log(JsonUtility.ToJson(data, true));
// Debug.Log(JsonUtility.ToJson(data, true));
#if UNITY_EDITOR
if (AnalyticsUtils.s_SendEditorAnalytics)
{

/// <param name="inferenceDevice"></param>
/// <param name="sensors"></param>
/// <param name="actionSpec"></param>
/// <param name="actuators"></param>
/// <returns></returns>
internal static InferenceEvent GetEventForModel(
NNModel nnModel,

ActionSpec actionSpec
ActionSpec actionSpec,
IList<IActuator> actuators
)
{
var barracudaModel = ModelLoader.Load(nnModel);

foreach (var sensor in sensors)
{
inferenceEvent.ObservationSpecs.Add(EventObservationSpec.FromSensor(sensor));
}
inferenceEvent.ActuatorInfos = new List<EventActuatorInfo>(actuators.Count);
foreach (var actuator in actuators)
{
inferenceEvent.ActuatorInfos.Add(EventActuatorInfo.FromActuator(actuator));
}
inferenceEvent.TotalWeightSizeBytes = GetModelWeightSize(barracudaModel);

17
com.unity.ml-agents/Runtime/Analytics/TrainingAnalytics.cs


public static void RemotePolicyInitialized(
string fullyQualifiedBehaviorName,
IList<ISensor> sensors,
ActionSpec actionSpec
ActionSpec actionSpec,
IList<IActuator> actuators
)
{
if (!IsAnalyticsEnabled())

return;
}
var data = GetEventForRemotePolicy(behaviorName, sensors, actionSpec);
var data = GetEventForRemotePolicy(behaviorName, sensors, actionSpec, actuators);
// Note - to debug, use JsonUtility.ToJson on the event.
// Debug.Log(
// $"Would send event {k_RemotePolicyInitializedEventName} with body {JsonUtility.ToJson(data, true)}"

#endif
}
static RemotePolicyInitializedEvent GetEventForRemotePolicy(
internal static RemotePolicyInitializedEvent GetEventForRemotePolicy(
ActionSpec actionSpec)
ActionSpec actionSpec,
IList<IActuator> actuators
)
{
var remotePolicyEvent = new RemotePolicyInitializedEvent();

foreach (var sensor in sensors)
{
remotePolicyEvent.ObservationSpecs.Add(EventObservationSpec.FromSensor(sensor));
}
remotePolicyEvent.ActuatorInfos = new List<EventActuatorInfo>(actuators.Count);
foreach (var actuator in actuators)
{
remotePolicyEvent.ActuatorInfos.Add(EventActuatorInfo.FromActuator(actuator));
}
remotePolicyEvent.MLAgentsEnvsVersion = s_TrainerPackageVersion;

10
com.unity.ml-agents/Runtime/Policies/BarracudaPolicy.cs


private string m_BehaviorName;
/// <summary>
/// List of actuators, only used for analytics
/// </summary>
private IList<IActuator> m_Actuators;
/// <summary>
/// Whether or not we've tried to send analytics for this model. We only ever try to send once per policy,
/// and do additional deduplication in the analytics code.
/// </summary>

public BarracudaPolicy(
ActionSpec actionSpec,
IList<IActuator> actuators,
NNModel model,
InferenceDevice inferenceDevice,
string behaviorName

m_ModelRunner = modelRunner;
m_BehaviorName = behaviorName;
m_ActionSpec = actionSpec;
m_Actuators = actuators;
}
/// <inheritdoc />

m_BehaviorName,
m_ModelRunner.InferenceDevice,
sensors,
m_ActionSpec
m_ActionSpec,
m_Actuators
);
}
m_AgentId = info.episodeId;

6
com.unity.ml-agents/Runtime/Policies/BehaviorParameters.cs


"Either assign a model, or change to a different Behavior Type."
);
}
return new BarracudaPolicy(actionSpec, m_Model, m_InferenceDevice, m_BehaviorName);
return new BarracudaPolicy(actionSpec, actuatorManager, m_Model, m_InferenceDevice, m_BehaviorName);
return new RemotePolicy(actionSpec, FullyQualifiedBehaviorName);
return new RemotePolicy(actionSpec, actuatorManager, FullyQualifiedBehaviorName);
return new BarracudaPolicy(actionSpec, m_Model, m_InferenceDevice, m_BehaviorName);
return new BarracudaPolicy(actionSpec, actuatorManager, m_Model, m_InferenceDevice, m_BehaviorName);
}
else
{

10
com.unity.ml-agents/Runtime/Policies/RemotePolicy.cs


internal ICommunicator m_Communicator;
/// <summary>
/// List of actuators, only used for analytics
/// </summary>
private IList<IActuator> m_Actuators;
IList<IActuator> actuators,
string fullyQualifiedBehaviorName)
{
m_FullyQualifiedBehaviorName = fullyQualifiedBehaviorName;

m_Actuators = actuators;
}
/// <inheritdoc />

TrainingAnalytics.RemotePolicyInitialized(
m_FullyQualifiedBehaviorName,
sensors,
m_ActionSpec
m_ActionSpec,
m_Actuators
);
}
m_AgentId = info.episodeId;

2
com.unity.ml-agents/Runtime/Sensors/IBuiltInSensor.cs


/// Interface for sensors that are provided as part of ML-Agents.
/// User-implemented sensors don't need to use this interface.
/// </summary>
public interface IBuiltInSensor
internal interface IBuiltInSensor
{
/// <summary>
/// Return the corresponding BuiltInSensorType for the sensor.

18
com.unity.ml-agents/Tests/Editor/Analytics/InferenceAnalyticsTests.cs


using System;
using System.Collections.Generic;
using NUnit.Framework;
using Unity.MLAgents.Sensors;

{
var sensors = new List<ISensor> { sensor_21_20_3.Sensor, sensor_20_22_3.Sensor };
var behaviorName = "continuousModel";
var actionSpec = GetContinuous2vis8vec2actionActionSpec();
var vectorActuator = new VectorActuator(null, actionSpec, "test'");
var actuators = new IActuator[] { vectorActuator };
InferenceDevice.CPU, sensors, GetContinuous2vis8vec2actionActionSpec()
InferenceDevice.CPU, sensors, actionSpec,
actuators
);
// The behavior name should be hashed, not pass-through.

Assert.AreEqual(20, continuousEvent.ObservationSpecs[0].DimensionInfos[0].Size);
Assert.AreEqual("None", continuousEvent.ObservationSpecs[0].CompressionType);
Assert.AreEqual(Test3DSensor.k_BuiltInSensorType, continuousEvent.ObservationSpecs[0].BuiltInSensorType);
Assert.AreEqual((int)BuiltInActuatorType.VectorActuator, continuousEvent.ActuatorInfos[0].BuiltInActuatorType);
Assert.AreNotEqual(null, continuousEvent.ModelHash);
// Make sure nested fields get serialized

Assert.IsTrue(jsonString.Contains("NumDiscreteActions"));
Assert.IsTrue(jsonString.Contains("SensorName"));
Assert.IsTrue(jsonString.Contains("Flags"));
Assert.IsTrue(jsonString.Contains("ActuatorInfos"));
}
[Test]

using (new AnalyticsUtils.DisableAnalyticsSending())
{
var sensors = new List<ISensor> { sensor_21_20_3.Sensor, sensor_20_22_3.Sensor };
var policy = new BarracudaPolicy(GetContinuous2vis8vec2actionActionSpec(), continuousONNXModel, InferenceDevice.CPU, "testBehavior");
var policy = new BarracudaPolicy(
GetContinuous2vis8vec2actionActionSpec(),
Array.Empty<IActuator>(),
continuousONNXModel,
InferenceDevice.CPU,
"testBehavior"
);
policy.RequestDecision(new AgentInfo(), sensors);
}
Academy.Instance.Dispose();

38
com.unity.ml-agents/Tests/Editor/Analytics/TrainingAnalyticsTest.cs


using System;
using UnityEngine;
using Unity.Barracuda;
using UnityEditor;
namespace Unity.MLAgents.Tests.Analytics
{

}
[Test]
public void TestRemotePolicyEvent()
{
var behaviorName = "testBehavior";
var sensor1 = new Test3DSensor("SensorA", 21, 20, 3);
var sensor2 = new Test3DSensor("SensorB", 20, 22, 3);
var sensors = new List<ISensor> { sensor1, sensor2 };
var actionSpec = ActionSpec.MakeContinuous(2);
var vectorActuator = new VectorActuator(null, actionSpec, "test'");
var actuators = new IActuator[] { vectorActuator };
var remotePolicyEvent = TrainingAnalytics.GetEventForRemotePolicy(behaviorName, sensors, actionSpec, actuators);
// The behavior name should be hashed, not pass-through.
Assert.AreNotEqual(behaviorName, remotePolicyEvent.BehaviorName);
Assert.AreEqual(2, remotePolicyEvent.ObservationSpecs.Count);
Assert.AreEqual(3, remotePolicyEvent.ObservationSpecs[0].DimensionInfos.Length);
Assert.AreEqual(20, remotePolicyEvent.ObservationSpecs[0].DimensionInfos[0].Size);
Assert.AreEqual("None", remotePolicyEvent.ObservationSpecs[0].CompressionType);
Assert.AreEqual(Test3DSensor.k_BuiltInSensorType, remotePolicyEvent.ObservationSpecs[0].BuiltInSensorType);
Assert.AreEqual(2, remotePolicyEvent.ActionSpec.NumContinuousActions);
Assert.AreEqual(0, remotePolicyEvent.ActionSpec.NumDiscreteActions);
Assert.AreEqual(2, remotePolicyEvent.ActuatorInfos[0].NumContinuousActions);
Assert.AreEqual(0, remotePolicyEvent.ActuatorInfos[0].NumDiscreteActions);
}
[Test]
public void TestRemotePolicy()
{
if (Academy.IsInitialized)

using (new AnalyticsUtils.DisableAnalyticsSending())
{
var actionSpec = ActionSpec.MakeContinuous(3);
var policy = new RemotePolicy(actionSpec, "TestBehavior?team=42");
var policy = new RemotePolicy(actionSpec, Array.Empty<IActuator>(), "TestBehavior?team=42");
policy.RequestDecision(new AgentInfo(), new List<ISensor>());
}

49
com.unity.ml-agents/Runtime/Actuators/IBuiltInActuator.cs


namespace Unity.MLAgents.Actuators
{
/// <summary>
/// Identifiers for "built in" actuator types.
/// These are only used for analytics, and should not be used for any runtime decisions.
///
/// NOTE: Do not renumber these, since the values are used for analytics. Renaming is allowed though.
/// </summary>
public enum BuiltInActuatorType
{
/// <summary>
/// Default Sensor type if it cannot be determined.
/// </summary>
Unknown = 0,
/// <summary>
/// VectorActuator used by the Agent
/// </summary>
AgentVectorActuator = 1,
/// <summary>
/// Corresponds to <see cref="VectorActuator"/>
/// </summary>
VectorActuator = 2,
/// <summary>
/// Corresponds to the Match3Actuator in com.unity.ml-agents.extensions.
/// </summary>
Match3Actuator = 3,
/// <summary>
/// Corresponds to the InputActionActuator in com.unity.ml-agents.extensions.
/// </summary>
InputActionActuator = 4,
}
/// <summary>
/// Interface for actuators that are provided as part of ML-Agents.
/// User-implemented actuators don't need to use this interface.
/// </summary>
internal interface IBuiltInActuator
{
/// <summary>
/// Return the corresponding BuiltInActuatorType for the actuator.
/// </summary>
/// <returns>A BuiltInActuatorType corresponding to the actuator.</returns>
BuiltInActuatorType GetBuiltInActuatorType();
}
}

3
com.unity.ml-agents/Runtime/Actuators/IBuiltInActuator.cs.meta


fileFormatVersion: 2
guid: e3d7ef9a9a5043549cc5c0bbee520810
timeCreated: 1613514041
正在加载...
取消
保存