/// <inheritdoc /> public INDArray Multiply(INDArray array, INumber value) { TNDArray internalArray = InternaliseArray(array); TNumber internalValue = InternaliseNumber(value); return(CreateArrayFromHandle(internalValue.Handle * internalArray.Handle)); }
private INDArray CheckNice(INDArray array, string paramName = "unspecified") { if (!Enabled) { return(array); } if (array == null) { Report($"ndarray \"{paramName}\" is null."); } else { if (array.Rank != array.Shape.Length) { Report($"ndarray \"{paramName}\" has inconsistent rank ({array.Rank}) / shape (length {array.Length}).", array); } if (CheckNaN && UnderlyingHandler.IsNaN(array)) { Report($"ndarray \"{paramName}\" contains NaN values.", array); } if (CheckInfinite && UnderlyingHandler.IsNotFinite(array)) { Report($"ndarray \"{paramName}\" contains infinite values.", array); } } return(array); }
public void TestWeightedNetworkMergerMerge() { INetworkMerger merger = new WeightedNetworkMerger(3, 8); INetwork netA = NetworkMergerTestUtils.GenerateNetwork(1); INetwork netB = NetworkMergerTestUtils.GenerateNetwork(9); merger.AddMergeEntry("layers.*.weights"); merger.Merge(netA, netB); IRegistryResolver resolverA = new RegistryResolver(netA.Registry); IRegistryResolver resolverB = new RegistryResolver(netB.Registry); INDArray weightsA = resolverA.ResolveGet <INDArray>("layers.*.weights")[0]; INDArray weightsB = resolverB.ResolveGet <INDArray>("layers.*.weights")[0]; float firstValueA = weightsA.GetValue <float>(0, 0); float firstValueB = weightsB.GetValue <float>(0, 0); // the first value will change Assert.AreEqual(6.82, System.Math.Round(firstValueA * 100) / 100); // the second net may not be changed Assert.AreEqual(9, firstValueB); merger.RemoveMergeEntry("layers.*.weights"); merger.Merge(netA, netB); weightsA = resolverA.ResolveGet <INDArray>("layers.*.weights")[0]; firstValueA = weightsA.GetValue <float>(0, 0); // may not change Assert.AreEqual(6.82, System.Math.Round(firstValueA * 100) / 100); }
protected Dictionary <string, INDArray> GetOwnSlice(IDictionary <string, INDArray> block) { Dictionary <string, INDArray> slicedBlock = new Dictionary <string, INDArray>(); foreach (string section in block.Keys) { INDArray sectionBlock = block[section]; long[] beginIndex = new long[sectionBlock.Rank]; long[] endIndex = new long[sectionBlock.Rank]; long beginRecordIndex = (long)(sectionBlock.Shape[0] * ShareOffset); long endRecordIndex = (long)Math.Ceiling(sectionBlock.Shape[0] * (ShareOffset + Share)); //slice is empty, return null to indicate as specified if (beginRecordIndex == endRecordIndex) { return(null); } beginIndex[0] = beginRecordIndex; endIndex[0] = endRecordIndex; for (int i = 1; i < sectionBlock.Rank; i++) { endIndex[i] = sectionBlock.Shape[i]; } slicedBlock.Add(section, sectionBlock.Slice(beginIndex, endIndex)); } return(slicedBlock); }
/// <inheritdoc /> public override void Fill(INDArray filler, INDArray arrayToFill, long[] sourceBeginIndices, long[] sourceEndIndices, long[] destinationBeginIndices, long[] destinationEndIndices) { IDataBuffer <float> fillerData = InternaliseArray(filler).Data; IDataBuffer <float> arrayToFillData = InternaliseArray(arrayToFill).Data; int sourceOffset = (int)NDArrayUtils.GetFlatIndex(filler.Shape, filler.Strides, sourceBeginIndices); int sourceLength = (int)NDArrayUtils.GetFlatIndex(filler.Shape, filler.Strides, sourceEndIndices) - sourceOffset + 1; // +1 because end is inclusive int destinationOffset = (int)NDArrayUtils.GetFlatIndex(arrayToFill.Shape, arrayToFill.Strides, destinationBeginIndices); int destinationLength = (int)NDArrayUtils.GetFlatIndex(arrayToFill.Shape, arrayToFill.Strides, destinationEndIndices) - destinationOffset + 1; // same here if (sourceLength < 0) { throw new ArgumentOutOfRangeException($"Source begin indices must be smaller than source end indices, but source length was {sourceLength}."); } if (destinationLength < 0) { throw new ArgumentOutOfRangeException($"Destination begin indices must be smaller than destination end indices, but destination length was {destinationLength}."); } if (sourceLength != destinationLength) { throw new ArgumentException($"Source and destination indices length must batch, but source length was {sourceLength} and destination legnth was {destinationLength}."); } Array.Copy(fillerData.Data, sourceOffset, arrayToFillData.Data, destinationOffset, sourceLength); }
/// <summary> /// Score an intermediate result (part of the entire validation dataset was used as specified by the validation iterator). /// </summary> /// <param name="predictions">The predictions.</param> /// <param name="targets">The targets.</param> /// <param name="handler">The computation handler.</param> protected override void ScoreIntermediate(INDArray predictions, INDArray targets, IComputationHandler handler) { predictions = handler.FlattenTimeAndFeatures(predictions); targets = handler.FlattenTimeAndFeatures(targets); if (predictions.Shape[1] != 1) { throw new InvalidOperationException($"Cannot score uni-class classification accuracy on targets with != 1 feature shape (feature shape length was {predictions.Shape[1]})."); } int totalClassifications = ParameterRegistry.Get <int>("total_classifications"); int correctClassifications = ParameterRegistry.Get <int>("correct_classifications"); double lowerThreshold = ParameterRegistry.Get <double>("lower_threshold"); double upperThreshold = ParameterRegistry.Get <double>("upper_threshold"); for (int i = 0; i < predictions.Shape[0]; i++) { double value = predictions.GetValue <double>(i, 0); int target = targets.GetValue <int>(i, 0); if (value < lowerThreshold && target == 0 || value > upperThreshold && target == 1) { correctClassifications++; } } totalClassifications += (int)predictions.Shape[0]; ParameterRegistry["total_classifications"] = totalClassifications; ParameterRegistry["correct_classifications"] = correctClassifications; }
/// <summary> /// Process a certain ndarray with a certain computation handler. /// </summary> /// <param name="array">The ndarray to process.</param> /// <param name="handler">The computation handler to do the processing with.</param> /// <returns>An ndarray with the processed contents of the given array (can be the same or a new one).</returns> internal override INDArray ProcessDirect(INDArray array, IComputationHandler handler) { int recordLength = (int)(array.Length / array.Shape[0]); long[] firstBufferIndices = new long[array.Shape.Length]; long[] secondBufferIndices = new long[array.Shape.Length]; _random = new Random(31415926); // fixed rng for reproducability for (int i = 0; i < array.Shape[0]; i++) { int swapIndex = _random.Next((int)array.Shape[0]); for (int y = 0; y < recordLength; y++) { NDArrayUtils.GetIndices(recordLength * i + y, array.Shape, array.Strides, firstBufferIndices); NDArrayUtils.GetIndices(recordLength * swapIndex + y, array.Shape, array.Strides, secondBufferIndices); double firstValue = array.GetValue <double>(firstBufferIndices); double secondValue = array.GetValue <double>(secondBufferIndices); array.SetValue(secondValue, firstBufferIndices); array.SetValue(firstValue, secondBufferIndices); } } return(array); }
protected virtual INDArray GeneratePossibleMoves(INDArray values) { List <int[]> possibleMoves = new List <int[]>(); int[] valuesInts = values.GetDataAs <int>().Data; for (int i = 0; i < values.Length; i++) { if (valuesInts[i] == 0) { int[] valuesIntsClone = (int[])valuesInts.Clone(); valuesIntsClone[i] = 1; possibleMoves.Add(valuesIntsClone); _moveOrder.Add(i); } } if (possibleMoves.Count > 0) { int[] moves = possibleMoves.Aggregate(ArrayUtils.Concatenate); return(Handler.NDArray(moves, possibleMoves.Count, 1, 9)); } return(null); }
/// <summary> /// This method accepts a network pass and processes. /// </summary> /// <param name="array">The array that is the response from the pass.</param> public void ReceivePass(INDArray array) { array = Handler.FlattenTimeAndFeatures(array); array = Handler.RowWise(array, Handler.SoftMax); float[][] elements = Handler.RowWiseTransform(array, subarray => subarray.GetDataAs <float>().Data); int maxIndex = 0; float maxScore = float.NegativeInfinity; for (int i = 0; i < elements.Length; i++) { float[] currentMove = elements[i]; float score = currentMove[1] + currentMove[2] * 2; if (score > maxScore) { maxIndex = i; } } if (maxIndex < _moveOrder.Count) { int maxPosInGrid = _moveOrder[maxIndex]; _moveOrder.Clear(); Content.Dispatcher.Invoke(() => Content.SetIndex(maxPosInGrid / 3, maxPosInGrid % 3, Content.AiTicTacToePlayer)); } }
/// <inheritdoc /> public INDArray Pow(INDArray array, INumber value) { TNDArray internalArray = InternaliseArray(array); TNumber internalValue = InternaliseNumber(value); return(CreateArrayFromHandle(DNDArray.Pow(internalArray.Handle, internalValue.Handle))); }
/// <inheritdoc /> public INDArray Pow <TOther>(INDArray array, TOther value) { TNDArray internalArray = InternaliseArray(array); float internalValue = (float)System.Convert.ChangeType(value, typeof(float)); return(CreateArrayFromHandle(DNDArray.Pow(internalArray.Handle, internalValue))); }
/// <inheritdoc /> public INDArray Divide(INDArray a, INDArray b) { TNDArray internalA = InternaliseArray(a); TNDArray internalB = InternaliseArray(b); return(CreateArrayFromHandle(DNDArray.op_DotDivide(internalA.Handle, internalB.Handle))); }
/// <inheritdoc /> public INDArray Divide <TOther>(TOther value, INDArray array) { TNDArray internalArray = InternaliseArray(array); float internalValue = (float)System.Convert.ChangeType(value, typeof(float)); return(CreateArrayFromHandle(internalValue / internalArray.Handle)); }
/// <inheritdoc /> public INDArray Dot(INDArray a, INDArray b) { TNDArray internalA = InternaliseArray(a); TNDArray internalB = InternaliseArray(b); return(CreateArrayFromHandle(internalA.Handle * internalB.Handle)); }
/// <summary> /// Invoke this hook with a certain parameter registry if optional conditional criteria are satisfied. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { IValueModifier modifier = ParameterRegistry.Get <IValueModifier>("modifier"); string identifier = ParameterRegistry.Get <string>("parameter_identifier"); object parameter = resolver.ResolveGetSingle <object>(identifier); INumber asNumber = parameter as INumber; INDArray asArray = parameter as INDArray; if (asNumber != null) { parameter = modifier.Modify(identifier, asNumber, asNumber.AssociatedHandler); } else if (asArray != null) { parameter = modifier.Modify(identifier, asArray, asArray.AssociatedHandler); } else { throw new InvalidOperationException($"Cannot apply modifier {modifier} to parameter \"{identifier}\" with value {parameter}, " + $"parameter is neither {nameof(INumber)} nor {nameof(INDArray)}."); } resolver.ResolveSet(identifier, parameter); }
public void TestAverageNetworkMergerMerge() { INetworkMerger merger = new AverageNetworkMerger(); INetwork netA = NetworkMergerTestUtils.GenerateNetwork(1); INetwork netB = NetworkMergerTestUtils.GenerateNetwork(5); merger.AddMergeEntry("layers.*.weights"); merger.Merge(netA, netB); IRegistryResolver resolverA = new RegistryResolver(netA.Registry); IRegistryResolver resolverB = new RegistryResolver(netB.Registry); INDArray weightsA = resolverA.ResolveGet <INDArray>("layers.*.weights")[0]; INDArray weightsB = resolverB.ResolveGet <INDArray>("layers.*.weights")[0]; float firstValueA = weightsA.GetValue <float>(0, 0); float firstValueB = weightsB.GetValue <float>(0, 0); // the first value will change Assert.AreEqual(3, firstValueA); // the second net may not be changed Assert.AreEqual(5, firstValueB); merger.RemoveMergeEntry("layers.*.weights"); merger.Merge(netA, netB); weightsA = resolverA.ResolveGet <INDArray>("layers.*.weights")[0]; firstValueA = weightsA.GetValue <float>(0, 0); Assert.AreEqual(3, firstValueA); }
/// <summary> /// Make a data block out of a number of (name, ndarray) pairs. /// </summary> /// <param name="blockData">The block data in the form of (name, ndarray) [(name, ndarray)] ...</param> /// <returns>The block resulting from the given block data.</returns> public static IDictionary <string, INDArray> MakeBlock(params object[] blockData) { if (blockData.Length % 2 != 0) { throw new ArgumentException($"Block data must be in pairs of 2 (name, ndarray) but length was {blockData.Length}."); } IDictionary <string, INDArray> block = new Dictionary <string, INDArray>(); for (int i = 0; i < blockData.Length; i += 2) { string name = blockData[i] as string; INDArray array = blockData[i + 1] as INDArray; if (name == null) { throw new ArgumentException($"Name must be of type string and non-null, but name at index {i} was {blockData[i]}"); } if (array == null) { throw new ArgumentException($"Array must be of type INDArray and non-null, but array at index {i + 1} was {blockData[i + 1]}"); } if (block.ContainsKey(name)) { throw new ArgumentException($"Duplicate name at index {i}: {name} already exists in this block."); } block.Add(name, array); } return(block); }
/// <inheritdoc /> public override Dictionary <string, INDArray> ExtractDirectFrom(object readData, int numberOfRecords, IComputationHandler handler) { Dictionary <string, INDArray> unprocessedNamedArrays = (Dictionary <string, INDArray>)readData; Dictionary <string, INDArray> processedNamedArrays = new Dictionary <string, INDArray>(); foreach (string sectionName in unprocessedNamedArrays.Keys) { INDArray processedArray = unprocessedNamedArrays[sectionName]; if (processedArray.Shape[0] != numberOfRecords) { long[] beginIndices = (long[])processedArray.Shape.Clone(); long[] endIndices = (long[])processedArray.Shape.Clone(); beginIndices = NDArrayUtils.GetSliceIndicesAlongDimension(0, 0, beginIndices, copyResultShape: false, sliceEndIndex: false); endIndices = NDArrayUtils.GetSliceIndicesAlongDimension(0, Math.Min(numberOfRecords, processedArray.Shape[0]), endIndices, copyResultShape: false, sliceEndIndex: true); processedArray = processedArray.Slice(beginIndices, endIndices); } if (ProcessedSectionNames == null || ProcessedSectionNames.Contains(sectionName)) { processedArray = ProcessDirect(processedArray, handler); } processedNamedArrays.Add(sectionName, processedArray); } return(processedNamedArrays); }
/// <inheritdoc /> internal override INDArray Optimise(string paramIdentifier, INDArray parameter, INDArray gradient, IComputationHandler handler) { // implementation according to the reference algorithm 1 in the published paper "ADADELTA: AN ADAPTIVE LEARNING RATE METHOD" double decayRate = Registry.Get <double>("decay_rate"), smoothing = Registry.Get <double>("smoothing"); string memoryIdentifierUpdate = paramIdentifier + "_update", memoryIdentifierGradient = paramIdentifier + "_gradient"; // get accumulated gradients / update if memorised, otherwise initialise empty (all zeroes) INDArray previousAccumulatedGradient = GetMemory(memoryIdentifierGradient, () => handler.NDArray((long[])gradient.Shape.Clone())); INDArray previousAccumulatedUpdate = GetMemory(memoryIdentifierUpdate, () => handler.NDArray((long[])gradient.Shape.Clone())); // compute accumulated decayed gradients INDArray currentGradientDecayed = handler.Multiply(handler.Multiply(gradient, gradient), 1.0 - decayRate); INDArray currentAccumulatedGradient = handler.Add(handler.Multiply(previousAccumulatedGradient, decayRate), currentGradientDecayed); // compute previous accumulated gradient root mean squared (rms) and previous accumulated update rms INDArray previousUpdateRms = SquareRootSmoothed(previousAccumulatedUpdate, smoothing, handler); INDArray gradientRms = SquareRootSmoothed(currentAccumulatedGradient, smoothing, handler); // compute parameter update using previous accumulated gradient / update rms INDArray update = handler.Multiply(handler.Multiply(handler.Divide(previousUpdateRms, gradientRms), gradient), -1.0); // compute current accumulated squared decayed updates for next iteration INDArray squaredUpdateDecayed = handler.Multiply(handler.Multiply(update, update), 1.0 - decayRate); INDArray currentAccumulatedUpdate = handler.Add(handler.Multiply(previousAccumulatedUpdate, decayRate), squaredUpdateDecayed); // store accumulated values for next iteration SetProtectedMemory(memoryIdentifierGradient, currentAccumulatedGradient, handler); SetProtectedMemory(memoryIdentifierUpdate, currentAccumulatedUpdate, handler); ExposeParameterUpdate(paramIdentifier, update); // compute optimised parameter using computed update return(handler.Add(parameter, update)); }
protected override INDArray MergeNDArrays(INDArray[] arrays, IComputationHandler handler) { IComputationHandler newHandler = null; if (handler == null) { foreach (INDArray ndArray in arrays) { if (ndArray.AssociatedHandler != null) { newHandler = ndArray.AssociatedHandler; } } } else { newHandler = handler; } if (newHandler == null) { throw new ArgumentNullException(nameof(handler)); } INDArray sum = newHandler.Multiply(arrays[0], Weights[0]); for (int i = 1; i < arrays.Length; i++) { sum = newHandler.Add(sum, newHandler.Multiply(arrays[i], Weights[i])); } return(newHandler.Divide(sum, _sum)); }
/// <summary> /// Run this layer. Take relevant input values from inputs and put relevant output values in outputs registry. Each input and each output registry represents one connected layer. /// </summary> /// <param name="buffer">The buffer containing the inputs, parameters and outputs respective to this layer.</param> /// <param name="handler">The computation handler to use for computations (duh).</param> /// <param name="trainingPass">Indicate whether this is run is part of a training pass.</param> public override void Run(ILayerBuffer buffer, IComputationHandler handler, bool trainingPass) { INDArray inputs = buffer.Inputs["default"].Get <INDArray>("activations"); INDArray weights = buffer.Parameters.Get <INDArray>("weights"); string activation = buffer.Parameters.Get <string>("activation"); long batches = inputs.Shape[0]; int inputSize = Parameters.Get <int>("default_input_size"), size = Parameters.Get <int>("size"); INDArray biases = handler.StackRows((int)batches, buffer.Parameters.Get <INDArray>("biases")); INDArray activations = handler.PermuteBatchAndTime(inputs); // BatchTimeFeatures ordering by default, needs to be TimeBatchFeatures for layers operating on the time dimension activations = activations.Reshape(activations.Shape[0], activations.Shape[1] * ArrayUtils.Product(2, activations.Shape)); activations = handler.RowWise(activations, timeSlice => { timeSlice = timeSlice.Reshape(inputs.Shape[0], inputSize); timeSlice = handler.Dot(timeSlice, weights); timeSlice = handler.Add(timeSlice, biases); timeSlice = handler.Activation(activation, timeSlice); return(timeSlice.Reshape(1L, batches * size)); }); activations = activations.Reshape(activations.Shape[0], batches, size); buffer.Outputs["default"]["activations"] = handler.PermuteBatchAndTime(activations); // TODO are those the right dimensions? they should be... }
public TicTacToeField(IComputationHandler handler, WPFMonitor monitor) { _monitor = monitor; InitializeComponent(); _buttons = new TicTacToeButton[3, 3]; Field = handler.NDArray(_buttons.GetLength(0) * _buttons.GetLength(1)); for (int i = 0; i < _buttons.GetLength(0); i++) { for (int j = 0; j < _buttons.GetLength(1); j++) { int row = i; int column = j; TicTacToeButton button = new TicTacToeButton(); button.Click += (sender, args) => ButtonClick(row, column); _buttons[i, j] = button; ContentGrid.Children.Add(button); Grid.SetRow(button, row); Grid.SetColumn(button, column); } } InitGame(); }
/// <inheritdoc /> public override void Fill(INDArray filler, INDArray arrayToFill) { IDataBuffer <float> arrayToFillData = InternaliseArray(arrayToFill).Data; IDataBuffer <float> fillerData = InternaliseArray(filler).Data; arrayToFillData.SetValues(fillerData.Data, fillerData.Offset, 0, Math.Min(arrayToFill.Length, filler.Length)); }
protected override INumber CalculateCost(INDArray predictions, INDArray targets, IRegistry parameters, IComputationHandler handler) { INDArray difference = handler.Subtract(predictions, targets); INumber cost = handler.Sum(handler.Pow(difference, 2)); return(cost); }
/// <inheritdoc /> public override INumber AsNumber(INDArray array, params long[] indices) { ADFloat32NDArray internalArray = InternaliseArray(array); long flatIndex = NDArrayUtils.GetFlatIndex(array.Shape, array.Strides, indices); return(new ADFloat32Number(DNDArray.ToDNumber(internalArray.Handle, (int)flatIndex))); }
/// <inheritdoc /> internal override INDArray ProcessDirect(INDArray array, IComputationHandler handler) { //BTF with single feature dimension, TODO couldn't feature dimension just be flattened and ignored? if (array.Rank != 3) { throw new ArgumentException($"Cannot one-hot encode ndarrays which are not of rank 3 (BTF with single feature dimension), but given ndarray was of rank {array.Rank}."); } INDArray encodedArray = handler.NDArray(array.Shape[0], array.Shape[1], array.Shape[2] * _valueToIndexMapping.Count); long[] bufferIndices = new long[3]; for (long i = 0; i < array.Shape[0] * array.Shape[1]; i++) { bufferIndices = NDArrayUtils.GetIndices(i, array.Shape, array.Strides, bufferIndices); object value = array.GetValue <int>(bufferIndices); if (!_valueToIndexMapping.ContainsKey(value)) { throw new ArgumentException($"Cannot one-hot encode unknown value {value}, value was not registered as a possible value."); } bufferIndices[2] = _valueToIndexMapping[value]; encodedArray.SetValue(1, bufferIndices); } return(encodedArray); }
private void RegisterActiveBlock(Dictionary <string, INDArray> block, int blockIndex, IComputationHandler handler) { INDArray firstNamedBlock = block[block.First().Key]; if (IsBlockActive(blockIndex, handler)) { //block already registered as active, nothing to do here return; } RecordBlock recordBlock = new RecordBlock(block, blockIndex, firstNamedBlock.Shape[0], handler.GetSizeBytes(block.Values.ToArray()), handler) { Loaded = true, Active = true }; lock (_activeBlocks) { TotalActiveBlockSizeBytes += recordBlock.EstimatedSizeBytes; TotalActiveRecords += recordBlock.NumberRecords; if (!_activeBlocks.ContainsKey(blockIndex)) { _activeBlocks.Add(blockIndex, new HashSet <RecordBlock>()); } _activeBlocks[blockIndex].Add(recordBlock); } }
/// <summary> /// Score an intermediate result (part of the entire validation dataset was used as specified by the validation iterator). /// </summary> /// <param name="predictions">The predictions.</param> /// <param name="targets">The targets.</param> /// <param name="handler">The computation handler.</param> protected override void ScoreIntermediate(INDArray predictions, INDArray targets, IComputationHandler handler) { predictions = handler.FlattenTimeAndFeatures(predictions); if (predictions.Shape[1] <= 1) { throw new InvalidOperationException($"Cannot score multi-class classification accuracy on targets with less than 2 feature indices (there were {predictions.Shape[1]}."); } int[] tops = ParameterRegistry.Get <int[]>("tops"); predictions = handler.RowWise(predictions, handler.SoftMax); var perRowTopPredictions = handler.RowWiseTransform(predictions, row => row.GetDataAs <double>().Data.Select((x, i) => new KeyValuePair <double, int>(x, i)).OrderByDescending(x => x.Key).Select(p => p.Value).ToArray()).ToList(); int[] targetIndices = handler.RowWiseTransform(handler.FlattenTimeAndFeatures(targets), handler.MaxIndex); foreach (int top in tops) { int correctClassifications = perRowTopPredictions.Where((rowPredictions, rowIndex) => rowPredictions.Take(top).Any(predicted => predicted == targetIndices[rowIndex])).Count(); ParameterRegistry[$"correct_classifications_top{top}"] = ParameterRegistry.Get <int>($"correct_classifications_top{top}") + correctClassifications; } ParameterRegistry["total_classifications"] = ParameterRegistry.Get <int>("total_classifications") + targetIndices.Length; }
/// <summary> /// Create a hook with a certain time step and a set of required global registry entries. /// </summary> /// <param name="timestep">The time step.</param> /// <param name="desiredTargets">The targets for which the inputs should be optimised for.</param> /// <param name="desiredCost">The maximum factor of difference between approached targets and desired targets (squared difference).</param> /// <param name="sharedResultInputKey">The shared key under which the result input will be available.</param> /// <param name="sharedResultSuccessKey">The shared key under which the result success flag will be available.</param> public TargetMaximisationHook(ITimeStep timestep, INDArray desiredTargets, string sharedResultSuccessKey, string sharedResultInputKey, double desiredCost = 0.06) : base(timestep, "network.self", "optimiser.self") { if (desiredTargets == null) { throw new ArgumentNullException(nameof(desiredTargets)); } if (sharedResultInputKey == null) { throw new ArgumentNullException(nameof(sharedResultInputKey)); } if (sharedResultSuccessKey == null) { throw new ArgumentNullException(nameof(sharedResultSuccessKey)); } ParameterRegistry["desired_targets"] = desiredTargets; ParameterRegistry["desired_cost"] = desiredCost; ParameterRegistry["max_optimisation_steps"] = 1024; ParameterRegistry["max_optimisation_attempts"] = 2; ParameterRegistry["shared_result_input_key"] = sharedResultInputKey; ParameterRegistry["shared_result_success_key"] = sharedResultSuccessKey; InvokePriority = 10000; }
/// <inheritdoc /> public INDArray Subtract(INumber value, INDArray array) { TNDArray internalArray = InternaliseArray(array); TNumber internalValue = InternaliseNumber(value); return(CreateArrayFromHandle(internalValue.Handle - internalArray.Handle)); }