How do I convert a 3*1 vector into a 2*2 lower triangular matrix in pytorch

Viewed 101

I have created a network in pytorch, whose output is B*N*H*W. I want that N is equal to 3 and then convert the output into a 2*2 lower trangular matrix with a upper zero in the 2nd demension. There may be two ways to achieve that.

    class Net(nn.Module):
        def __init__(self, in_ch=3, out_ch=N):
        super().__init__():
            self.net = nn.Sequatial([...])
        def forward(self, x):
            return self.net(x)

First, let the network output be B*4*H*W, and then mutiple a mask of [1,0,1,1] in the 2nd dimension to make one channel to be zero. This way can get a 2*2 lower trangular matrix with a upper zero, while I don't know if there will be information lost. And I don't know how to check the loss of information while training.

    class Net(nn.Module):
        def __init__(self, in_ch=3, out_ch=4):
        super().__init__():
            self.net = nn.Sequatial([...])
            self.mask = torch.FloatTensor([1.,0.,1.,1.]).cuda()
        def forward(self, x):
            return torch.einsum('abij,b->abij', self.net(x), self.mask)

Second, I think that the direct solution is to output a B*3*H*W tensor and convert the 2nd dimension into a 2*2 lower trangular matrix with a upper zero. But I don't have an effictive approach to implementing this. The transform operation in 2nd dimension may be like:

    array[2.3, 5.1, 6.3]  -->  array[[2.3, 0.],
                                     [5.1, 6.3]] 

There are still two questions. How to convert the 2nd dimension of B*3*H*W to a tensor of shape B*2*2*H*W and if the first method will make the information lost while training.

1 Answers

Try this:

You can easily calculate N from len(a) as N*(N+1)/2 = len(a) => N

Here is the numpy version:

a = np.array([2.3, 5.1, 6.3])  
N = 2

c = np.zeros((N, N))
c[np.tril_indices(N)] = a

Output:

c
>array([[2.3, 0. ],
       [5.1, 6.3]])

Here is the pytorch version:

a = torch.tensor([2.3, 5.1, 6.3])
c = torch.zeros(N, N)
c[torch.tril_indices(N, N, offset=0).tolist()] = a
c

Output:

tensor([[2.3000, 0.0000],
        [5.1000, 6.3000]])
Related