Esempio n. 1
0
            public Mapper(IHostEnvironment env, TensorFlowTransform parent, ISchema inputSchema)
            {
                Contracts.CheckValue(env, nameof(env));
                _host = env.Register(nameof(Mapper));
                _host.CheckValue(inputSchema, nameof(inputSchema));
                _host.CheckValue(parent, nameof(parent));
                _parent               = parent;
                _schema               = inputSchema;
                _inputColIndices      = new int[_parent.Inputs.Length];
                _isInputVector        = new bool[_parent.Inputs.Length];
                _fullySpecifiedShapes = new TFShape[_parent.Inputs.Length];
                for (int i = 0; i < _parent.Inputs.Length; i++)
                {
                    if (!inputSchema.TryGetColumnIndex(_parent.Inputs[i], out _inputColIndices[i]))
                    {
                        throw _host.Except($"Column {_parent.Inputs[i]} doesn't exist");
                    }

                    var type = inputSchema.GetColumnType(_inputColIndices[i]);
                    _isInputVector[i] = type.IsVector;
                    var expectedType = TensorFlowUtils.Tf2MlNetType(_parent.TFInputTypes[i]);
                    if (type.ItemType != expectedType)
                    {
                        throw _host.ExceptSchemaMismatch(nameof(inputSchema), "input", _parent.Inputs[i], expectedType.ToString(), type.ToString());
                    }
                    var originalShape = _parent.TFInputShapes[i];
                    var shape         = originalShape.ToIntArray();

                    var colTypeDims = Enumerable.Range(0, type.AsVector.DimCount + 1).Select(d => d == 0 ? 1 : (long)type.AsVector.GetDim(d - 1)).ToArray();
                    if (shape == null)
                    {
                        _fullySpecifiedShapes[i] = new TFShape(colTypeDims);
                    }
                    else if (type.AsVector.DimCount == 1)
                    {
                        // If the column is one dimension we make sure that the total size of the TF shape matches.
                        // Compute the total size of the known dimensions of the shape.
                        int valCount = shape.Where(x => x > 0).Aggregate((x, y) => x * y);
                        // The column length should be divisible by this, so that the other dimensions can be integral.
                        if (type.ValueCount % valCount != 0)
                        {
                            throw Contracts.Except($"Input shape mismatch: Input '{_parent.Inputs[i]}' has shape {originalShape.ToString()}, but input data is of length {type.ValueCount}.");
                        }

                        // If the shape is multi-dimensional, we should be able to create the length of the vector by plugging
                        // in a single value for the unknown shapes. E.g., if the shape is [?,?,3], then there should exist a value
                        // d such that d*d*3 is equal to the length of the input column.
                        var d = originalShape.NumDimensions > 2 ? Math.Pow(type.ValueCount / valCount, 1.0 / (originalShape.NumDimensions - 2)) : 1;
                        if (originalShape.NumDimensions > 2 && d - (int)d != 0)
                        {
                            throw Contracts.Except($"Input shape mismatch: Input '{_parent.Inputs[i]}' has shape {originalShape.ToString()}, but input data is of length {type.ValueCount}.");
                        }

                        // Fill in the unknown dimensions.
                        var l = new long[originalShape.NumDimensions];
                        for (int ishape = 0; ishape < originalShape.NumDimensions; ishape++)
                        {
                            l[ishape] = originalShape[ishape] == -1 ? (int)d : originalShape[ishape];
                        }
                        _fullySpecifiedShapes[i] = new TFShape(l);
                    }
                    else
                    {
                        if (shape.Select((dim, j) => dim != -1 && dim != colTypeDims[j]).Any(b => b))
                        {
                            throw Contracts.Except($"Input shape mismatch: Input '{_parent.Inputs[i]}' has shape {originalShape.ToString()}, but input data is {type.AsVector.ToString()}.");
                        }

                        // Fill in the unknown dimensions.
                        var l = new long[originalShape.NumDimensions];
                        for (int ishape = 0; ishape < originalShape.NumDimensions; ishape++)
                        {
                            l[ishape] = originalShape[ishape] == -1 ? colTypeDims[ishape] : originalShape[ishape];
                        }
                        _fullySpecifiedShapes[i] = new TFShape(l);
                    }
                }
            }
