Python/Pytorch

[Pytorch] 텐서를 넘파이 배열, 리스트로 변환하는 방법 정리

jimmy_AI 2022. 8. 12. 16:29
반응형

파이토치 tensor를 numpy array나 list로 바꾸기

파이썬 파이토치에서 tensor 자료형을 넘파이 배열 또는 리스트 자료형으로

변환하는 방법에 대하여 케이스별로 정리해보도록 하겠습니다.

 

 

1. 기본 텐서의 경우 : numpy() / tolist()

먼저, grad 정보가 없고 gpu에 선언되지 않은 가장 기본적인 텐서의 경우입니다.

아래와 같은 예시의 tensor를 형변환해보도록 하겠습니다.

data1 = torch.randn(3, 2)

data1

# 출력 결과
tensor([[-0.2370, -1.4314],
        [-0.7539,  0.5552],
        [-1.1405, -0.4047]])

 

넘파이 배열 자료형으로 바꾸려면 tensor.numpy() 형태로 지정해주시면 됩니다.

data1.numpy()

# 출력 결과
array([[-0.23703063, -1.4314126 ],
       [-0.7539355 ,  0.5551915 ],
       [-1.140489  , -0.40470666]], dtype=float32)

 

반면, 리스트 자료형으로 변환하려면 tensor.tolist() 형태로 작성해주시면 됩니다.

data1.tolist()

# 출력 결과
[[-0.23703062534332275, -1.4314125776290894],
 [-0.7539355158805847, 0.5551915168762207],
 [-1.1404889822006226, -0.4047066569328308]]

 

 

2. grad 정보가 포함된 경우 numpy array로 변환 : detach().numpy()

만일, 모델의 output으로 반환된 텐서 내에 autograd 기능이 포함되어 있어

grad 정보가 같이 저장된 경우 리스트 변환시에는 위 예시처럼 tolist()를 바로 적용할 수 있지만

넘파이 배열로 바꾸려면 detach() 메소드로 grad 정보 제거 후 numpy()를 적용해야 합니다.

 

예시로 다음과 같이 grad 정보가 저장된 텐서를 가정해보겠습니다.

data2

# 출력 결과
tensor([[0.3311, 1.1163],
        [0.4816, 0.4099],
        [0.5949, 0.3613]], grad_fn=<AddmmBackward0>)

 

numpy()를 바로 적용 시도할 경우에는 아래와 같은 오류 메시지가 출력됩니다.

data2.numpy()

# RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.

 

따라서, 넘파이 배열 변환 시에는 tensor.detach().numpy() 형태로 작성해주셔야 합니다.

data2.detach().numpy()

# 출력 결과
array([[0.33107007, 1.116349  ],
       [0.4816136 , 0.4098794 ],
       [0.5949428 , 0.36126232]], dtype=float32)

 

반응형

 

3. gpu에 선언된 텐서의 경우 numpy array로 변환 : cpu().numpy()

만일, gpu에 올라가있는 tensor라면 넘파이 배열 자료형 변환 시

cpu() 메소드를 통하여 cpu로 옮긴 뒤, numpy() 메소드를 적용해주셔야 합니다.

(단, 리스트 변환 시에는 마찬가지로 tolist()만 사용해주셔도 무방합니다.)

 

아래와 같이 cuda에 선언된 예시 텐서를 np.array로 바꿔보겠습니다.

data3 = torch.rand(3, 2).cuda()

data3

# 출력 결과
tensor([[0.7657, 0.5605],
        [0.3344, 0.0708],
        [0.1097, 0.8183]], device='cuda:0')

 

만일, 그냥 numpy()를 바로 시도할 경우 아래와 같이 오류가 발생합니다.

data3.numpy()

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

 

여기서는 tensor.cpu().numpy() 형태로 넘파이 배열 자료형 변환을 완료하였습니다.

data3.cpu().numpy()

# 출력 결과
array([[0.7657117 , 0.5605019 ],
       [0.3344291 , 0.07077938],
       [0.10965961, 0.81833345]], dtype=float32)

 

참고로, 만일 gpu에 올라가 있고 grad 정보도 포함되어 있는 경우라면

detach()와 cpu()를 모두 적용해주셔야 넘파이 배열로의 형변환을 완료할 수 있습니다.

(여기서도 리스트로 변환 시에는 tolist()만 단독 적용이 가능합니다.)

data4

# 출력 결과
tensor([[-0.4238, -0.4075],
        [ 0.2597, -0.2759],
        [-0.0784, -1.2160]], device='cuda:0', grad_fn=<AddmmBackward0>)

### 넘파이 배열로 자료형 변환 ###
data4.detach().cpu().numpy()

# 출력 결과
array([[-0.42379946, -0.40748018],
       [ 0.25967413, -0.2758565 ],
       [-0.07839801, -1.2159803 ]], dtype=float32)

### 리스트로 자료형 변환 ###
data4.tolist()

# 출력 결과
[[-0.42379945516586304, -0.4074801802635193],
 [0.2596741318702698, -0.27585649490356445],
 [-0.07839801162481308, -1.2159802913665771]]