// TODO: implement negative strides static public TensorShape ApplyStridedSlice(this TensorShape shape, int[] starts, int[] ends, int[] stride) { Assert.AreEqual(starts.Length, shape.rank); Assert.AreEqual(ends.Length, shape.rank); Assert.AreEqual(stride.Length, shape.rank); int[] counts = shape.ToArray(); int[] sliced = shape.ToArray(); Assert.AreEqual(counts.Length, shape.rank); for (int i = 0; i < counts.Length; ++i) { // NOTE: begin=0, end=0, stride=1 <= full range from the existing axis // begin=0, end=X, stride=1 <= full range from the existing axis, if X==last element on this axis // begin=0, end=0, stride=0 <= new axis OR shrink axis to a single 1st element // begin=N, end=N, stride=0 <= shrink axis to a single Nth element Assert.IsTrue(starts[i] < counts[i]); if (starts[i] != ends[i]) { sliced[i] = WrapIndex(ends[i], counts[i]) - WrapIndex(starts[i], counts[i]); } else { sliced[i] = counts[i]; } if (stride[i] != 0 && stride[i] < counts[i]) { sliced[i] /= stride[i]; } else { sliced[i] = 1; } if (sliced[i] < 0) { sliced[i] = counts[i] + sliced[i]; } if (sliced[i] < 0) { sliced[i] = 0; } } return(new TensorShape(sliced)); }
static public TensorShape Reduce(this TensorShape shape, int axis) { axis = shape.Axis(axis); var newShapeArray = shape.ToArray(); newShapeArray[axis] = 1; return(new TensorShape(newShapeArray)); }
/// <summary> /// Add an input to the model /// </summary> public Model.Input Input(string name, TensorShape shape) { m_Model.inputs.Add(new Model.Input { name = name, shape = shape.ToArray() }); return(m_Model.inputs.Last()); }
static public TensorShape Gather(TensorShape[] shapes, int axis) { TensorShape X = shapes[0]; TensorShape indices = shapes[1]; int[] shape = X.ToArray(); shape[axis] = indices.length; return(new TensorShape(shape)); }
/// <summary> /// Generates a Tensor with random values drawn from a uniform distribution. /// The shape of the tensor is specified by shape /// The uniform distribution scale is specified by min and max range /// </summary> public Layer RandomUniform(string name, TensorShape shape, float min, float max, float seed) { Layer layer = new Layer(name, Layer.Type.RandomUniform); layer.alpha = (max - min); layer.beta = min; layer.pad = new int[1] { (int)seed }; layer.pool = shape.ToArray(); m_Model.layers.Add(layer); return(layer); }
/// <summary> /// Generates a Tensor with random values drawn from a normal distribution. /// The shape of the tensor is specified by scale /// The normal distribution is specified by mean and scale /// </summary> public Layer RandomNormal(string name, TensorShape shape, float mean, float scale, float seed) { Layer layer = new Layer(name, Layer.Type.RandomNormal); layer.alpha = scale; layer.beta = mean; layer.pad = new int[1] { (int)seed }; layer.pool = shape.ToArray(); m_Model.layers.Add(layer); return(layer); }
static public TensorShape Reshape(this TensorShape shape, int[] size) { Assert.AreEqual(size.Length, 4); var newShapeArray = shape.ToArray(); // From: https://github.com/onnx/onnx/blob/master/docs/Operators.md#Reshape // // At most one dimension of the new shape can be -1. // In this case, the value is inferred from the size of the tensor and the remaining dimensions. // // A dimension could also be 0, // in which case the actual dimension value is unchanged (i.e. taken from the input tensor). var multipleOf = 1; var unknownIndex = -1; for (int q = 0; q < size.Length; ++q) { if (size[q] > 0) { multipleOf *= size[q]; newShapeArray[q] = size[q]; } else if (size[q] == 0) { multipleOf *= newShapeArray[q]; } else if (unknownIndex == -1) { unknownIndex = q; } else { throw new ArgumentException("Can only specify one unknown dimension"); } } if (unknownIndex == -1) { // all dimensions are given var newShape = new TensorShape(newShapeArray); if (shape.length != newShape.length) { throw new ArgumentException("Cannot reshape array of size " + shape.length + " into shape " + newShape); } return(newShape); } var solveForIndex = shape.length / multipleOf; bool remainderLeft = shape.length % multipleOf != 0; if (remainderLeft) { throw new ArgumentException("Cannot reshape array of size " + shape.length + " into shape with multiple of " + multipleOf + " elements"); } newShapeArray[unknownIndex] = solveForIndex; return(new TensorShape(newShapeArray)); }
/// <summary> /// Apply shape to the input tensor. Number of elements in the shape must match number of elements in input tensor. /// </summary> public Layer Reshape(string name, object input, TensorShape shape) { return(Reshape(name, input, shape.ToArray())); }