| | using System.Collections.Generic; |
| | using System.Diagnostics; |
| | using Unity.Barracuda; |
| | using Unity.MLAgents.Actuators; |
| | using Unity.MLAgents.Inference; |
| | using Unity.MLAgents.Policies; |
| | using Unity.MLAgents.Sensors; |
| | using UnityEngine; |
| |
|
| | #if MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | using UnityEngine.Analytics; |
| | #endif |
| |
|
| |
|
| | #if UNITY_EDITOR |
| | using UnityEditor; |
| | #if MLA_UNITY_ANALYTICS_MODULE |
| | using UnityEditor.Analytics; |
| | #endif // MLA_UNITY_ANALYTICS_MODULE |
| | #endif // UNITY_EDITOR |
| |
|
| |
|
| | namespace Unity.MLAgents.Analytics |
| | { |
| | internal class InferenceAnalytics |
| | { |
| | const string k_VendorKey = "unity.ml-agents"; |
| | const string k_EventName = "ml_agents_inferencemodelset"; |
| | const int k_EventVersion = 1; |
| |
|
| | |
| | |
| | |
| | static bool s_EventRegistered; |
| |
|
| | |
| | |
| | |
| | const int k_MaxEventsPerHour = 1000; |
| |
|
| | |
| | |
| | |
| | const int k_MaxNumberOfElements = 1000; |
| |
|
| |
|
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | |
| | |
| | |
| | private static HashSet<NNModel> s_SentModels; |
| | #endif |
| |
|
| | static bool EnableAnalytics() |
| | { |
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | if (s_EventRegistered) |
| | { |
| | return true; |
| | } |
| |
|
| | AnalyticsResult result = EditorAnalytics.RegisterEventWithLimit(k_EventName, k_MaxEventsPerHour, k_MaxNumberOfElements, k_VendorKey, k_EventVersion); |
| | if (result == AnalyticsResult.Ok) |
| | { |
| | s_EventRegistered = true; |
| | } |
| | if (s_EventRegistered && s_SentModels == null) |
| | { |
| | s_SentModels = new HashSet<NNModel>(); |
| | } |
| |
|
| | #else // no editor, no analytics |
| | s_EventRegistered = false; |
| | #endif |
| | return s_EventRegistered; |
| | } |
| |
|
| | public static bool IsAnalyticsEnabled() |
| | { |
| | #if UNITY_EDITOR |
| | return EditorAnalytics.enabled; |
| | #else |
| | return false; |
| | #endif |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | [Conditional("MLA_UNITY_ANALYTICS_MODULE")] |
| | public static void InferenceModelSet( |
| | NNModel nnModel, |
| | string behaviorName, |
| | InferenceDevice inferenceDevice, |
| | IList<ISensor> sensors, |
| | ActionSpec actionSpec, |
| | IList<IActuator> actuators |
| | ) |
| | { |
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | |
| | |
| | if (!IsAnalyticsEnabled()) |
| | return; |
| |
|
| | if (!EnableAnalytics()) |
| | return; |
| |
|
| | var added = s_SentModels.Add(nnModel); |
| |
|
| | if (!added) |
| | { |
| | |
| | return; |
| | } |
| |
|
| | var data = GetEventForModel(nnModel, behaviorName, inferenceDevice, sensors, actionSpec, actuators); |
| | |
| | |
| | if (AnalyticsUtils.s_SendEditorAnalytics) |
| | { |
| | EditorAnalytics.SendEventWithLimit(k_EventName, data, k_EventVersion); |
| | } |
| | #endif |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | internal static InferenceEvent GetEventForModel( |
| | NNModel nnModel, |
| | string behaviorName, |
| | InferenceDevice inferenceDevice, |
| | IList<ISensor> sensors, |
| | ActionSpec actionSpec, |
| | IList<IActuator> actuators |
| | ) |
| | { |
| | var barracudaModel = ModelLoader.Load(nnModel); |
| | var inferenceEvent = new InferenceEvent(); |
| |
|
| | |
| | inferenceEvent.BehaviorName = AnalyticsUtils.Hash(k_VendorKey, behaviorName); |
| |
|
| | inferenceEvent.BarracudaModelSource = barracudaModel.IrSource; |
| | inferenceEvent.BarracudaModelVersion = barracudaModel.IrVersion; |
| | inferenceEvent.BarracudaModelProducer = barracudaModel.ProducerName; |
| | inferenceEvent.MemorySize = (int)barracudaModel.GetTensorByName(TensorNames.MemorySize)[0]; |
| | inferenceEvent.InferenceDevice = (int)inferenceDevice; |
| |
|
| | if (barracudaModel.ProducerName == "Script") |
| | { |
| | |
| | inferenceEvent.BarracudaModelSource = "NN"; |
| | inferenceEvent.BarracudaModelProducer = "tensorflow_to_barracuda.py"; |
| | } |
| |
|
| | #if UNITY_EDITOR |
| | var barracudaPackageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssembly(typeof(Tensor).Assembly); |
| | inferenceEvent.BarracudaPackageVersion = barracudaPackageInfo.version; |
| | #else |
| | inferenceEvent.BarracudaPackageVersion = null; |
| | #endif |
| |
|
| | inferenceEvent.ActionSpec = EventActionSpec.FromActionSpec(actionSpec); |
| | inferenceEvent.ObservationSpecs = new List<EventObservationSpec>(sensors.Count); |
| | 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); |
| | inferenceEvent.ModelHash = GetModelHash(barracudaModel); |
| | return inferenceEvent; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | static long GetModelWeightSize(Model barracudaModel) |
| | { |
| | long totalWeightsSizeInBytes = 0; |
| | for (var l = 0; l < barracudaModel.layers.Count; ++l) |
| | { |
| | for (var d = 0; d < barracudaModel.layers[l].datasets.Length; ++d) |
| | { |
| | totalWeightsSizeInBytes += barracudaModel.layers[l].datasets[d].length; |
| | } |
| | } |
| | return totalWeightsSizeInBytes; |
| | } |
| |
|
| | |
| | |
| | |
| | struct MLAgentsHash128 |
| | { |
| | private Hash128 m_Hash; |
| |
|
| | public void Append(float[] values, int count) |
| | { |
| | if (values == null) |
| | { |
| | return; |
| | } |
| |
|
| | |
| | |
| | #if UNITY_2020_1_OR_NEWER |
| | m_Hash.Append(values, 0, count); |
| | #else |
| | for (var i = 0; i < count; i++) |
| | { |
| | var tempHash = new Hash128(); |
| | HashUtilities.ComputeHash128(ref values[i], ref tempHash); |
| | HashUtilities.AppendHash(ref tempHash, ref m_Hash); |
| | } |
| | #endif |
| | } |
| |
|
| | public void Append(string value) |
| | { |
| | var tempHash = Hash128.Compute(value); |
| | HashUtilities.AppendHash(ref tempHash, ref m_Hash); |
| | } |
| |
|
| | public override string ToString() |
| | { |
| | return m_Hash.ToString(); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | static string GetModelHash(Model barracudaModel) |
| | { |
| | var hash = new MLAgentsHash128(); |
| |
|
| | |
| | const int kMaxFloats = 256; |
| |
|
| | foreach (var layer in barracudaModel.layers) |
| | { |
| | hash.Append(layer.name); |
| | var numFloatsToHash = Mathf.Min(layer.weights.Length, kMaxFloats); |
| | hash.Append(layer.weights, numFloatsToHash); |
| | } |
| |
|
| | return hash.ToString(); |
| | } |
| | } |
| | } |
| |
|