Porting CPU Model to GPU version

import torch
from torch import nn
from torchvision import models
from torch.autograd import Variable
class TableModule(nn.Module):
    def __init__(self):
        super(TableModule, self).__init__()
        
    def forward(self, x, dim):
        y = torch.cat(x, dim)
        return y


class VGGkModule(nn.Module):
    def __init__(self):
        super(VGGkModule,self).__init__()
        self.layer1 = models.vgg16('pretrained=true')
        self.layer2 = models.vgg16('pretrained=true')
        self.layer3 = models.vgg16('pretrained=true')
        self.layer4 = models.vgg16('pretrained=true')
        self.layer5 = models.vgg16('pretrained=true')
     
    def forward(self,x):
        y1 = self.layer1(x[0])
        y2 = self.layer2(x[1])
        y3 = self.layer3(x[2])
        y4 = self.layer4(x[3])
        y5 = self.layer5(x[4])
        par = TableModule()
        rep = par([y1,y2,y3,y4,y5],1)
        return rep


class LinearModule(nn.Module):
    def __init__(self):
        super(LinearModule,self).__init__()
        self.layer1 = nn.Linear(5000,1000)
    def forward(self,x):
        net = VGGkModule()
        x1 = net(x)
        y = self.layer1(x1)
        return y


class ParallelModule(nn.Module):
    def __init__(self):
        super(ParallelModule, self).__init__()
        self.layer1 = models.vgg16('pretrained=true')
        self.layer2 = LinearModule()        
    def forward(self, x):
        y1 = self.layer1(x[0])
        y2 = self.layer2(x[1:6])
        par = TableModule()
        y  = par([y1,y2],1)
        return y


class ProjModule(nn.Module):
    def __init__(self):
        super(ProjModule,self).__init__()
        self.layer1 = nn.Linear(2000,1000)
    def forward(self,x):
        net = ParallelModule()
        x1 = net(x)
        print 'Done1'
        y = self.layer1(x1)
        return y


inp = Variable(torch.rand(6,1,3,224,224))
net = ProjModule()
net.cuda()
output = net(inp.cuda())

I want to convert above code to gpu version but it is throwing a lot of errors by just converting net to cuda and porting inp to gpu using:

inp= torch.rand(6,3,224,224).cuda()

Please tell the solution to port it to gpu.

As well how shall I update this code to accomodate batch size?

What kind of errors are thrown? Could you please post the error messages?
inp should be pushed to GPU using inp = torch.randn(6, 3, 224, 224).cuda().

Sorry, the last line in the statement was incorrect. It is .cuda() only in the actual code.

The error is : Expecting CUDA Tensor(not CPU Tensor)

This error usually is thrown when mixing up cuda.Tensors with CPU Tensors.
Could you post the line of code throwing this error?

Usually this should be enough to train your model on a GPU:

model = ...
model.cuda()
inp = Variable(torch.randn(6, 3, 224, 224).cuda())
output = model(inp)

The error is occuring at the last line. Do I need to port all the classes to cuda as the trace error is giving errors at the lines when it is getting forwarded through vgg.

Trace Error : https://pastebin.com/qQUmFQ8Z

As well please tell how shall I update this code to accomodate batch size?

Could you try to format your code? It’s quite hard to read it at the moment.
Just paste it between:
```
your code
```

It seems that some Modules are still on CPU.
Try to create VGGkModule in your LinearModule in the __init__ function:

class LinearModule(nn.Module):
    def __init__(self):
        super(LinearModule, self).__init__()
        self.layer1 = nn.Linear(5000, 1000)
        self.net = VGGkModule()

    def forward(self, x):
        x = self.net(x)
        x = self.layer1(x)
        return x

The LinearModule does not know anything about net, so it cannot push it to the GPU.

1 Like

Thanks. That worked.
Can you please tell also about how can I incorporate batch size?
Currently I am using input

inp = Variable(torch.rand(6,1,3,224,224)).cuda()

You could create a Dataset and use a DataLoader to yield your batches from it.
See the data loading tutorial for more information.

Using this approach you won’t have to implement the batching itself. The DataLoader will handle it for you.

I am able to load the data in batch format using the resource but the data is not getting forwarded through model.

RuntimeError: 5D (nOutputPlane x nInputPlane x kT x kH x kW) tensor expected for weight, but got: [64 x 3 x 3 x 3] at /opt/conda/conda-bld/pytorch_1501972792122/work/pytorch-0.1.12/torch/lib/THCUNN/generic/VolumetricConvolution.cu:38

What can be the cause?

Could you print the shape of the input Variable?
What does dimension 1 stand for in inp?
The dimensions of image data are defined as [batch, channels, width, height].
It seems you have an additional dimension.

Each forward pass expects 6 images(ProjModule) as input.

So, the dims. I want to define are [batch,n_images(i.e. 6),channels(i.e. 3),width,height]

There is a one more 1 which I am using as of now because VGGkModule is throwing an error saying expecting 3 dimensions. but when I add one more dimension, it works.

VGGkModule expects 5 images

class VGGkModule(nn.Module):
    def __init__(self):
        super(VGGkModule,self).__init__()
        self.layer1 = models.vgg16('pretrained=true')
     
    def forward(self,x):
        x = x.view(-1,5,3,224,224)
        y1 = self.layer1(x[:,0])
        y2 = self.layer1(x[:,1])
        y3 = self.layer1(x[:,2])
        y4 = self.layer1(x[:,3])
        y5 = self.layer1(x[:,4])
        par = TableModule()
        rep = par([y1,y2,y3,y4,y5],0)
        m = rep.view(-1,1000,1,5)
        pool = nn.MaxPool1d(5)
        out = pool(m)
        return out.view(-1,1000)

Trying this,
ValueError: expected 3D input (got 4D input)

This code snippet works:

class VGGkModule(nn.Module):
    def __init__(self):
        super(VGGkModule,self).__init__()
        self.layer1 = vgg16(pretrained=False)
     
    def forward(self,x):
        x = x.view(-1,5,3,224,224)
        y1 = self.layer1(x[:,0])
        return y1

x = Variable(torch.randn(10, 5, 3, 224, 224))
model = VGGkModule()
output = model(x)

Could you post the complete error message? Probably another layer is throwing this error.

Ohh. It is occuring due to pooling layer.

Ah Ok, now I see it.
You are using nn.MaxPool1d, which expects the input to have dimensions [batch, channel, length].
Try to change the line before the pooling operation to: m = rep.view(-1, 1000, 5).

Also, you could define the layers in the __init__ function or use the functional API (F.max_pool1d).

1 Like