Tensor
Tensor란 pytorch의 자료형으로, 단일 데이터 타입으로 된 자료들의 다차원 행렬이다.
이를 이용하여 GPU 연산을 수행한다.
- data : list, ndarray 등의 data type
- dtype : array 내부의 데이터 타입 (ex.float32, int64...)
- device: default=None, CPU or GPU
- requires_grad : default=False, gradient 값 저장 유무
[오류가 난다면 생각해 볼 것!]
✅ Tensor로 변환되는 데이터인가?
✅ 연산할 tensor 간 dtype이 같은가?
✅ 연산할 tensor가 같은 device에 올라가 있는가?
1. torch.tensor()
tensor 변환 시, 새 메모리를 할당한다.
tensor의 dtype은 따로 설정하지 않으면 자동을 torch.float 형태로 할당한다.
x = [[2,6,3],[2,5,7]] # list
np_x = np.array(x) #numpy.ndarray
# list to tensor
tensor_x = torch.tensor(x) # CPU tensor
2. torch.from_numpy()
torch.tensor로 tensor를 생성하면, input array 사본을 tensor로 생성하여 새로운 메모리를 할당한다.
➡ 생성된 tensor의 값을 변경하더라도 numpy array값은 바뀌지 않는다.
그러나,
torch.from_numpy()로 tensor를 생성하면 자동으로 input array의 dtype을 상속받아 tensor와 메모리를 공유한다.
➡ tensor의 값을 변경하면 input array 값도 바뀐다.
# ndarray to tensor
tensor_x = torch.tensor(np_x) # tensor
tensor_x = torch.from_numpy(np_x) #tensor
3. tensor device / dtype 변경하기
device = torch.device("cuda")
# to cuda(GPU)
y = torch.as_tensor(tensor_x, dtype=torch.float64, device=device)
y = tensor_x.to(device, dtype=torch.float64)
tensor_x.cuda()
# to cpu
tensor_x.cpu()
4. tensor 복사하기
- detach() : 기존 Tensor에서 gradient 전파가 안 되는 tensor를 생성한다.
➡ storage를 공유하므로 detach로 생성한 tensor가 변경되면 원본 tensor도 변한다. - clone() : 기존 Tensor와 내용을 복사한 텐서 생성한다.
with torch.no_grad()는 범위 내의 requires_grad를 모두 False로!
# 모델 결과를 계산할때
tensor_x.detach().cpu().numpy()
5. 특정 shape의 tensor 생성하기
shape = (2,3,)
# 0으로 이루어진 tensor
zero_tensor = torch.zeros(shape)
print(f"zero tensor: {zero_tensor}, shape: {(zero_tensor.shape)}")
# 1로 이루어진 tensor
one_tensor = torch.ones(shape)
print(f"one tensor: {one_tensor}, shape: {(one_tensor.shape)}")
rand_tensor = torch.rand(shape) # [0,1) 범위의 균등 분포에서 임의의 값 추출
print(f"random tensor: {rand_tensor}, shape: {(rand_tensor.shape)}")

rand_dis_tensor = torch.randn(shape) # 정규분포에서 임의 값 추출
print(f"random distribution tensor: {rand_dis_tensor}, shape: {(rand_dis_tensor.shape)}")

rand_int_tensor = torch.randint(10, shape) # [low,high) 범위의 int 값을 임의 추출
print(f"random int tensor: {rand_int_tensor}, shape: {(rand_int_tensor.shape)}")
# 1D tensor
one_dim_tensor = torch.arange(1,4,2) # start, end, step
print(f"일정한 간격의 1D tensor : {one_dim_tensor}")
one_dim_shaped_tensor = torch.arange(1*2*3) # default:start=0, step=1
print(f"{one_dim_shaped_tensor}")
print(f"Shaped : {one_dim_shaped_tensor.view(1,2,3)}")
6. tensor 정보 확인 및 변경
- rank : dimension 개수
- shape : 각 dimension의 value 개수
- axis : 특정 dimension 지칭
예시)
rank : 3
shape : (4, 3, 2)
axis : 0,1,2
x = torch.rand(4,3,2)
print(f"Rank : {len(x.shape)}") # 3
print(f"Shape : {x.shape}") # torch.Size([4, 3, 2])
6-1. Shape 변경하기
1개의 차원에 한해서 -1로 값 지정이 가능한데, 이 경우 자동으로 변환이 가능한 차원이
지정되어 차원 배정한다.
- view() : 기존의 데이터와 같은 메모리 공간을 공유하며 stride 크기만 변경하여 보여주기만 다르게 한다.
- contigious해야만 동작하며, 아닌 경우 에러가 발생한다.
- reshape() : 가능하면 input의 view를 반환하고, 안되면 contiguous 한 tensor로 copy 하고 view를 반환한다.
view는 메모리가 기존 Tensor와 동일한 메모리를 공유하는게 보장되지만 reshape은 그렇지 않다.
- 안전하게 형태만 바꾸고 싶다 ➡ reshape
- 메모리가 공유되어 업데이트에 대한 보장이 이뤄진다 ➡ view (단 continguous하지 않은 경우 에러 발생 가능)
메모리 주소는 x.storage().data_ptr()로 확인 가능 (x는 Tensor)
# shape 변경
print(x.view(-1,2,2).shape) # the size -1 is inferred from other dimensions
#(?,2,2) 형태로 변경해라
# torch.Size([6, 2, 2])
xx = x.view(4,6,-1) #(4,6,?) 형태로 변경해라
xx.shape #torch.Size([4, 6, 1])
6-2. Rank 변경하기
- squeeze() : 차원의 size가 1인 차원을 없애준다.
- 여러개의 차원 중 특정 차원만 지우고 싶다면 x.squeeze(1)처럼 사용, 아니면 모두 제거한다.
- unsqueeze() : 차원 size가 1인 차원을 생성한다.
- idx번째 차원을 만들면 기존 idx차원부터 한 칸씩 미뤄진다.
# rank 변경
xxx = xx.squeeze()
print(xxx.shape) # torch.Size([4, 6])
print(xxx.unsqueeze(dim=-1).shape) # 마지막에 차원 추가
# torch.Size([4, 6, 1])
REFERENCE
https://jimmy-ai.tistory.com/122
What’s the difference between reshape and view in pytorch?
https://sanghyu.tistory.com/19
'Data Science > Basic' 카테고리의 다른 글
온톨로지는 뭘까. (1) | 2025.02.02 |
---|---|
지표를 설계해보자 (1) | 2024.11.10 |
지표, 넌 누구니? (1) | 2024.10.27 |
Sequential Model, Functional Model (0) | 2022.04.30 |
댓글