본문 바로가기
AI Naver boost camp/[Week 01] Pytorch

Tensor 생성과 조작

by AI-BT 2024. 8. 6.
728x90
반응형

Tensor 생성

import torch

# 문제 1: 크기 (3, 2)인 모든 원소가 0인 텐서를 만드세요.
a = torch.zeros([3, 2])
print(a)

# 문제 2: 크기 (2, 4)인 모든 원소가 1인 텐서를 만드세요.
b = torch.ones([2, 4])
print(b)

# 문제 3: 크기 (4, 3)인 텐서를 만들고, 각 원소가 0과 1 사이의 균등 분포에서 랜덤하게 초기화되도록 하세요.
c = torch.rand([4, 3])
print(c)

# 문제 4: 크기 (3, 3)인 텐서를 만들고, 각 원소가 평균 0, 표준편차 1의 정규 분포에서 랜덤하게 초기화되도록 하세요.
d = torch.randn([3, 3])
print(d)

# 문제 5: 1부터 10까지의 step 2를 가지는 순서대로 1차원 텐서를 만드세요.
e = torch.arange(1, 10, 2)
print(e)

 

 

Tensor 조작

 

1. indexing, slicing

import torch

tensor = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 문제 1: 텐서의 첫 번째 행을 추출하세요.
result = tensor[0, :]
print(result)

# 문제 2: 텐서의 두 번째 열을 추출하세요.
result = tensor[:,1]
print(result)

# 문제 3: 텐서의 마지막 두 개의 행을 추출하세요.
result = tensor[1:,:]
print(result)

# 문제 4: 텐서의 두 번째 행과 세 번째 행에서 첫 번째 열과 두 번째 열을 추출하세요.
result = tensor[1:,:2]
print(result)

# 문제 5: 텐서의 짝수 인덱스의 행만 추출하세요.
result = tensor[::2,:]
print(result)

 

 

2. Tensor 형태 변경

 

- view()

view() 메서드는 텐서의 형태를 변경하지만,

원래 텐서와 데이터의 메모리 레이아웃이 연속적(contiguous)일 때만 사용 가능하다.

만약 텐서가 연속적이지 않다면, view()를 사용하기 전에 contiguous() 메서드를 호출한다.

 

- reshape()

reshape() 메서드는 텐서의 형태를 변경한다.

view()와 달리, reshape()는 원래 텐서가 연속적이지 않더라도 새로운 텐서를 만들어서 형태를 변경할 수 있다.

따라서 reshape()는 view()보다 유연하게 사용할 수 있습니다.

 

어떤것을 사용하는 것이 좋을까?

reshape 유연성과 안전하다는 장점이 있지만,

countigus(연속적)이지 않을때는 메모리를 새로 할당하기 때문에

성능 저하의 단점이 있다. 따라서 메모리 연속성이 확실하고 성능이 중요한 경우 view() 메소드를 사용하는게 좋다.

 

차이점 
메모리 연속성
view(): 메모리가 연속적일 때만 사용 가능. 그렇지 않으면 contiguous()를 호출해야 함.
reshape(): 메모리가 연속적이지 않아도 새로운 텐서를 만들어 형태를 변경할 수 있음.

사용 유연성
view(): 덜 유연하지만, 메모리가 연속적인 경우 더 효율적일 수 있음.
reshape(): 더 유연하며, 다양한 상황에서 사용 가능.

import torch

# 원래 텐서
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)

# (2, 3) 형태를 (3, 2)로 변경
view_tensor = tensor.view(3, 2)
print("Original Tensor:")
print(tensor)
print("\nView Tensor:")
print(view_tensor)

# 원래 텐서
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)

# (2, 3) 형태를 (3, 2)로 변경
reshape_tensor = tensor.reshape(3, 2)
print("Original Tensor:")
print(tensor)
print("\nReshape Tensor:")
print(reshape_tensor)

 

 

3. squeeze(), unsueeze()

import torch

# squeeze
# 원래 텐서
tensor = torch.tensor([[[[1, 2, 3, 4, 5]],
                        [[6, 7, 8, 9, 10]],
                        [[11, 12, 13, 14, 15]]]])

print("Original Tensor:")
print(tensor)
print(tensor.shape)

# 크기가 1인 차원을 제거
squeezed_tensor = torch.squeeze(tensor)

print("\nSqueezed Tensor:")
print(squeezed_tensor)
print(squeezed_tensor.shape)3

