Search code examples
pythonpytorch

Error: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first


I am trying to make a MLP classifier in PyTorch. The error is produced from the code in the final chunk. I'm not sure why numpy is even involved with this, can someone please point me in the right direction.

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

data = ImageFolder(data_dir, transform=transforms.Compose([transforms.Resize((224,224)),transforms.ToTensor()]))
trainloader = torch.utils.data.DataLoader(data, batch_size=600,shuffle=True, num_workers=2)
testloader = torch.utils.data.DataLoader(data, batch_size=150,shuffle=True, num_workers=2)

dataiter = iter(trainloader)
x_train, y_train = dataiter.next()
x_train = x_train.view(600,-1).to('cpu').to(device)
y_train = y_train.to('cpu').to(device)

class Net(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.layer1 = torch.nn.Linear(150528, 9408)
        self.layer2 = torch.nn.Linear(9408, 3)

    def forward(self, x):
        # here we define the (forward) computational graph,
        # in terms of the tensors, and elt-wise non-linearities
        x = F.relu(self.layer1(x))
        x = self.layer2(x)
        return x

def train_show(network, data, targ, lossFunc, optimiser, epochs):
    lossHistory = []  # just to show a plot later...
    accuHistory = []

    for t in range(epochs):
        optimiser.zero_grad()      # Gradients accumulate by default, so don't forget to do this. 

        y = network.forward(data)  # the forward pass

        loss = lossFunc(y,targ)    # recompute the loss
        loss.backward()            # runs autograd, to get the gradients needed by optimiser
        optimiser.step()           # take a step

        # just housekeeping and reporting
        accuracy = torch.mean((torch.argmax(y,dim=1) == targ).float())
        lossHistory.append(loss.detach().item())
        accuHistory.append(accuracy.detach())

    plt.figure(figsize=(10,5))
    plt.subplot(1,2,1)
    plt.plot(lossHistory,'r'); plt.title("loss"); plt.xlabel("epochs")
    plt.subplot(1,2,2)
    plt.plot(accuHistory,'b'); plt.title("accuracy")
net = Net().to('cpu').to(device)
lossFunction = torch.nn.CrossEntropyLoss().to('cpu').to(device)  
optimiser = torch.optim.SGD(net.parameters(), lr=0.01)
train_show(net, x_train, y_train, lossFunction, optimiser, 50)

Solution

  • The plotting function you are using, plt.plot, works on numpy arrays and not on torch.tensors. Therefore, accHistory is being converted to numpy array and failed there.

    Please see this answer for more details.