Beispiel #1
0
        /// <summary>
        /// Generates failed checks that correspond to inputs shapes incompatibilities between
        /// the model and the BrainParameters.
        /// </summary>
        /// <param name="model">
        /// The Barracuda engine model for loading static parameters
        /// </param>
        /// <param name="brainParameters">
        /// The BrainParameters that are used verify the compatibility with the InferenceEngine
        /// </param>
        /// <param name="sensors">Attached sensors</param>
        /// <param name="observableAttributeTotalSize">Sum of the sizes of all ObservableAttributes.</param>
        /// <returns>A IEnumerable of the checks that failed</returns>
        static IEnumerable <FailedCheck> CheckInputTensorShape(
            Model model, BrainParameters brainParameters, ISensor[] sensors,
            int observableAttributeTotalSize)
        {
            var failedModelChecks = new List <FailedCheck>();
            var tensorTester      =
                new Dictionary <string, Func <BrainParameters, TensorProxy, ISensor[], int, FailedCheck> >()
            {
                { TensorNames.PreviousActionPlaceholder, CheckPreviousActionShape },
                { TensorNames.RandomNormalEpsilonPlaceholder, ((bp, tensor, scs, i) => null) },
                { TensorNames.ActionMaskPlaceholder, ((bp, tensor, scs, i) => null) },
                { TensorNames.SequenceLengthPlaceholder, ((bp, tensor, scs, i) => null) },
                { TensorNames.RecurrentInPlaceholder, ((bp, tensor, scs, i) => null) },
            };

            foreach (var mem in model.memories)
            {
                tensorTester[mem.input] = ((bp, tensor, scs, i) => null);
            }

            for (var sensorIndex = 0; sensorIndex < sensors.Length; sensorIndex++)
            {
                var sens = sensors[sensorIndex];
                if (sens.GetObservationSpec().Rank == 3)
                {
                    tensorTester[TensorNames.GetObservationName(sensorIndex)] =
                        (bp, tensor, scs, i) => CheckVisualObsShape(tensor, sens);
                }
                if (sens.GetObservationSpec().Rank == 2)
                {
                    tensorTester[TensorNames.GetObservationName(sensorIndex)] =
                        (bp, tensor, scs, i) => CheckRankTwoObsShape(tensor, sens);
                }
                if (sens.GetObservationSpec().Rank == 1)
                {
                    tensorTester[TensorNames.GetObservationName(sensorIndex)] =
                        (bp, tensor, scs, i) => CheckRankOneObsShape(tensor, sens);
                }
            }

            // If the model expects an input but it is not in this list
            foreach (var tensor in model.GetInputTensors())
            {
                if (!tensorTester.ContainsKey(tensor.name))
                {
                    failedModelChecks.Add(FailedCheck.Warning("Model contains an unexpected input named : " + tensor.name
                                                              ));
                }
                else
                {
                    var tester = tensorTester[tensor.name];
                    var error  = tester.Invoke(brainParameters, tensor, sensors, observableAttributeTotalSize);
                    if (error != null)
                    {
                        failedModelChecks.Add(error);
                    }
                }
            }
            return(failedModelChecks);
        }
        /// <summary>
        /// Generates failed checks that correspond to inputs expected by the model that are not
        /// present in the BrainParameters.
        /// </summary>
        /// <param name="model">
        /// The Barracuda engine model for loading static parameters
        /// </param>
        /// <param name="brainParameters">
        /// The BrainParameters that are used verify the compatibility with the InferenceEngine
        /// </param>
        /// <param name="memory">
        /// The memory size that the model is expecting.
        /// </param>
        /// <param name="sensors">Array of attached sensor components</param>
        /// <returns>
        /// A IEnumerable of the checks that failed
        /// </returns>
        static IEnumerable <FailedCheck> CheckInputTensorPresence(
            Model model,
            BrainParameters brainParameters,
            int memory,
            ISensor[] sensors
            )
        {
            var failedModelChecks = new List <FailedCheck>();
            var tensorsNames      = model.GetInputNames();

            for (var sensorIndex = 0; sensorIndex < sensors.Length; sensorIndex++)
            {
                if (!tensorsNames.Contains(
                        TensorNames.GetObservationName(sensorIndex)))
                {
                    var sensor = sensors[sensorIndex];
                    failedModelChecks.Add(
                        FailedCheck.Warning("The model does not contain an Observation Placeholder Input " +
                                            $"for sensor component {sensorIndex} ({sensor.GetType().Name}).")
                        );
                }
            }

            // If the model has a non-negative memory size but requires a recurrent input
            if (memory > 0)
            {
                var modelVersion   = model.GetVersion();
                var netHasMemories = false;
                if (modelVersion < (int)BarracudaModelParamLoader.ModelApiVersion.MLAgents2_0)
                {
                    netHasMemories = tensorsNames.Any(x => x.EndsWith("_h")) &&
                                     tensorsNames.Any(x => x.EndsWith("_c"));
                }
                else
                {
                    netHasMemories = tensorsNames.Any(x => x == TensorNames.RecurrentInPlaceholder);
                }
                if (!netHasMemories)
                {
                    failedModelChecks.Add(
                        FailedCheck.Warning("The model does not contain a Recurrent Input Node but has memory_size.")
                        );
                }
            }

            // If the model uses discrete control but does not have an input for action masks
            if (model.HasDiscreteOutputs())
            {
                if (!tensorsNames.Contains(TensorNames.ActionMaskPlaceholder))
                {
                    failedModelChecks.Add(
                        FailedCheck.Warning("The model does not contain an Action Mask but is using Discrete Control.")
                        );
                }
            }
            return(failedModelChecks);
        }
        public void InitializeObservations(List <ISensor> sensors, ITensorAllocator allocator)
        {
            // Loop through the sensors on a representative agent.
            // All vector observations use a shared ObservationGenerator since they are concatenated.
            // All other observations use a unique ObservationInputGenerator
            var visIndex = 0;
            ObservationGenerator vecObsGen = null;

            for (var sensorIndex = 0; sensorIndex < sensors.Count; sensorIndex++)
            {
                var sensor = sensors[sensorIndex];
                var shape  = sensor.GetObservationShape();
                var rank   = shape.Length;
                ObservationGenerator obsGen = null;
                string obsGenName           = null;
                switch (rank)
                {
                case 1:
                    if (vecObsGen == null)
                    {
                        vecObsGen = new ObservationGenerator(allocator);
                    }
                    obsGen     = vecObsGen;
                    obsGenName = TensorNames.VectorObservationPlaceholder;
                    break;

                case 2:
                    // If the tensor is of rank 2, we use the index of the sensor
                    // to create the name
                    obsGen     = new ObservationGenerator(allocator);
                    obsGenName = TensorNames.GetObservationName(sensorIndex);
                    break;

                case 3:
                    // If the tensor is of rank 3, we use the "visual observation
                    // index", which only counts the rank 3 sensors
                    obsGen     = new ObservationGenerator(allocator);
                    obsGenName = TensorNames.GetVisualObservationName(visIndex);
                    visIndex++;
                    break;

                default:
                    throw new UnityAgentsException(
                              $"Sensor {sensor.GetName()} have an invalid rank {rank}");
                }
                obsGen.AddSensorIndex(sensorIndex);
                m_Dict[obsGenName] = obsGen;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Generates failed checks that correspond to inputs expected by the model that are not
        /// present in the BrainParameters. Tests the models created with the API of version 1.X
        /// </summary>
        /// <param name="model">
        /// The Barracuda engine model for loading static parameters
        /// </param>
        /// <param name="brainParameters">
        /// The BrainParameters that are used verify the compatibility with the InferenceEngine
        /// </param>
        /// <param name="memory">
        /// The memory size that the model is expecting.
        /// </param>
        /// <param name="sensors">Array of attached sensor components</param>
        /// <returns>
        /// A IEnumerable of the checks that failed
        /// </returns>
        static IEnumerable <FailedCheck> CheckInputTensorPresenceLegacy(
            Model model,
            BrainParameters brainParameters,
            int memory,
            ISensor[] sensors
            )
        {
            var failedModelChecks = new List <FailedCheck>();
            var tensorsNames      = model.GetInputNames();

            // If there is no Vector Observation Input but the Brain Parameters expect one.
            if ((brainParameters.VectorObservationSize != 0) &&
                (!tensorsNames.Contains(TensorNames.VectorObservationPlaceholder)))
            {
                failedModelChecks.Add(
                    FailedCheck.Warning("The model does not contain a Vector Observation Placeholder Input. " +
                                        "You must set the Vector Observation Space Size to 0.")
                    );
            }

            // If there are not enough Visual Observation Input compared to what the
            // sensors expect.
            var visObsIndex = 0;

            for (var sensorIndex = 0; sensorIndex < sensors.Length; sensorIndex++)
            {
                var sensor = sensors[sensorIndex];
                if (sensor.GetObservationSpec().Shape.Length == 3)
                {
                    if (!tensorsNames.Contains(
                            TensorNames.GetVisualObservationName(visObsIndex)))
                    {
                        failedModelChecks.Add(
                            FailedCheck.Warning("The model does not contain a Visual Observation Placeholder Input " +
                                                $"for sensor component {visObsIndex} ({sensor.GetType().Name}).")
                            );
                    }
                    visObsIndex++;
                }
                if (sensor.GetObservationSpec().Shape.Length == 2)
                {
                    if (!tensorsNames.Contains(
                            TensorNames.GetObservationName(sensorIndex)))
                    {
                        failedModelChecks.Add(
                            FailedCheck.Warning("The model does not contain an Observation Placeholder Input " +
                                                $"for sensor component {sensorIndex} ({sensor.GetType().Name}).")
                            );
                    }
                }
            }

            var expectedVisualObs = model.GetNumVisualInputs();

            // Check if there's not enough visual sensors (too many would be handled above)
            if (expectedVisualObs > visObsIndex)
            {
                failedModelChecks.Add(
                    FailedCheck.Warning($"The model expects {expectedVisualObs} visual inputs," +
                                        $" but only found {visObsIndex} visual sensors.")
                    );
            }

            // If the model has a non-negative memory size but requires a recurrent input
            if (memory > 0)
            {
                if (!tensorsNames.Any(x => x.EndsWith("_h")) ||
                    !tensorsNames.Any(x => x.EndsWith("_c")))
                {
                    failedModelChecks.Add(
                        FailedCheck.Warning("The model does not contain a Recurrent Input Node but has memory_size.")
                        );
                }
            }

            // If the model uses discrete control but does not have an input for action masks
            if (model.HasDiscreteOutputs())
            {
                if (!tensorsNames.Contains(TensorNames.ActionMaskPlaceholder))
                {
                    failedModelChecks.Add(
                        FailedCheck.Warning("The model does not contain an Action Mask but is using Discrete Control.")
                        );
                }
            }
            return(failedModelChecks);
        }