# unsqueeze
# 원래 텐서
tensor = torch.tensor([[1, 2, 3, 4, 5],
                       [6, 7, 8, 9, 10],
                       [11, 12, 13, 14, 15]])

print("Original Tensor:")
print(tensor)
print(tensor.shape)

# 첫 번째 위치에 크기가 1인 차원을 추가
unsqueezed_tensor_0 = torch.unsqueeze(tensor, 0)

print("\nUnsqueezed Tensor (dim=0):")
print(unsqueezed_tensor_0)
print(unsqueezed_tensor_0.shape)

# 두 번째 위치에 크기가 1인 차원을 추가
unsqueezed_tensor_1 = torch.unsqueeze(tensor, 1)

print("\nUnsqueezed Tensor (dim=1):")
print(unsqueezed_tensor_1)
print(unsqueezed_tensor_1.shape)

# 세 번째 위치에 크기가 1인 차원을 추가
unsqueezed_tensor_2 = torch.unsqueeze(tensor, 2)

print("\nUnsqueezed Tensor (dim=2):")
print(unsqueezed_tensor_2)
print(unsqueezed_tensor_2.shape)

 

dimension 이 1 추가 혹은 축소를 하는 방법이다.

 

4. stack

pyTorch에서 여러 텐서를 새로운 차원으로 쌓아 하나의 텐서로 만드는 데 사용되는 함수이다.

이 함수는 주어진 텐서들의 리스트를 받아,  지정한 차원(axis)에 따라 새로운 텐서를 생성한다.

torch.stack은 각 텐서의 shape이 동일해야 한다.

import torch

# 3개의 2차원 텐서를 생성
tensor1 = torch.tensor([[1, 2], [3, 4]])
tensor2 = torch.tensor([[5, 6], [7, 8]])
tensor3 = torch.tensor([[9, 10], [11, 12]])

# 텐서 리스트
tensor_list = [tensor1, tensor2, tensor3]
print("tensor_list = ", tensor_list)

# 0번째 차원에 쌓기
stacked_tensor_0 = torch.stack(tensor_list, dim=0)

print("Stacked Tensor (dim=0):")
print(stacked_tensor_0)
print(stacked_tensor_0.shape)  # (3, 2, 2)

# 1번째 차원에 쌓기
stacked_tensor_1 = torch.stack(tensor_list, dim=1)

print("\nStacked Tensor (dim=1):")
print(stacked_tensor_1)
print(stacked_tensor_1.shape)  # (2, 3, 2)

# 2번째 차원에 쌓기
stacked_tensor_2 = torch.stack(tensor_list, dim=2)

print("\nStacked Tensor (dim=2):")
print(stacked_tensor_2)
print(stacked_tensor_2.shape)  # (2, 2, 3)

 

코드 결과

tensor_list =  [tensor([[1, 2],
        [3, 4]]), tensor([[5, 6],
        [7, 8]]), tensor([[ 9, 10],
        [11, 12]])]
Stacked Tensor (dim=0):
tensor([[[ 1,  2],
         [ 3,  4]],

        [[ 5,  6],
         [ 7,  8]],

        [[ 9, 10],
         [11, 12]]])
torch.Size([3, 2, 2])

Stacked Tensor (dim=1):
tensor([[[ 1,  2],
         [ 5,  6],
         [ 9, 10]],

        [[ 3,  4],
         [ 7,  8],
         [11, 12]]])
torch.Size([2, 3, 2])
...

        [[ 3,  7, 11],
         [ 4,  8, 12]]])
torch.Size([2, 2, 3])

 

 

5. clone(), detach() 차이

 

clone()
목적 

텐서의 데이터를 복제하여 새로운 텐서를 만들되, 원본 텐서와 같은 연산 그래프에 속하게 함.


기울기 계산

복제된 텐서로 수행한 연산은 연산 그래프에 기록되어 역전파 시 원본 텐서에 영향을 미침.\


사용 예시

복제된 텐서를 변형하거나 추가 연산을 수행하되, 원본 텐서와의 연관성을 유지하고 싶을 때.

detach()
목적

텐서를 연산 그래프에서 분리하여 새로운 텐서를 만들고, 역전파 시 해당 텐서의 기울기를 계산하지 않음.


기울기 계산

분리된 텐서를 통한 연산은 연산 그래프에 기록되지 않으므로 역전파 시 원본 텐서에 영향을 미치지 않음.


사용 예시

파라미터를 고정하거나, 그래디언트 계산에서 제외하고 싶을 때.

728x90
반응형

댓글