private static IOps CreateOps(WorkerFactory.Type type, ITensorAllocator allocator, bool verbose) { switch (type) { case WorkerFactory.Type.ComputePrecompiled: return(new PrecompiledComputeOps(ComputeShaderSingleton.Instance.kernels, ComputeShaderSingleton.Instance.referenceKernels, allocator, verbose)); case WorkerFactory.Type.Compute: return(new ComputeOps(ComputeShaderSingleton.Instance.kernels, ComputeShaderSingleton.Instance.referenceKernels, allocator, verbose)); case WorkerFactory.Type.ComputeRef: return(new ReferenceComputeOps(ComputeShaderSingleton.Instance.referenceKernels, allocator)); case WorkerFactory.Type.CSharpBurst: return(new BurstCPUOps(allocator)); case WorkerFactory.Type.CSharp: return(new UnsafeArrayCPUOps(allocator)); default: return(new ReferenceCPUOps(allocator)); } }
/// <summary> /// Returns a new TensorAppliers object. /// </summary> /// <param name="bp"> The BrainParameters used to determine what Appliers will be /// used</param> /// <param name="seed"> The seed the Appliers will be initialized with.</param> /// <param name="allocator"> Tensor allocator</param> /// <param name="memories">Dictionary of AgentInfo.id to memory used to pass to the inference model.</param> /// <param name="barracudaModel"></param> public TensorApplier( BrainParameters bp, int seed, ITensorAllocator allocator, Dictionary <int, List <float> > memories, object barracudaModel = null) { if (bp.vectorActionSpaceType == SpaceType.Continuous) { m_Dict[TensorNames.ActionOutput] = new ContinuousActionOutputApplier(); } else { m_Dict[TensorNames.ActionOutput] = new DiscreteActionOutputApplier(bp.vectorActionSize, seed, allocator); } m_Dict[TensorNames.RecurrentOutput] = new MemoryOutputApplier(memories); if (barracudaModel != null) { var model = (Model)barracudaModel; for (var i = 0; i < model?.memories.Count; i++) { m_Dict[model.memories[i].output] = new BarracudaMemoryOutputApplier(model.memories.Count, i, memories); } } }
public DiscreteActionOutputApplier(ActionSpec actionSpec, int seed, ITensorAllocator allocator) { m_ActionSize = actionSpec.BranchSizes; m_Multinomial = new Multinomial(seed); m_Allocator = allocator; m_ActionSpec = actionSpec; }
public static void ResizeTensor(TensorProxy tensor, int batch, ITensorAllocator allocator) { if (tensor.shape[0] == batch && tensor.data != null && tensor.data.batch == batch) { return; } tensor.data?.Dispose(); tensor.shape[0] = batch; if (tensor.shape.Length == 4) { tensor.data = allocator.Alloc( new TensorShape( batch, (int)tensor.shape[1], (int)tensor.shape[2], (int)tensor.shape[3])); } else { tensor.data = allocator.Alloc( new TensorShape( batch, (int)tensor.shape[tensor.shape.Length - 1])); } }
public VisualObservationInputGenerator( int index, bool grayScale, ITensorAllocator allocator) { m_Index = index; m_GrayScale = grayScale; m_Allocator = allocator; }
/// <summary> /// Returns a new TensorAppliers object. /// </summary> /// <param name="actionSpec"> Description of the action spaces for the Agent.</param> /// <param name="seed"> The seed the Appliers will be initialized with.</param> /// <param name="allocator"> Tensor allocator</param> /// <param name="memories">Dictionary of AgentInfo.id to memory used to pass to the inference model.</param> /// <param name="barracudaModel"></param> public TensorApplier( ActionSpec actionSpec, int seed, ITensorAllocator allocator, Dictionary <int, List <float> > memories, object barracudaModel = null) { actionSpec.CheckNotHybrid(); if (actionSpec.NumContinuousActions > 0) { m_Dict[TensorNames.ActionOutput] = new ContinuousActionOutputApplier(); } else { m_Dict[TensorNames.ActionOutput] = new DiscreteActionOutputApplier(actionSpec.BranchSizes, seed, allocator); } m_Dict[TensorNames.RecurrentOutput] = new MemoryOutputApplier(memories); if (barracudaModel != null) { var model = (Model)barracudaModel; for (var i = 0; i < model?.memories.Count; i++) { m_Dict[model.memories[i].output] = new BarracudaMemoryOutputApplier(model.memories.Count, i, memories); } } }
/// <summary> /// Converts a list of Texture2D into a Tensor. /// </summary> /// <param name="tensorProxy"> /// Tensor proxy to fill with Texture data. /// </param> /// <param name="textures"> /// The list of textures to be put into the tensor. /// Note that the textures must have same width and height. /// </param> /// <param name="blackAndWhite"> /// If set to <c>true</c> the textures /// will be converted to grayscale before being stored in the tensor. /// </param> /// <param name="allocator">Tensor allocator</param> public static void TextureToTensorProxy(TensorProxy tensorProxy, List <Texture2D> textures, bool blackAndWhite, ITensorAllocator allocator) { var batchSize = textures.Count; var width = textures[0].width; var height = textures[0].height; var data = tensorProxy.Data; for (var b = 0; b < batchSize; b++) { var cc = textures[b].GetPixels32(); for (var h = height - 1; h >= 0; h--) { for (var w = 0; w < width; w++) { var currentPixel = cc[(height - h - 1) * width + w]; if (!blackAndWhite) { // For Color32, the r, g and b values are between // 0 and 255. data[b, h, w, 0] = currentPixel.r / 255.0f; data[b, h, w, 1] = currentPixel.g / 255.0f; data[b, h, w, 2] = currentPixel.b / 255.0f; } else { data[b, h, w, 0] = (currentPixel.r + currentPixel.g + currentPixel.b) / 3f / 255.0f; } } } } }
public RecurrentInputGenerator( ITensorAllocator allocator, Dictionary <int, List <float> > memories) { m_Allocator = allocator; m_Memories = memories; }
/// <summary> /// Returns a new TensorAppliers object. /// </summary> /// <param name="bp"> The BrainParameters used to determine what Appliers will be /// used</param> /// <param name="seed"> The seed the Appliers will be initialized with.</param> /// <param name="allocator"> Tensor allocator</param> /// <param name="barracudaModel"></param> public TensorApplier( BrainParameters bp, int seed, ITensorAllocator allocator, object barracudaModel = null) { m_Dict[TensorNames.ValueEstimateOutput] = new ValueEstimateApplier(); if (bp.vectorActionSpaceType == SpaceType.Continuous) { m_Dict[TensorNames.ActionOutput] = new ContinuousActionOutputApplier(); } else { m_Dict[TensorNames.ActionOutput] = new DiscreteActionOutputApplier(bp.vectorActionSize, seed, allocator); } m_Dict[TensorNames.RecurrentOutput] = new MemoryOutputApplier(); if (barracudaModel != null) { var model = (Model)barracudaModel; for (var i = 0; i < model?.memories.Length; i++) { m_Dict[model.memories[i].output] = new BarracudaMemoryOutputApplier(model.memories.Length, i); } } }
/// <summary> /// Create `BurstCPUOps` /// </summary> /// <param name="allocator">allocator</param> public BurstCPUOps(ITensorAllocator allocator = null) : base(allocator) { if (PreferBLAS == BLAS.Native && !blas.IsNative()) { PreferBLAS = BLAS.Disabled; } }
/// <summary> /// Initializes the Brain with the Model that it will use when selecting actions for /// the agents /// </summary> /// <param name="model"> The Barracuda model to load </param> /// <param name="actionSpec"> Description of the actions for the Agent.</param> /// <param name="inferenceDevice"> Inference execution device. CPU is the fastest /// option for most of ML Agents models. </param> /// <param name="seed"> The seed that will be used to initialize the RandomNormal /// and Multinomial objects used when running inference.</param> /// <exception cref="UnityAgentsException">Throws an error when the model is null /// </exception> public ModelRunner( NNModel model, ActionSpec actionSpec, InferenceDevice inferenceDevice, int seed = 0) { Model barracudaModel; m_Model = model; m_ModelName = model.name; m_InferenceDevice = inferenceDevice; m_TensorAllocator = new TensorCachingAllocator(); if (model != null) { #if BARRACUDA_VERBOSE m_Verbose = true; #endif D.logEnabled = m_Verbose; barracudaModel = ModelLoader.Load(model); WorkerFactory.Type executionDevice; switch (inferenceDevice) { case InferenceDevice.CPU: executionDevice = WorkerFactory.Type.CSharp; break; case InferenceDevice.GPU: executionDevice = WorkerFactory.Type.ComputePrecompiled; break; case InferenceDevice.Burst: executionDevice = WorkerFactory.Type.CSharpBurst; break; case InferenceDevice.Default: // fallthrough default: executionDevice = WorkerFactory.Type.CSharpBurst; break; } m_Engine = WorkerFactory.CreateWorker(executionDevice, barracudaModel, m_Verbose); } else { barracudaModel = null; m_Engine = null; } m_InferenceInputs = barracudaModel.GetInputTensors(); m_OutputNames = barracudaModel.GetOutputNames(); m_TensorGenerator = new TensorGenerator( seed, m_TensorAllocator, m_Memories, barracudaModel); m_TensorApplier = new TensorApplier( actionSpec, seed, m_TensorAllocator, m_Memories, barracudaModel); m_InputsByName = new Dictionary <string, Tensor>(); m_InferenceOutputs = new List <TensorProxy>(); }
internal static IWorker CreateWorker(WorkerFactory.Type type, Model model, string[] additionalOutputs, string[] trimOutputs, WorkerFactory.WorkerConfiguration workerConfiguration, IModelExecutionsReporter modelExecutionsReporter = null) { type = ResolveAutoType(type); var compareAgainstType = ResolveAutoType(workerConfiguration.compareAgainstType); Assert.AreNotEqual(type, WorkerFactory.Type.Auto); Assert.AreNotEqual(compareAgainstType, WorkerFactory.Type.Auto); bool compare = type != compareAgainstType; if (WorkerFactory.IsType(type, WorkerFactory.Device.GPU) && !SystemInfo.supportsComputeShaders && !Application.isEditor) { D.LogWarning("Compute shaders are not supported on current platform. Falling back to CSharpFast."); type = WorkerFactory.Type.CSharpBurst; } IVars vars; if (WorkerFactory.IsType(type, WorkerFactory.Device.GPU) || WorkerFactory.IsType(compareAgainstType, WorkerFactory.Device.GPU)) { vars = new ComputeVarsWithSharedModel(); } else { vars = new DefaultVars(); } ITensorAllocator allocator = vars.GetAllocator(); if (workerConfiguration.verbose) { D.Log($"Storage type: {vars.GetType()}. Allocator type: {allocator.GetType()}."); } IOps ops = CreateOps(type, allocator, workerConfiguration.verbose); if (compare) { ops = new CompareOps(ops, CreateOps(compareAgainstType, allocator, workerConfiguration.verbose), workerConfiguration.compareLogLevel, workerConfiguration.compareEpsilon); } if (workerConfiguration.verbose || modelExecutionsReporter != null) { ops = new VerboseOps(ops, workerConfiguration.verbose); } if (Application.isEditor || modelExecutionsReporter != null) { ops = new StatsOps(ops); } model = ValidateModel( PatchModel(model, additionalOutputs, trimOutputs)); ops.SetModelExecutionsReporter(modelExecutionsReporter); return(new GenericWorker(model, ops, vars, workerConfiguration.verbose)); }
public void InitializeVisualObservations(Agent agent, ITensorAllocator allocator) { for (var visIndex = 0; visIndex < agent.m_Sensors.Count; visIndex++) { // TODO handle non-visual sensors too - need to index better m_Dict[TensorNames.VisualObservationPlaceholderPrefix + visIndex] = new VisualObservationInputGenerator(visIndex, allocator); } }
/// <summary> /// Create an uninitialized Tensor with specified `shape` and an optional debug `name`. /// </summary> public Tensor(TensorShape shape, string name = "") { this.name = name; this.shape = shape; m_TensorOnDevice = null; m_TensorAllocator = null; m_Cache = null; m_CacheIsDirty = false; }
/// <summary> /// Initializes the Brain with the Model that it will use when selecting actions for /// the agents /// </summary> /// <param name="seed"> The seed that will be used to initialize the RandomNormal /// and Multinomial obsjects used when running inference.</param> /// <exception cref="UnityAgentsException">Throws an error when the model is null /// </exception> public void ReloadModel(int seed = 0) { if (_tensorAllocator == null) { _tensorAllocator = new TensorCachingAllocator(); } #if ENABLE_TENSORFLOW if (model != null) { _engine = new TFSharpInferenceEngine(); _engine.PrepareModel(model.bytes); } else { _engine = null; } _modelParamLoader = ModelParamLoader.GetLoaderAndCheck(_engine, brainParameters); _inferenceInputs = _modelParamLoader.GetInputTensors(); _inferenceOutputs = _modelParamLoader.GetOutputTensors(); _tensorGenerator = new TensorGenerator(brainParameters, seed, _tensorAllocator); _tensorApplier = new TensorApplier(brainParameters, seed, _tensorAllocator); #else if (model != null) { #if BARRACUDA_VERBOSE _verbose = true; #endif D.logEnabled = _verbose; // Cleanup previous instance if (_engine != null) { _engine.Dispose(); } _barracudaModel = ModelLoader.Load(model.Value); var executionDevice = inferenceDevice == InferenceDevice.GPU ? BarracudaWorkerFactory.Type.ComputePrecompiled : BarracudaWorkerFactory.Type.CSharp; _engine = BarracudaWorkerFactory.CreateWorker(executionDevice, _barracudaModel, _verbose); } else { _barracudaModel = null; _engine = null; } _modelParamLoader = BarracudaModelParamLoader.GetLoaderAndCheck(_engine, _barracudaModel, brainParameters); _inferenceInputs = _modelParamLoader.GetInputTensors(); _outputNames = _modelParamLoader.GetOutputNames(); _tensorGenerator = new TensorGenerator(brainParameters, seed, _tensorAllocator, _barracudaModel); _tensorApplier = new TensorApplier(brainParameters, seed, _tensorAllocator, _barracudaModel); #endif }
/// <summary> /// Create an uninitialized Tensor with specified `shape` and ITensorAllocator `allocator`. /// </summary> public Tensor(TensorShape shape, ITensorAllocator allocator) { this.name = ""; this.shape = shape; m_TensorOnDevice = null; m_TensorAllocator = allocator; m_Cache = null; m_CacheIsDirty = false; }
public BarracudaRecurrentInputGenerator( int memoryIndex, ITensorAllocator allocator, Dictionary <int, List <float> > memories) { m_MemoryIndex = memoryIndex; m_Allocator = allocator; m_Memories = memories; }
public static IWorker CreateWorker(WorkerFactory.Type type, Model model, string[] additionalOutputs, string[] trimOutputs, bool verbose, WorkerFactory.Type compareAgainstType, bool differenceAsError) { type = ResolveAutoType(type); compareAgainstType = ResolveAutoType(compareAgainstType); Assert.AreNotEqual(type, WorkerFactory.Type.Auto); Assert.AreNotEqual(compareAgainstType, WorkerFactory.Type.Auto); bool compare = type != compareAgainstType; if (WorkerFactory.IsType(type, WorkerFactory.Device.GPU) && !SystemInfo.supportsComputeShaders && !Application.isEditor) { D.LogWarning("Compute shaders are not supported on current platform. Falling back to CSharpFast."); type = WorkerFactory.Type.CSharp; } IVars vars; if (WorkerFactory.IsType(type, WorkerFactory.Device.GPU) || WorkerFactory.IsType(compareAgainstType, WorkerFactory.Device.GPU)) { vars = new ComputeVarsWithSharedModel(); } else { vars = new DefaultVars(); } ITensorAllocator allocator = vars.GetAllocator(); if (verbose) { D.Log($"Storage type: {vars.GetType()}. Allocator type: {allocator.GetType()}."); } IOps ops = CreateOps(type, allocator, verbose); if (compare) { ops = new CompareOps(ops, CreateOps(compareAgainstType, allocator, verbose), differenceAsError); } if (verbose) { ops = new VerboseOps(ops); } if (Application.isEditor) { ops = new StatsOps(ops); } model = ValidateModel( PatchModel(model, additionalOutputs, trimOutputs)); return(new GenericWorker(model, ops, vars, verbose)); }
/// <summary> /// Create an uninitialized Tensor of shape `s` and ITensorAllocator `a`. /// </summary> public Tensor(TensorShape s, ITensorAllocator a) { //;;UnityEngine.Debug.Log("Tensor::Tensor " + n + " " + s + " " + a); name = ""; shape = s; m_TensorOnDevice = null; m_TensorAllocator = a; m_Cache = null; m_CacheIsDirty = false; }
/// <summary> /// Create an uninitialized Tensor of shape `s`. /// </summary> public Tensor(TensorShape s, string n = "") { //;;UnityEngine.Debug.Log("Tensor::Tensor " + n + " " + s); name = n; shape = s; m_TensorOnDevice = null; m_TensorAllocator = null; m_Cache = null; m_CacheIsDirty = false; }
/// <summary> /// Create a Tensor of shape `s`, a ITensorData `d` and an optional name `n` /// </summary> public Tensor(TensorShape s, ITensorData d, string n = "") { //;;UnityEngine.Debug.Log("Tensor::Tensor " + n + " " + s + " @ " + ((d != null) ? d.GetType().Name : "null")); name = n; shape = s; m_TensorOnDevice = d; m_TensorAllocator = null; m_Cache = null; m_CacheIsDirty = false; }
/// <summary> /// Create a Tensor with specified `shape`, an array of data `srcData` and an optional debug `name`. /// `srcData` must be of size `shape.length`. /// </summary> public Tensor(TensorShape shape, float[] srcData, string name = "") { this.name = name; this.shape = shape; m_TensorOnDevice = new ArrayTensorData(shape); Assert.IsTrue(srcData.Length == length); m_TensorOnDevice.Upload(srcData, shape, 0); m_TensorAllocator = null; m_Cache = null; m_CacheIsDirty = false; }
/// <summary> /// Create a Tensor of shape `s`, an array of data `srcData` and an optional name `n` /// `srcData` should be of size `s.length`. /// </summary> public Tensor(TensorShape s, float[] srcData, string n = "") { //;;UnityEngine.Debug.Log("Tensor::Tensor " + n + " " + s + " []-> " + srcData); name = n; shape = s; m_TensorOnDevice = new ArrayTensorData(shape); m_TensorOnDevice.Upload(srcData, 0, Math.Min(length, srcData.Length)); m_TensorAllocator = null; m_Cache = null; m_CacheIsDirty = false; }
/// Called from ITensorAllocator, puts Tensor in the ready for reuse state. internal ITensorData Invalidate() { ITensorData unpinned = m_TensorOnDevice; PinToDevice(null, false); Assert.AreEqual(m_TensorOnDevice, null); m_Cache = null; m_CacheIsDirty = false; m_TensorOnDevice = null; m_TensorAllocator = null; return(unpinned); }
/// <summary> /// Returns a new TensorGenerators object. /// </summary> /// <param name="seed"> The seed the Generators will be initialized with.</param> /// <param name="allocator"> Tensor allocator.</param> /// <param name="memories">Dictionary of AgentInfo.id to memory for use in the inference model.</param> /// <param name="barracudaModel"></param> public TensorGenerator( int seed, ITensorAllocator allocator, Dictionary <int, List <float> > memories, object barracudaModel = null) { // If model is null, no inference to run and exception is thrown before reaching here. if (barracudaModel == null) { return; } var model = (Model)barracudaModel; m_ApiVersion = model.GetVersion(); // Generator for Inputs m_Dict[TensorNames.BatchSizePlaceholder] = new BatchSizeGenerator(allocator); m_Dict[TensorNames.SequenceLengthPlaceholder] = new SequenceLengthGenerator(allocator); m_Dict[TensorNames.RecurrentInPlaceholder] = new RecurrentInputGenerator(allocator, memories); if (m_ApiVersion < (int)BarracudaModelParamLoader.ModelApiVersion.MLAgents2_0) { for (var i = 0; i < model.memories.Count; i++) { m_Dict[model.memories[i].input] = new BarracudaRecurrentInputGenerator(i, allocator, memories); } } m_Dict[TensorNames.PreviousActionPlaceholder] = new PreviousActionInputGenerator(allocator); m_Dict[TensorNames.ActionMaskPlaceholder] = new ActionMaskInputGenerator(allocator); m_Dict[TensorNames.RandomNormalEpsilonPlaceholder] = new RandomNormalInputGenerator(seed, allocator); // Generators for Outputs if (model.HasContinuousOutputs()) { m_Dict[model.ContinuousOutputName()] = new BiDimensionalOutputGenerator(allocator); } if (model.HasDiscreteOutputs()) { m_Dict[model.DiscreteOutputName()] = new BiDimensionalOutputGenerator(allocator); } m_Dict[TensorNames.RecurrentOutput] = new BiDimensionalOutputGenerator(allocator); m_Dict[TensorNames.ValueEstimateOutput] = new BiDimensionalOutputGenerator(allocator); }
/// <summary> /// Create a Tensor from multiple texture, shape is [srcTextures.length, texture.height, texture.width, `channels=3`] /// All textures must be of the same size and dimension. /// </summary> public Tensor(UnityEngine.Texture[] srcTextures, int channels = 3, string n = "") { name = n; var tensorData = new TextureAsTensorData(srcTextures, channels); //;;UnityEngine.Debug.Log("Tensor::Tensor " + n + " " + tensorData.shape + " [TEX] " + srcTextures); shape = tensorData.shape; Assert.IsTrue(tensorData.GetMaxCount() >= length); m_TensorOnDevice = tensorData; m_TensorAllocator = null; m_Cache = null; m_CacheIsDirty = false; }
public LegacyDiscreteActionOutputApplier(ActionSpec actionSpec, int seed, ITensorAllocator allocator) { m_ActionSize = actionSpec.BranchSizes; m_Multinomial = new Multinomial(seed); m_ActionSpec = actionSpec; m_StartActionIndices = Utilities.CumSum(m_ActionSize); // Scratch space for computing the cumulative distribution function. // In order to reuse it, make it the size of the largest branch. var largestBranch = Mathf.Max(m_ActionSize); m_CdfBuffer = new float[largestBranch]; }
/// <summary> /// Returns a new TensorAppliers object. /// </summary> /// <param name="actionSpec"> Description of the actions for the Agent.</param> /// <param name="seed"> The seed the Appliers will be initialized with.</param> /// <param name="allocator"> Tensor allocator</param> /// <param name="memories">Dictionary of AgentInfo.id to memory used to pass to the inference model.</param> /// <param name="barracudaModel"></param> public TensorApplier( ActionSpec actionSpec, int seed, ITensorAllocator allocator, Dictionary <int, List <float> > memories, object barracudaModel = null) { // If model is null, no inference to run and exception is thrown before reaching here. if (barracudaModel == null) { return; } var model = (Model)barracudaModel; if (!model.SupportsContinuousAndDiscrete()) { actionSpec.CheckAllContinuousOrDiscrete(); } if (actionSpec.NumContinuousActions > 0) { var tensorName = model.ContinuousOutputName(); m_Dict[tensorName] = new ContinuousActionOutputApplier(actionSpec); } var modelVersion = model.GetVersion(); if (actionSpec.NumDiscreteActions > 0) { var tensorName = model.DiscreteOutputName(); if (modelVersion == (int)BarracudaModelParamLoader.ModelApiVersion.MLAgents1_0) { m_Dict[tensorName] = new LegacyDiscreteActionOutputApplier(actionSpec, seed, allocator); } if (modelVersion == (int)BarracudaModelParamLoader.ModelApiVersion.MLAgents2_0) { m_Dict[tensorName] = new DiscreteActionOutputApplier(actionSpec, seed, allocator); } } m_Dict[TensorNames.RecurrentOutput] = new MemoryOutputApplier(memories); if (modelVersion < (int)BarracudaModelParamLoader.ModelApiVersion.MLAgents2_0) { for (var i = 0; i < model?.memories.Count; i++) { m_Dict[model.memories[i].output] = new BarracudaMemoryOutputApplier(model.memories.Count, i, memories); } } }
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; } }
/// <summary> /// Returns a new TensorGenerators object. /// </summary> /// <param name="bp"> The BrainParameters used to determine what Generators will be /// used</param> /// <param name="seed"> The seed the Generators will be initialized with.</param> /// <param name="allocator"> Tensor allocator</param> /// <param name="barracudaModel"></param> public TensorGenerator( BrainParameters bp, int seed, ITensorAllocator allocator, object barracudaModel = null) { // Generator for Inputs m_Dict[TensorNames.BatchSizePlaceholder] = new BatchSizeGenerator(allocator); m_Dict[TensorNames.SequenceLengthPlaceholder] = new SequenceLengthGenerator(allocator); m_Dict[TensorNames.VectorObservationPlacholder] = new VectorObservationGenerator(allocator); m_Dict[TensorNames.RecurrentInPlaceholder] = new RecurrentInputGenerator(allocator); if (barracudaModel != null) { var model = (Model)barracudaModel; for (var i = 0; i < model?.memories.Length; i++) { m_Dict[model.memories[i].input] = new BarracudaRecurrentInputGenerator(i, allocator); } } m_Dict[TensorNames.PreviousActionPlaceholder] = new PreviousActionInputGenerator(allocator); m_Dict[TensorNames.ActionMaskPlaceholder] = new ActionMaskInputGenerator(allocator); m_Dict[TensorNames.RandomNormalEpsilonPlaceholder] = new RandomNormalInputGenerator(seed, allocator); if (bp.cameraResolutions != null) { for (var visIndex = 0; visIndex < bp.cameraResolutions.Length; visIndex++) { var index = visIndex; var bw = bp.cameraResolutions[visIndex].blackAndWhite; m_Dict[TensorNames.VisualObservationPlaceholderPrefix + visIndex] = new VisualObservationInputGenerator(index, bw, allocator); } } // Generators for Outputs m_Dict[TensorNames.ActionOutput] = new BiDimensionalOutputGenerator(allocator); m_Dict[TensorNames.RecurrentOutput] = new BiDimensionalOutputGenerator(allocator); m_Dict[TensorNames.ValueEstimateOutput] = new BiDimensionalOutputGenerator(allocator); }