public override void Concat(Volume <float> right, Volume <float> result) { var batchSize = Math.Max(this.Shape.Dimensions[3], right.Shape.Dimensions[3]); if (this.Shape.TotalLength > 1 && right.Shape.TotalLength > 1) { var left = ReShape(new Shape(1, 1, -1, batchSize)); right = right.ReShape(new Shape(1, 1, -1, batchSize)); var elementPerBatch = result.Shape.TotalLength / batchSize; var threshold = left.Shape.Dimensions[2]; for (var n = 0; n < batchSize; n++) { for (var i = 0; i < elementPerBatch; i++) { result.Set(0, 0, i, n, i < threshold ? left.Get(0, 0, i, n) : right.Get(0, 0, i - threshold, n)); } } } else if (this.Shape.TotalLength == 1 && right.Shape.TotalLength > 1) { // Left volume is actually a scalar => broadcast its value right = right.ReShape(new Shape(1, 1, -1, batchSize)); var elementPerBatch = result.Shape.TotalLength / batchSize; var threshold = 1; for (var n = 0; n < batchSize; n++) { for (var i = 0; i < elementPerBatch; i++) { result.Set(0, 0, i, n, i < threshold ? Get(0) : right.Get(0, 0, i - threshold, n)); } } } else { // Right volume is actually a scalar => broadcast its value var left = ReShape(new Shape(1, 1, -1, batchSize)); var elementPerBatch = result.Shape.TotalLength / batchSize; var threshold = left.Shape.Dimensions[2]; for (var n = 0; n < batchSize; n++) { for (var i = 0; i < elementPerBatch; i++) { result.Set(0, 0, i, n, i < threshold ? left.Get(0, 0, i, n) : right.Get(0)); } } } }
public override void Sum(Volume <float> result) { var batchsize = this.Shape.Dimensions[3]; var channel = this.Shape.Dimensions[2]; var height = this.Shape.Dimensions[1]; var width = this.Shape.Dimensions[0]; var resultWIsOne = result.Shape.Dimensions[0] == 1; var resultHIsOne = result.Shape.Dimensions[1] == 1; var resultCIsOne = result.Shape.Dimensions[2] == 1; var resultNIsOne = result.Shape.Dimensions[3] == 1; for (var n = 0; n < batchsize; n++) { for (var c = 0; c < channel; c++) { for (var h = 0; h < height; h++) { for (var w = 0; w < width; w++) { var val = Get(w, h, c, n); var resultW = resultWIsOne ? 0 : w; var resultH = resultHIsOne ? 0 : h; var resultC = resultCIsOne ? 0 : c; var resultN = resultNIsOne ? 0 : n; var current = result.Get(resultW, resultH, resultC, resultN); result.Set(resultW, resultH, resultC, resultN, current + val); } } } } }
public override void Tile(Volume <float> reps, Volume <float> result) { var batchsize = this.Shape.Dimensions[3]; var channel = this.Shape.Dimensions[2]; var height = this.Shape.Dimensions[1]; var width = this.Shape.Dimensions[0]; var outputBatchSize = result.Shape.Dimensions[3]; var outputChannel = result.Shape.Dimensions[2]; var outputHeight = result.Shape.Dimensions[1]; var outputWidth = result.Shape.Dimensions[0]; for (var n = 0; n < outputBatchSize; n++) { for (var c = 0; c < outputChannel; c++) { for (var h = 0; h < outputHeight; h++) { for (var w = 0; w < outputWidth; w++) { result.Set(w, h, c, n, Get(w % width, h % height, c % channel, n % batchsize)); } } } } }
public override void DoSum(Volume <float> result) { var batchsize = this.Shape.GetDimension(3); var channel = this.Shape.GetDimension(2); var height = this.Shape.GetDimension(1); var width = this.Shape.GetDimension(0); var resultWIsOne = result.Shape.GetDimension(0) == 1; var resultHIsOne = result.Shape.GetDimension(1) == 1; var resultCIsOne = result.Shape.GetDimension(2) == 1; var resultNIsOne = result.Shape.GetDimension(3) == 1; for (int n = 0; n < batchsize; n++) { for (int c = 0; c < channel; c++) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { var val = this.Get(w, h, c, n); var resultW = resultWIsOne ? 0 : w; var resultH = resultHIsOne ? 0 : h; var resultC = resultCIsOne ? 0 : c; var resultN = resultNIsOne ? 0 : n; var current = result.Get(resultW, resultH, resultC, resultN); result.Set(resultW, resultH, resultC, resultN, current + val); } } } } }
public override void Norm1(Volume <float> result) { var batchSize = this.Shape.Dimensions[3]; var reshape = ReShape(-1, batchSize); var n = reshape.Shape.Dimensions[0]; for (var i = 0; i < batchSize; i++) { var sum = 0.0f; for (var j = 0; j < n; j++) { var d = reshape.Get(j, i); sum += Math.Abs(d); } result.Set(new[] { i }, sum); } }
public override void DoSum(Volume <float> result) { var batchSize = this.Shape.DimensionCount > 1 ? this.Shape.GetDimension(-1) : 1; var reshape = ReShape(-1, batchSize); var n = reshape.Shape.GetDimension(0); for (var i = 0; i < batchSize; i++) { var sum = 0.0f; for (var j = 0; j < n; j++) { var d = reshape.Get(j, i); sum += d; } result.Set(new[] { i }, sum); } }
public override void Transpose(Volume <float> result) { var expectedShape = new Shape(this.Shape.Dimensions[1], this.Shape.Dimensions[0], 1, this.Shape.Dimensions[3]); if (!result.Shape.Equals(expectedShape)) { throw new ArgumentException($"Result shape should be {expectedShape}"); } for (var n = 0; n < this.Shape.Dimensions[3]; n++) { for (var j = 0; j < this.Shape.Dimensions[1]; j++) { for (var i = 0; i < this.Shape.Dimensions[0]; i++) { result.Set(j, i, 0, n, this.Get(i, j, 0, n)); } } } }
public override void DoSum(Volume <float> result) { var batchSize = this.Shape.DimensionCount > 1 ? this.Shape.GetDimension(-1) : 1; var inputReshape = ReShape(-1, batchSize); var n = inputReshape.Shape.GetDimension(0); if (batchSize > 1 && result.Shape.DimensionCount > 1 && result.Shape.GetDimension(3) == 1) { var resultReshape = result.ReShape(-1, 1); for (var j = 0; j < n; j++) { var sum = 0.0f; // Sum over batch for (var i = 0; i < batchSize; i++) { var d = inputReshape.Get(j, i); sum += d; } resultReshape.Set(j, 0, sum); } } else { for (var i = 0; i < batchSize; i++) { var sum = 0.0f; for (var j = 0; j < n; j++) { var d = inputReshape.Get(j, i); sum += d; } result.Set(new[] { i }, sum); } } }
public override void Extract(int length, int offset, Volume <float> result) { var input = ReShape(1, 1, Shape.None, Shape.Keep); if (input.Shape.TotalLength == 1) { var v = input.Get(0); this.Storage.Map(x => v, result.Storage); } else { var batchSize = this.Shape.Dimensions[3]; for (var n = 0; n < batchSize; n++) { for (var i = 0; i < length; i++) { result.Set(0, 0, i, n, input.Get(0, 0, i + offset, n)); } } } }
public override void MatMultiply(Volume <float> right, Volume <float> result) { if (this.Shape.Dimensions[2] != 1 || right.Shape.Dimensions[2] != 1) { throw new ArgumentException($"Left and right volumes should be [w, h, 1, b]. left = {this.Shape} right = {right.Shape}"); } var broadCastLeft = this.Shape.Dimensions[3] == 1; var broadCastRight = right.Shape.Dimensions[3] == 1; if (this.Shape.Dimensions[3] != right.Shape.Dimensions[3] && !(broadCastLeft || broadCastRight)) { throw new ArgumentException($"Left and right volumes should have the same batch size. left = {this.Shape.Dimensions[3]} right = {right.Shape.Dimensions[3]}"); } var expectedShape = ComputeMatMultiplyShape(this.Shape, right.Shape); if (!result.Shape.Equals(expectedShape)) { throw new ArgumentException($"Result shape should be {expectedShape} but is {result.Shape}"); } for (var n = 0; n < this.Shape.Dimensions[3]; n++) { for (var i = 0; i < expectedShape.Dimensions[0]; i++) { for (var j = 0; j < expectedShape.Dimensions[1]; j++) { var cell = 0.0f; for (var k = 0; k < this.Shape.Dimensions[0]; k++) { cell += this.Get(k, j, 0, broadCastLeft ? 0 : n) * right.Get(i, k, 0, broadCastRight ? 0 : n); } result.Set(i, j, 0, n, cell); } } } }
public override void Min(Volume <float> result) { var batchSize = this.Shape.Dimensions[3]; var reshape = ReShape(-1, batchSize); var n = reshape.Shape.Dimensions[0]; for (var i = 0; i < batchSize; i++) { var min = float.MaxValue; for (var j = 0; j < n; j++) { var d = reshape.Get(j, i); if (d < min) { min = d; } } result.Set(new[] { i }, min); } }
public override void DoMax(Volume <float> result) { var batchSize = this.Shape.DimensionCount > 1 ? this.Shape.GetDimension(-1) : 1; var reshape = ReShape(-1, batchSize); var n = reshape.Shape.GetDimension(0); for (var i = 0; i < batchSize; i++) { var max = float.MinValue; for (var j = 0; j < n; j++) { var d = reshape.Get(j, i); if (d > max) { max = d; } } result.Set(new[] { i }, max); } }