Transpose issue

I’ve been running into an issue with Transpose.

I used to use Ops.Transpose on a Tensor to permutate the dimensions.
For example, I had a tensor of shape (1, 256, 256, 3) and but my model only takes into input a tensor of shape (1, 3, 256, 256). Thus in Sentis 1.3.0, I was doing this:

TensorFloat output = ops.Transpose(inputTensor, new int[] {0, 3, 1, 2})

and it would modify the data as well as the shape properly into the output tensor.

But now, I’m currently using IBackend.Transpose which is the same thing but we need to add the output tensor in the parameters. But it doesn’t update the shape of the output tensor.
I did a test:

        IBackend backend = WorkerFactory.CreateBackend(BackendType.CPU);
        TensorShape shape = new TensorShape(2, 3);
        float[] srcData = { 1, 2, 3, 4, 5, 6};
        TensorFloat tens = new TensorFloat(shape, srcData);
        tens.PrintDataPart(6);
        TensorFloat transposedTens = TensorFloat.AllocNoData(shape);
        Debug.Log($"Before transpose: tens.shape=" + tens.shape + " transposedTens.shape=" + transposedTens.shape);
        backend.Transpose(tens, transposedTens, new int[] { 1, 0 });
        Debug.Log($"After transpose: tens.shape=" + tens.shape + " transposedTens.shape=" + transposedTens.shape);
        transposedTens.PrintDataPart(6);
        backend.Dispose();
        tens.Dispose();
        transposedTens.Dispose();

And this is the output:

 1 2 3 4 5 6
Before transpose: tens.shape=(2, 3) transposedTens.shape=(2, 3)
After transpose: tens.shape=(2, 3) transposedTens.shape=(2, 3)
1 4 2 5 3 6 

The issue I have with the output is that the transposedTens’ shape is unchanged. Shouldn’t it be (3, 2) now ?
I may be completely wrong so please feel free to correct me.

Hi, unfotunately the backend API does not automatically do shape checking. You have to specify the output shape yourself.

On the line:

 TensorFloat transposedTens = TensorFloat.AllocNoData(shape);

you can replace with

 TensorFloat transposedTens = TensorFloat.AllocNoData(new TensorShape(3,2));

BTW you can also use the Functional API for manipulating tensors within models which has shape checking.

Thank you very much, that was quick :slight_smile:

Well I was actually checking the Functional API since I am preprocessing and postprocessing tensors so that might makes things even easier

Hi @MS-Fove .
Did you also know, if you are using TextureConverter.ToTensor(texture) to get the tensor from a texture, you can also specify the ordering without needing to use a permute operation:

TextureTransform settings = new TextureTransform().SetDimensions(256, 256, 3).SetTensorLayout(TensorLayout.NCHW)
var tensor = TextureConverter.ToTensor(texture,settings);

Here is also the functional code which will do the same thing. Let’s assume you want to permute the first input of two inputs:

         var newModel = Functional.Compile(
            (input1, input2) =>model.Forward ( Functional.Permute(input1, new[] { 0, 3, 1, 2 } ), input2)[0],
            (model.inputs[0],model.inputs[1])
        );

You can use the newModel now in place of the old model which will automatically permute the input1. The newModel inputs are now renamed as “input_0”, “input_1” and the outputs as “output_0”,… etc.