Free conversion, sometimes free memory
PyTorch and NumPy interoperate trivially. The only thing to internalize is when the conversion shares memory and when it copies:
torch.from_numpy(arr)— shares memory. Mutating one mutates the other.tensor.numpy()— shares memory if the tensor is CPU and contiguous. Errors if it's on GPU.torch.tensor(arr)— always copies. Use this when you want independence.torch.as_tensor(arr)— shares memory when possible, copies otherwise. Useful when you don't care which.
The GPU rule
You can only get a NumPy array out of a CPU tensor. If your tensor is on GPU, move it back first (.cpu()). And if it has gradients, call .detach() first to get rid of the graph attachment — otherwise NumPy will refuse to convert it.
The full incantation for "give me numpy from a model output": output.detach().cpu().numpy(). Memorize that chain — you'll write it constantly when computing metrics or plotting.