Esempio n. 2
0
 private ITensorValueGetter CreateTensorValueGetter <T>(IRow input, bool isVector, int colIndex, TFShape tfShape)
 {
     if (isVector)
     {
         return(new TensorValueGetterVec <T>(input, colIndex, tfShape));
     }
     else
     {
         return(new TensorValueGetter <T>(input, colIndex));
     }
 }
Esempio n. 3
0
 /// <summary>
 /// Creates a new tensor from a portion of an array of bytes
 /// </summary>
 /// <param name="shape">Represents the tensor shape.</param>
 /// <param name="data">The linear array of data, the data is shuffled to fit in the tensor with the specified dimensions.</param>
 /// <param name="start">The offset into the provided data array where the data resides.</param>
 /// <param name="count">The number of bytes to copy from count into the tensor.</param>
 /// <remarks>
 /// Use the FromBuffer method to create a tensor that has the specified dimensions
 /// and is initialized with data from the data array.   The data is copied starting
 /// at the start offset, for count bytes and is laid out into the tensor following the
 /// specified dimensions.
 /// </remarks>
 public static TFTensor FromBuffer(TFShape shape, byte [] data, int start, int count)
 {
     return(new TFTensor(SetupTensor(TFDataType.UInt8, shape, data, start, count, size: 1)));
 }
Esempio n. 4
0
        private TensorFlowTransform(IHostEnvironment env, TFSession session, string[] inputs, string[] outputs)
        {
            Contracts.CheckValue(env, nameof(env));
            _host = env.Register(nameof(RegistrationName));
            _host.CheckValue(session, nameof(session));
            _host.CheckNonEmpty(inputs, nameof(inputs));
            _host.CheckNonEmpty(outputs, nameof(outputs));
            Session = session;
            foreach (var input in inputs)
            {
                _host.CheckNonWhiteSpace(input, nameof(inputs));
                if (Session.Graph[input] == null)
                {
                    throw _host.ExceptParam(nameof(inputs), $"Input column '{input}' does not exist in the model");
                }
                var tfInput = new TFOutput(Session.Graph[input]);
                if (!TensorFlowUtils.IsTypeSupported(tfInput.OutputType))
                {
                    throw _host.ExceptParam(nameof(session), $"Input type '{tfInput.OutputType}' of input column '{input}' is not supported in TensorFlow");
                }
            }

            var newNames = new HashSet <string>();

            foreach (var output in outputs)
            {
                _host.CheckNonWhiteSpace(output, nameof(outputs));
                if (!newNames.Add(output))
                {
                    throw _host.ExceptParam(nameof(outputs), $"Output column '{output}' specified multiple times");
                }
                if (Session.Graph[output] == null)
                {
                    throw _host.ExceptParam(nameof(outputs), $"Output column '{output}' does not exist in the model");
                }
            }

            Inputs        = inputs;
            TFInputTypes  = new TFDataType[Inputs.Length];
            TFInputShapes = new TFShape[Inputs.Length];
            for (int i = 0; i < Inputs.Length; i++)
            {
                var tfInput = new TFOutput(Graph[Inputs[i]]);
                TFInputTypes[i]  = tfInput.OutputType;
                TFInputShapes[i] = Graph.GetTensorShape(tfInput);
                if (TFInputShapes[i].NumDimensions != -1)
                {
                    var newShape = new long[TFInputShapes[i].NumDimensions];
                    newShape[0] = TFInputShapes[i][0] == -1 ? BatchSize : TFInputShapes[i][0];

                    for (int j = 1; j < TFInputShapes[i].NumDimensions; j++)
                    {
                        newShape[j] = TFInputShapes[i][j];
                    }
                    TFInputShapes[i] = new TFShape(newShape);
                }
            }

            Outputs       = outputs;
            OutputTypes   = new ColumnType[Outputs.Length];
            TFOutputTypes = new TFDataType[Outputs.Length];
            for (int i = 0; i < Outputs.Length; i++)
            {
                var   tfOutput = new TFOutput(Graph[Outputs[i]]);
                var   shape    = Graph.GetTensorShape(tfOutput);
                int[] dims     = shape.NumDimensions > 0 ? shape.ToIntArray().Skip(shape[0] == -1 ? BatchSize : 0).ToArray() : new[] { 0 };
                var   type     = TensorFlowUtils.Tf2MlNetType(tfOutput.OutputType);
                OutputTypes[i]   = new VectorType(type, dims);
                TFOutputTypes[i] = tfOutput.OutputType;
            }
        }
