public void ElementCountIsCachedProperly() { var dims = new TensorDimensions(3, 5, 7); Assert.Equal(3 * 5 * 7, dims.ElementCount); Assert.Equal(3 * 5 * 7, dims.ElementCount); }
/// <summary> /// Computes new TensorDimensions which have all dimensions except for the last dimension equal to the input TensorDimensions. The last dimension is computed based on the count. /// </summary> private TensorDimensions ComputeLastDimension(TensorDimensions dims, int count) { int allButLastCount = 1; for (int i = 0; i < dims.Rank - 1; i++) { allButLastCount *= dims[i]; } if (allButLastCount == 0 || count == 0) { return(new TensorDimensions(0)); } if (count % allButLastCount != 0) { MyLog.WARNING.WriteLine(Name + ": Could not set proper output dimensions!"); return(new TensorDimensions(count)); } int lastDimension = count / allButLastCount; List <int> outputDimensions = new List <int>(); for (int i = 0; i < dims.Rank - 1; i++) { outputDimensions.Add(dims[i]); } outputDimensions.Add(lastDimension); return(new TensorDimensions(outputDimensions)); }
public ColumnHintTestData(TensorDimensions initialDims, int columnHint, TensorDimensions expectedDims, string comment) { InitialDims = initialDims; ColumnHint = columnHint; ExpectedDims = expectedDims; Comment = comment; }
public void ComputesCompatibleTensorDimsWithInvalidData() { var dims = TensorDimensions.GetBackwardCompatibleDims(0, 0); Assert.Equal(1, dims.Rank); Assert.Equal(0, dims[0]); }
public void ComputesCompatibleTensorDimsWithWrongColumnHint() { var dims = TensorDimensions.GetBackwardCompatibleDims(10, 3); Assert.Equal(1, dims.Rank); Assert.Equal(10, dims[0]); }
public void ComputesCompatibleTensorDims() { var dims = TensorDimensions.GetBackwardCompatibleDims(10, 2); Assert.Equal(2, dims[0]); Assert.Equal(5, dims[1]); }
public void DefaultDimIsRankOneOfSizeZero() { TensorDimensions emptyDims = TensorDimensions.Empty; Assert.Equal(1, emptyDims.Rank); Assert.Equal(0, emptyDims[0]); Assert.Equal(0, emptyDims.ElementCount); }
public void HashCodeIsCachedProperly() { var dims = new TensorDimensions(3, 5, 7); int hashCode = dims.GetHashCode(); Assert.Equal(hashCode, dims.GetHashCode()); }
public void ApplyWithErrorMessageTheory(CustomDimensionsHint hint, TensorDimensions originalDims) { string errorMessage; var resultDims = hint.TryToApply(originalDims, out errorMessage); Assert.Equal(originalDims, resultDims); Assert.False(string.IsNullOrEmpty(errorMessage)); }
public CustomDimsTestCase(TensorDimensions dims, CustomDimensionsHint customDims, RenderingMethod method, int vectorElements, Size expectedSize) { Dims = dims; CustomDims = customDims; Method = method; VectorElements = vectorElements; ExpectedSize = expectedSize; }
public void ApplyFallbackTheory(CustomDimensionsHint hint, TensorDimensions originalDims) { TensorDimensions resultDims; bool didApply = hint.TryToApply(originalDims, out resultDims); Assert.Equal(originalDims, resultDims); Assert.False(didApply); }
// TODO(Premek): Report warnings using a logger interface. internal static Size ComputeCustomTextureSize(TensorDimensions dims, CustomDimensionsHint customDims, RenderingMethod method, int vectorElements, out string warning) { warning = ""; if (dims.IsEmpty) { return(Size.Empty); } bool isDivisible; string divisorName = (method == RenderingMethod.RGB) ? "3 (RGB channel count)" : "vector element count"; bool isRowVector = (dims.Rank == 1) || (dims.Rank == 2 && dims[1] == 1); bool isColumnVector = !isRowVector && (dims.Rank == 2) && (dims[0] == 1); TensorDimensions adjustedDims; bool didApplyCustomDims = customDims.TryToApply(dims, out adjustedDims); if (!customDims.IsEmpty && !didApplyCustomDims) { warning = "Could not apply custom dimensions (the element count must match the original)."; } if (!didApplyCustomDims && (isRowVector || isColumnVector)) { return(ComputeTextureSizeForVector(dims.ElementCount, isRowVector, method, vectorElements, divisorName, ref warning)); } int shrinkedLastDim = ShrinkSizeForRenderingMethod(adjustedDims[adjustedDims.Rank - 1], method, vectorElements, out isDivisible); if (!isDivisible || (shrinkedLastDim == 0)) { if (string.IsNullOrEmpty(warning)) { warning = string.Format("The last dimension is {0} {1}. Ignoring dimensions.", (!isDivisible) ? "not divisible by" : "smaller than", divisorName); } return(ComputeTextureSize( ShrinkSizeForRenderingMethod(dims.ElementCount, method, vectorElements, out isDivisible))); } // Squash all dimensions except the first one together. // TODO(Premek): Decide according to actual sizes of the dimensions. int squashedOtherDims = shrinkedLastDim; for (int i = 1; i < adjustedDims.Rank - 1; i++) { squashedOtherDims *= adjustedDims[i]; } return(new Size(adjustedDims[0], squashedOtherDims)); }
public void AnyDimensionCanBeZero() { var rank1Dims = new TensorDimensions(0); Assert.Equal(0, rank1Dims.ElementCount); var rankNDims = new TensorDimensions(3, 0, 5); Assert.Equal(3, rankNDims[0]); Assert.Equal(0, rankNDims.ElementCount); }
public override void UpdateMemoryBlocks() { Output.Count = OutputSize; //Output.ColumnHint = ColumnHint; Output.Dims = TensorDimensions.GetBackwardCompatibleDims(Output.Count, ColumnHint); RandomPool.Count = PatternCount * OutputSize; //RandomPool.ColumnHint = ColumnHint; RandomPool.Dims = TensorDimensions.GetBackwardCompatibleDims(RandomPool.Count, ColumnHint); Label.Count = PatternCount / PatternGroups; //Label.ColumnHint = Label.Count; Label.Dims = TensorDimensions.GetBackwardCompatibleDims(Label.Count, Label.Count); }
private void SetTextureDimensions() { string warning = ""; Size textureSize = Size.Empty; if (ObserveTensors) { TensorDimensions d = GetTileDimensions(); int i = 0; // if CustomDimensions specified, use the first two dimensions if (UseCustomDimensions) { TileWidth = d[0]; TileHeight = d[1]; } // if not, try to find suitable dimensions in a smarter way else { TileWidth = 1; TileHeight = 1; while (i < d.Rank && TileWidth <= 1) // first non-one value is width { TileWidth = d[i]; i++; } while (i < d.Rank && TileHeight <= 1) // second non-one value is width { TileHeight = d[i]; i++; } } textureSize = ComputeTiledTextureSize(d, Target); // add boundaries between tiles textureSize.Height += TilesInColumn - 1; textureSize.Width += TilesInRow - 1; } else { textureSize = ComputeCustomTextureSize(Target.Dims, m_customDimensions, Method, Elements, out warning); } if (!string.IsNullOrEmpty(warning)) { MyLog.WARNING.WriteLine("Memory block '{0}: {1}' observer: {2}", Target.Owner.Name, Target.Name, warning); } TextureWidth = textureSize.Width; TextureHeight = textureSize.Height; }
private Size ComputeTiledTextureSize(TensorDimensions dims, MyAbstractMemoryBlock target) { int effectivePixelsDisplayed; if (Method == RenderingMethod.RGB) { // check if: // memory block has 3 chanels // chanels are divisible by requested TileWidth and TileHeight // TileWidth and TileHeight are not too big if ( dims.ElementCount % 3 != 0 || dims.ElementCount / TileWidth / TileHeight % 3 != 0 || dims.ElementCount / TileWidth / TileHeight / 3 == 0) { MyLog.WARNING.WriteLine("Memory block '{0}: {1}' observer: {2}", Target.Owner.Name, Target.Name, "RGB rendering, but Memory block.count and TileWidth and TileHeight values incompatible with the RGB format!" + " Swtiching to RedGreenScale. Use correct CustomDimensions"); Method = RenderingMethod.RedGreenScale; effectivePixelsDisplayed = dims.ElementCount; } else { effectivePixelsDisplayed = (int)Math.Ceiling((decimal)((float)dims.ElementCount / (float)3)); } } else { effectivePixelsDisplayed = dims.ElementCount; } if (TileWidth * TileHeight * TilesInRow > effectivePixelsDisplayed) { TilesInRow = effectivePixelsDisplayed / (TileWidth * TileHeight); String message = " (Parsed from " + (UseCustomDimensions ? "CustomDimensions)" : "MemoryBlock.Dims)"); MyLog.WARNING.WriteLine("Memory block '{0}: {1}' observer: {2}", Target.Owner.Name, Target.Name, "TilesInRow too big, adjusting to the max. value " + TilesInRow + "\n\t\t..for TileWidth=" + TileWidth + ", TileHeight=" + TileHeight + message); } m_noBlocks = effectivePixelsDisplayed / (TileWidth * TileHeight); TilesInColumn = (int)Math.Ceiling((decimal)((float)m_noBlocks / (float)TilesInRow)); return(new Size(TileWidth * TilesInRow, TilesInColumn * TileHeight)); }
public override void UpdateMemoryBlocks() { if (ConvertToBinary) { if (m_userInput == null || m_userInput.Length != 1) { m_userInput = new float[1]; } } else { if (m_userInput == null || m_userInput.Length != OutputSize) { m_userInput = new float[OutputSize]; } } //Output.ColumnHint = ColumnHint; Output.Dims = TensorDimensions.GetBackwardCompatibleDims(Output.Count, ColumnHint); }
public void PrintsEmptyDims() { var dims = new TensorDimensions(); Assert.Equal("0", dims.Print()); }
private bool IsRankOne(TensorDimensions dimensions) { return(dimensions.Any() && dimensions.All(dim => dim == 1)); }
public override void Validate(MyValidator validator) { switch (Operation) { case MyJoinOperation.StackInputs: return; case MyJoinOperation.DistanceSquared: case MyJoinOperation.CosineDistance: case MyJoinOperation.DotProduct: validator.AssertError(InputBranches == 2, this, "Two operands are needed for distance measures"); break; case MyJoinOperation.MatMultiplication: bool is_correct = Input0ColHint == (Input1Count / Input1ColHint); // if (Input1ColHint==1) /// BrainSim. bug for Nx1 vector, column hint is one, although it should be N... // is_correct = Input0ColHint == Input1Count; validator.AssertError(is_correct, this, "# of columns in Mat1 needs to correspond to # of rows in Mat2!"); break; case MyJoinOperation.AddToIdcs: case MyJoinOperation.AddToIdcs_Normalize: validator.AssertError(InputBranches >= 3, this, "Must provide the Target vector, Source vector and the idcs as the first three inputs"); validator.AssertError(GetInputSize(1) == GetInputSize(2), this, "Dimensions of the Source vector and idcs must be the same"); validator.AssertError(GetInputSize(0) >= GetInputSize(1), this, "Target vector must be bigger than Source vector"); return; case MyJoinOperation.GatherFromIdcs: validator.AssertError(InputBranches >= 2, this, "Must provide the Target vector and the idcs as the first two inputs"); validator.AssertError(GetInputSize(0) >= GetInputSize(1), this, "Target vector must be bigger than the idcs"); return; default: validator.AssertError(InputBranches >= 2, this, "Operation needs at least two operands"); break; } TensorDimensions firstInputDimensions = null;; bool firstInputDimensionsRankOne = false; for (int i = 0; i < InputBranches; i++) { MyMemoryBlock <float> ai = GetInput(i); if (ai == null) { validator.AddError(this, string.Format("Missing input {0}.", i)); } else if (InputBranches > 2) // Two inputs are allowed to be of variable size { validator.AssertError(ai.Count == OutputSize, this, "Operand size differs from output size"); } if (firstInputDimensions == null) { firstInputDimensions = ai.Dims; firstInputDimensionsRankOne = IsRankOne(firstInputDimensions); } var bothDimensionsRankOne = firstInputDimensionsRankOne && IsRankOne(ai.Dims); if (firstInputDimensions.Rank != ai.Dims.Rank && !bothDimensionsRankOne) { validator.AddError(this, string.Format("{0}: Incompatible input ranks!", Name)); return; } } }
public override void UpdateMemoryBlocks() { TensorDimensions firstInputDimensions = new TensorDimensions(1); int totalOutputs = 0; //Output.ColumnHint = 1; for (int i = 0; i < InputBranches; i++) { MyMemoryBlock <float> ai = GetInput(i); if (ai == null) { continue; } m_offsets[i] = totalOutputs; totalOutputs += ai.Count; if (firstInputDimensions[0] == 1) { firstInputDimensions = GetInput(i).Dims; } //if (Output.ColumnHint == 1 && ai.ColumnHint > 1) //{ // Output.ColumnHint = ai.ColumnHint; //} } switch (Operation) { case MyJoinOperation.StackInputs: OutputSize = totalOutputs; Output.Dims = ComputeLastDimension(firstInputDimensions, totalOutputs); break; case MyJoinOperation.AddToIdcs_Normalize: Temp.Count = GetInputSize(1) + 1; goto default; case MyJoinOperation.GatherFromIdcs: OutputSize = GetInputSize(1); Output.Dims = ComputeLastDimension(firstInputDimensions, GetInputSize(1)); break; case MyJoinOperation.DistanceSquared: case MyJoinOperation.CosineDistance: case MyJoinOperation.DotProduct: OutputSize = 1; //Output.ColumnHint = 1; InputBlocksPointers.Count = 2; Temp.Count = GetInputSize(0); Output.Dims = new TensorDimensions(1); break; case MyJoinOperation.MatMultiplication: if (Input0ColHint == 0) { OutputSize = 0; } else { OutputSize = Input0Count / Input0ColHint * Input1ColHint; /// size of output matrix: #rows A times #cols B } Output.ColumnHint = Input1ColHint; /// # of columns in the output correspond to the # of columns in the first matrix if (firstInputDimensions.Rank > 2) { MyLog.WARNING.WriteLine(Name + ": Matrix multiplication is not defined for tensors."); } InputBlocksPointers.Count = 2; break; default: if (InputBranches > 2) { // All are validated to be of the same length OutputSize = GetInputSize(0); InputBlocksPointers.Count = InputBranches; Output.Dims = ComputeLastDimension(firstInputDimensions, GetInputSize(0)); } else // (if InputBranches == 2) { InputBlocksPointers.Count = InputBranches; int max = 0; for (int i = 0; i < 2; i++) { var input = GetInput(i); if (input != null && input.Count > max) { max = input.Count; } } OutputSize = max; Output.Dims = ComputeLastDimension(firstInputDimensions, max); } break; } TensorDimensions adjustedDims; if (!m_outputDimsHint.TryToApply(Output.Dims, out adjustedDims) && !m_outputDimsHint.IsEmpty) { MyLog.WARNING.WriteLine("Join node '{0}': Could not apply OutputDimensions.", Name); // TODO(Premek): Be specific. } Output.Dims = adjustedDims; // Adjusted or original. }
private static MyAbstractMemoryBlock GetMemBlock(TensorDimensions dims) { return(new MyMemoryBlock <float> { Dims = dims }); }
public void TranspositionTests(TensorDimensions initial, TensorDimensions expected) { Assert.True(initial.Transpose().Equals(expected)); }
private TensorDimensions[] GetOutputBranchSpec() { TensorDimensions[] branchSizes = null; bool ok = true; if (OutputBranchesSpec != null && OutputBranchesSpec != "") { string[] branchConf = OutputBranchesSpec.Split(','); if (branchConf.Length > 0) { MyLog.DEBUG.WriteLine("creating: " + branchConf.Length + " outputs"); branchSizes = new TensorDimensions[branchConf.Length]; try { for (int i = 0; i < branchConf.Length; i++) { // parsing multidimensional string[] dimConf = branchConf[i].Split('x'); if (dimConf.Length > 1) { MyLog.DEBUG.WriteLine("Multidimensional"); TensorDimensions f = null; for (int j = 0; j < dimConf.Length; j++) { int h = int.Parse(dimConf[j], CultureInfo.InvariantCulture); MyLog.INFO.WriteLine("adding: " + h); if (j == 0) { f = new TensorDimensions(new int[] { h }); } else { f = f.AddDimensions(new int[] { h }); } } MyLog.DEBUG.WriteLine("TD: " + f.Print(true)); branchSizes[i] = f; } else { MyLog.DEBUG.WriteLine("Monodimensional"); int h = int.Parse(branchConf[i], CultureInfo.InvariantCulture); MyLog.DEBUG.WriteLine("adding: " + h); branchSizes[i] = new TensorDimensions(h); } } } catch { ok = false; } } } if (!ok) { return(null); } return(branchSizes); }
public void WildcardDimensionIsCorrectlyComputed() { TensorDimensions dims = CustomDimensionsHint.Parse("2, *, 3").TryToApply(new TensorDimensions(30)); Assert.Equal(dims, new TensorDimensions(2, 5, 3)); }