2

First of all, I tried those solutions: 1, 2, 3, and 4, but did not work for me.

After training and testing the neural network, I am trying to show some examples to verify my work. I named the method predict which I pass the image to it to predict for which class it belongs:

def predict(model, image_path, topk=5):
''' Predict the class (or classes) of an image using a trained deep learning model.
'''

output = process_image(image_path)
output.unsqueeze_(0)
output = output.cuda().float()

model.eval()

with torch.no_grad():
    score = model(output)
    prob, idxs = torch.topk(score, topk)

    # Convert indices to classes
    idxs = np.array(idxs)
    idx_to_class = {val:key for key, val in model.class_to_idx.items()}
    classes = [idx_to_class[idx] for idx in idxs[0]]

    # Map the class name with collected topk classes
    names = []
    for cls in classes:
        names.append(cat_to_name[str(cls)])

    return prob, names

Then there is the final step which displays the final result based on the training of the neural network and done like this:

# TODO: Display an image along with the top 5 classes
x_pos, y_pos = predict(model, img_pil, topk=5)

ax_img = imshow(output)
ax_img.set_title(y_pos[0])

plt.figure(figsize=(4,4))
plt.barh(range(len(y_pos)), np.exp(x_pos[0]))
plt.yticks(range(len(y_pos)), y_pos)

plt.show()

The error is:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-45-e3f9951e9804> in <module>()
----> 1 x_pos, y_pos = predict(model, img_pil, topk=5)
      2
      3 ax_img = imshow(output)
      4 ax_img.set_title(y_pos[0])
      5

1 frames
<ipython-input-44-d77500f31561> in predict(model, image_path, topk)
     14
     15         # Convert indices to classes
---> 16         idxs = np.array(idxs)
     17         idx_to_class = {val:key for key, val in model.class_to_idx.items()}
     18         classes = [idx_to_class[idx] for idx in idxs[0]]

/usr/local/lib/python3.6/dist-packages/torch/tensor.py in __array__(self, dtype)
    456     def __array__(self, dtype=None):
    457         if dtype is None:
--> 458             return self.numpy()
    459         else:
    460             return self.numpy().astype(dtype, copy=False)

TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.

How do I solve this?

I tried to change idx to idxs = idxs.cpu().numpy() and the error is:

TypeError                                 Traceback (most recent call last)
<ipython-input-62-e3f9951e9804> in <module>()
      5
      6 plt.figure(figsize=(4,4))
----> 7 plt.barh(range(len(y_pos)), np.exp(x_pos[0]))
      8 plt.yticks(range(len(y_pos)), y_pos)
      9

/usr/local/lib/python3.6/dist-packages/torch/tensor.py in __array__(self, dtype)
    456     def __array__(self, dtype=None):
    457         if dtype is None:
--> 458             return self.numpy()
    459         else:
    460             return self.numpy().astype(dtype, copy=False)

TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.
Ahmad
  • 1,618
  • 5
  • 24
  • 46

3 Answers3

6

Try to change

idxs = np.array(idxs)

to

idxs = idxs.cpu().numpy()

And change

plt.barh(range(len(y_pos)), np.exp(x_pos[0]))

to

plt.barh(range(len(y_pos)), np.exp(x_pos[0].cpu().numpy()))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
one
  • 2,205
  • 1
  • 15
  • 37
  • still the same error: TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first. – Ahmad Sep 07 '19 at 10:03
  • 1
    you first change to `idxs = idxs.cpu().numpy()` and show the complete error information. there may be somewhere else existing the same error – one Sep 07 '19 at 10:03
  • may be you can't change at your post. I can't understand the comment as the disorder format. – one Sep 07 '19 at 10:11
3

So if you're here in 2021 and still have this "TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first."

Try x.to("cpu").numpy() from this site https://jbencook.com/pytorch-numpy-conversion/

So something like idxs = idxs.to("cpu").numpy().squeeze() would work.

ArthurEzenwanne
  • 176
  • 2
  • 10
0

Numpy does not use GPU; Numpy operations have to be done in CPU. Torch.Tensor can be done in GPU. So wherever numpy operations are there you need to move it to CPU

Ex device below is CPU; Model is run in GPU

    df["x"] = df["x"].apply(lambda x: torch.tensor(x).unsqueeze(0))
    df["y"] = df["x"].apply(lambda x: model(x.to(device))[0].detach())

and below when you need to use np.pad, you move it back to cpu

df["y"] = df["y"].apply(lambda x: np.pad(x.to("cpu"), [(0, 0), (0,  max_length - x.shape[1])], 'constant')  ) 
Alex Punnen
  • 5,287
  • 3
  • 59
  • 71