Esempio n. 5
0
 /// <summary>
 /// Creates a new tensor from a portion of an array of Complex numbers
 /// </summary>
 /// <param name="shape">Represents the tensor shape.</param>
 /// <param name="data">The linear array of data, the data is shuffled to fit in the tensor with the specified dimensions.</param>
 /// <param name="start">The offset into the provided data array where the data resides.</param>
 /// <param name="count">The number of bytes to copy from count into the tensor.</param>
 /// <remarks>
 /// Use the FromBuffer method to create a tensor that has the specified dimensions
 /// and is initialized with data from the data array.   The data is copied starting
 /// at the start offset, for count bytes and is laid out into the tensor following the
 /// specified dimensions.
 /// </remarks>
 public static TFTensor FromBuffer(TFShape shape, Complex [] data, int start, int count)
 {
     return(new TFTensor(SetupTensor(TFDataType.Complex128, shape, data, start, count, size: 16)));
 }
Esempio n. 6
0
 /// <summary>
 /// Creates a new tensor from a portion of an array of longs
 /// </summary>
 /// <param name="shape">Represents the tensor shape.</param>
 /// <param name="data">The linear array of data, the data is shuffled to fit in the tensor with the specified dimensions.</param>
 /// <param name="start">The offset into the provided data array where the data resides.</param>
 /// <param name="count">The number of bytes to copy from count into the tensor.</param>
 /// <remarks>
 /// Use the FromBuffer method to create a tensor that has the specified dimensions
 /// and is initialized with data from the data array.   The data is copied starting
 /// at the start offset, for count bytes and is laid out into the tensor following the
 /// specified dimensions.
 /// </remarks>
 public static TFTensor FromBuffer(TFShape shape, long [] data, int start, int count)
 {
     return(new TFTensor(SetupTensor(TFDataType.Int64, shape, data, start, count, size: 8)));
 }
Esempio n. 7
0
 /// <summary>
 /// Creates a new tensor from a portion of an array of floats
 /// </summary>
 /// <param name="shape">Represents the tensor shape.</param>
 /// <param name="data">The linear array of data, the data is shuffled to fit in the tensor with the specified dimensions.</param>
 /// <param name="start">The offset into the provided data array where the data resides.</param>
 /// <param name="count">The number of bytes to copy from count into the tensor.</param>
 /// <remarks>
 /// Use the FromBuffer method to create a tensor that has the specified dimensions
 /// and is initialized with data from the data array.   The data is copied starting
 /// at the start offset, for count bytes and is laid out into the tensor following the
 /// specified dimensions.
 /// </remarks>
 public static TFTensor FromBuffer(TFShape shape, float [] data, int start, int count)
 {
     return(new TFTensor(SetupTensor(TFDataType.Float, shape, data, start, count, size: 4)));
 }
            private ITensorValueGetter CreateTensorValueGetter(IRow input, TFDataType tfType, bool isVector, int colIndex, TFShape tfShape)
            {
                var type = TFTensor.TypeFromTensorType(tfType);

                _host.AssertValue(type);
                return(Utils.MarshalInvoke(CreateTensorValueGetter <int>, type, input, isVector, colIndex, tfShape));
            }
Esempio n. 9
0
 /// <summary>
 /// Compiles the initialization function
 /// </summary>
 /// <param name="graph">Tensorflow graph to use for creating the initialization function</param>
 /// <param name="shape">The shape of the variable to initialize</param>
 /// <returns>Returns the compiled initialization function</returns>
 public override TFOutput Compile(TFGraph graph, TFShape shape)
 {
     return(graph.Zeros(shape));
 }