본문 바로가기

AI Tech

What is Pytroch?

PyTorch는 머신 러닝과 딥 러닝을 위한 오픈 소스 프레임워크이다.

 

 

 

What is tensor?

https://tutorials.pytorch.kr/beginner/basics/tensorqs_tutorial.html

 

텐서(Tensor)

파이토치(PyTorch) 기본 익히기|| 빠른 시작|| 텐서(Tensor)|| Dataset과 Dataloader|| 변형(Transform)|| 신경망 모델 구성하기|| Autograd|| 최적화(Optimization)|| 모델 저장하고 불러오기 텐서(tensor)는 배열(array)이

tutorials.pytorch.kr

 

PyTorch의 Tensor는 다차원 배열을 표현하는 기본 데이터 구조이다. NumPy의 배열과 유사하다.

 

1. Tensor로 0차원 배열 표현하기

#0차원 배열
a = torch.tensor(36)

#출력값 a =  tensor(36)

 

2. Tensor로 1차원 배열 (vector) 표현하기

# 1차원 tensor
# 1차원 vector

b = torch.tensor([175,30,9,12])

#출력값 b =  tensor([175,  30,   9,  12])

3. Tensor로 2차원 배열 (matrix) 표현하기

# 2차원 tensor
# 3 x 4 행렬

c = torch.tensor([[175,30,9,12],
                 [77, 114, 140, 191],
                 [17, 111, 114, 11]])
                 
# 출력값 c =  tensor([[175,  30,   9,  12],
#        [ 77, 114, 140, 191],
#        [ 17, 111, 114,  11]])

4. Tensor로 3차원 배열 표현하기

# 3차원 Tensor
# 2x3x4 형태의 3차원 Tensor 생성


d = torch.tensor([
    [[1, 2, 3, 4],
     [5, 6, 7, 8],
     [9, 10, 11, 12]],
    
    [[13, 14, 15, 16],
     [17, 18, 19, 20],
     [21, 22, 23, 24]]
])
         
#출력값
# d = tensor([[[ 1,  2,  3,  4],
#         [ 5,  6,  7,  8],
#         [ 9, 10, 11, 12]],
#
#        [[13, 14, 15, 16],
#         [17, 18, 19, 20],
#         [21, 22, 23, 24]]])

 

 

 

 

Tensor의 데이터 타입

https://pytorch.org/docs/main/tensors.html

 

torch.Tensor — PyTorch main documentation

Shortcuts

pytorch.org

 

Tensor가 저장하는 값의 데이터 유형에는 무엇이 있을까?

(Tensor의 모든 원소의 Data type은 같다 => 연산의 효율을 높이고, 데이터의 일관성을 높이기 위해서)

 

Tensor는 uint8, int8, int16(short), int32(int), int64(long), float32(float), float64(double)등 다양한 데이터 유형을 지원한다.

 

#uint8

a = torch.tensor(1,dtype = torch.uint8)

#int8

b = torch.tensor(-1,dtype = torch.int8)

#short

c = torch.tensor(256,dtype = torch.short)

#int

d = torch.tensor(40000,dtype = torch.int)

#long

e = torch.tensor(2000000000,dtype = torch.long)

#float

f = torch.tensor(1,dtype = torch.float)

#double

g = torch.tensor(1,dtype = torch.double)

 

 

Tensor의 타입 캐스팅

 

# int형 타입을 double로 타입 캐스팅

i = torch.tensor([2, 3, 4], dtype = torch.int)
i = i.double()
print("i dtype :",i.dtype)

#출력값 i dtype : torch.float64

 

 

Tensor의 Method

#sum
tensor.sum()

#min, max
tensor.min()
tensor.max()

#mean, var, std
tensor.mean()
tensor.var()
tensor.std()

 

Tensor의 특성을 확인하는 Method

# tensor의 차원의 수를 확인
tensor.dim()

# tensor의 모양을 확인
tensor.size()
tensor.shape #(shape의 경우에는 Method가 아닌 속성이다)

# tensor의 요소의 총 개수 확인
tensor.numel()


### Numpy ###
# Numpy에서는 np.shape가 모양을 확인하고
# np.size가 요소의 총 개수를 확인한다.
# 헷갈리지 않도록 유의하자
# Tensor.numel() = np.size()

 

 

Tensor의 생성

https://pytorch.org/docs/stable/generated/torch.randn.html#torch.randn

 

torch.randn — PyTorch 2.4 documentation

Shortcuts

pytorch.org

 

0으로 초기화된 Tensor의 생성

# 0으로 초기화된 Tensor
a = torch.zeros(5)
a = torch.zeros([2,3])

print('a.dtype =', a.dtype)

a.dtype = torch.float32
# float형으로 초기화 된다.

# 1로 초기화된 Tensor
a = torch.ones([2,4])
a = torch.ones([2,4,6])

a.dtype = torch.float32
# float형으로 초기화 된다.

#특정한 Tensor을 0혹은 1로 초기화하기

a = torch.zeros_like(Tensor)
a = torch.ones_like(Tensor)

 

0, 1 사이의 연속균등분포와 표준정규분포에서 추출한 난수로 채워진 Tensor의 생성

 

# [0, 1]의 연속균등분포에서 추출한 난수로 채워진 Tensor
a = torch.rand(4)
b = torch.rand([3,4])

# 출력값 
# a = tensor([0.4765, 0.5537, 0.1685, 0.2151])
# b = tensor([[0.4924, 0.0125, 0.1298, 0.8920],
#         [0.6239, 0.9564, 0.0620, 0.3326],
#         [0.2280, 0.5233, 0.9444, 0.3584]])

# [0, 1]의 연속균등분포에서 추출한 난수로 Tensor 변환하기

c = torch.rand_like(tensor)

# 표준정규분포에서 추출한 난수로 채워진 Tensor
a = torch.randn(4)
b = torch.randn([3,4])

# 출력값 
# a = tensor([ 0.2871,  0.4660,  1.1191, -0.3111])
# b = tensor([[ 1.1400,  1.4602,  0.3568,  1.3110],
#         [ 1.4635,  0.3371,  1.0896,  0.1497],
#         [-0.0060, -1.2141, -1.5595, -0.7291]])

# [0, 1]의 연속균등분포에서 추출한 난수로 Tensor 변환하기

c = torch.randn_like(tensor)

 

지정된 범위에서 일정 간격을 가진 Tensor의 생성

#지정된 범위에서 일정 간격을 가진 Tensor의 생성

a = torch.arange(start = 0, end=10, step = 2)

# 출력값
# tensor([0, 2, 4, 6, 8])
# 10은 포함하지 않음.
# a.dtype = torch.int64

a = torch.arange(start = 0, end=10, step = 0.5)
# 출력값
# tensor([0.0000, 0.5000, 1.0000, 1.5000, 2.0000, 2.5000, 3.0000, 3.5000, 4.0000,
#        4.5000, 5.0000, 5.5000, 6.0000, 6.5000, 7.0000, 7.5000, 8.0000, 8.5000,
#        9.0000, 9.5000])
# 
# a.dtype = torch.float32
# 정수는 long형으로 부동소수는 float로 변환된다.

 

초기화되지 않은 Tensor의 생성

# 초기화되지 않은 Tensor의 생성
a = torch.empty(5)

# 출력값
# tensor([ 2.1915e-19,  4.3408e-41, -8.6762e-14,  3.2926e-41,  0.0000e+00])

# tensor을 특정한 수로 채우기
a.fill_(10)

# 출력값
# tensor([10., 10., 10., 10., 10.])

 

empty함수를 사용하면

1. Tensor를 빠르게 생성이 가능하다.

2. 메모리 오버헤드를 감소시킬 수 있다.

3. 효율적인 리소스(연산, 메모) 사용

 

Numpy를 이용하여 Tensor 생성

# Numpy를 이용하여 Tensor 생성

a = torch.from_Numpy(np)

 

CPU Tensor 생성

#정수형 CPU Tensor 생성
a = torch.IntTensor([1,2,3,4,5])

#실수형 CPU Tensor 생성
a = torch.FloatTensor([1,2,3,4,5])

ByteTensor, DoubleTensro, Longtensor 등 다양한 type을 지원한다.

 

Tensor의 복제

# Tensor의 복제
y = x.clone()
z = x.detach()

# detach의 경우 clone과 달리 계산그래프에서 분리한다.

 

clone(): 데이터와 그래디언트 추적을 포함한 새로운 Tensor를 생성한다.

detach(): 데이터만 공유하며, 그래디언트 추적을 제외한 새로운 Tensor를 생성한다.

 

CUDA Tensor의 생성

# CUDA Tensor의 생성

a = torch.tensor([1,2,3,4,5]).cuda()
a = torch.tensor([1,2,3,4,5]).to('cuda')

# CUDA Tensor을 Cpu Tensor로 변환

a.cpu()
a.to(device ='cpu')

 

 

Tensor Indexing, Slicing

https://pytorch.org/cppdocs/notes/tensor_indexing.html

 

Tensor Indexing API — PyTorch main documentation

Tensor Indexing API Indexing a tensor in the PyTorch C++ API works very similar to the Python API. All index types such as None / ... / integer / boolean / slice / tensor are available in the C++ API, making translation from Python indexing code to C++ ver

pytorch.org

 

1차원 Tensor의 Indeing, Slicing

 

Index는 0부터 시작하며, 뒤쪽에서부터 순서를 셀때는 -1부터 시작한다

 

print('a[1:4] = ', a[1:4])
print('a[-5:-2] = ', a[-5:-2])

print('a[:4] = ', a[:4])
print('a[:-2] = ', a[:-2])

print('a[1:] = ', a[1:])
print('a[-5:] = ', a[-5:])


print('a[:] = ', a[0:])

print('a[::2] = ', a[::2])

 

tensor[a:b:c] => a부터 b까지 c만큼의 stride로 subTensor를 생성한다.

 

2차원 Tensor의 Indeing, Slicing

b = torch.tensor([[10, 20, 30],
                  [40, 50, 60]])

print('b[1, 2] = ', b[1, 2])
print('b[-1, -1] = ', b[-1, -1])

 

print('b[1, :] = ', b[1, :])
print('b[-1, :] = ', b[-1, :])

print('b[:, 1:] = ', b[:, 1:])
print('b[:, -2:] = ', b[:, -2:])


tensor[a:b:c,a:b:c] => ',' 를 사용하여 행과 열을 표현한다.


Slicing은 새로운 Tensor을 만드는것이 아닌 view를 만드는것이기 때문에 연속적이지 않을 수 있다.

Slicing을 한 Tensor을 변경하면 원본 값에도 영향을 미친다.

 

 

Tensor의 모양 변경

 

view() : Tensor의 메모리가 연속적으로 할당된 경우에만 사용이 가능하다

=> is_contiguous()로 연속성 판단.

a = torch.tensor([[10, 20, 30],
                  [40, 50, 60]])

print(a.is_contiguous())

b = a[:,1:]

print(b.is_contiguous())

b = b.contiguous()
print(b.is_contiguous())

연속적이지 않을경우 contiguous()함수로 연속적으로 만들어준다.

=> contiguous함수가 view였던 것을 새로운 Tensor을 생성하여 재배치한다.

=> 이 경우 reshape과 큰 차이가 없다.

 

view()

a = torch.arange(20)
print(a)
a.size()

a.view(4,5)
a.view(4,-1)
a.view(-1,5)

a.view(2,2,5)
a.view(-1,2,5)
a.view(2,-1,5)
a.view(2,2,-1)

 

flatten()

a = torch.randn(3,2)
print(a)

a_modified = a.flatten()
print(a_modified)
a_modified = torch.flatten(a)
print(a_modified)

a = torch.randn(3,2,3)

a_modified = torch.flatten(a,0)
print(a_modified)

#(3,6)으로 Flatten
a_modified = torch.flatten(a,1)
print(a_modified)
print(a_modified.size())

#(6,3)으로 Flatten
a_modified = torch.flatten(a,0,1)
print(a_modified)
print(a_modified.size())

flatten(Tensor,a,b) => Tensor을 a번째 차원에서부터 b번째 차원까지 평탄화를 진행한다.

 

reshape()

a = torch.arange(20)
print(a)
print(a.size())

a= a.reshape(4,5)
print(a)

a= a.reshape(4,-1)
print(a)

a= a.reshape(-1,5)
print(a)

a= a.reshape(2,2,5)
print(a)

a= a.reshape(-1,2,5)
print(a)

a= a.reshape(2,-1,5)
print(a)

a= a.reshape(2,2,-1)
print(a)

 

reshape() vs view()

reshape은 Tensor의 형태를 변경할 수 있으며, 연속적이지 않은 데이터에 대해서도 새로운 Tensor를 생성할 수 있다.

view는 Tensor의 형태를 변경하며, 원본 Tensor와 같은 연속적인 메모리 블록을 참조하는 새로운 Tensor를 생성다. 연속적인 메모리 블록이 필요하다.

 

transpose()

Tensor의 특정한 두 축을 바꾸는 Method이다.

a = torch.randn(3,4)
print('a = ', a)
print(a.shape)

a = a.transpose(0, 1)
print('a = ', a)
print(a.shape)

 

a = torch.randn(3,4,7)
print('a = ', a)
print(a.shape)

a = a.transpose(1, 2)
print('a = ', a)
print(a.shape)

 

transpose(a,b) => a축과 b축을 바꾼다.

squeeze()

squeeze() 메서드는 Tensor의 차원 중 크기가 1인 차원을 제거하는 데 사용된다.

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

print(a)
print(a.shape)
print('\n')

b = a.squeeze()
print(b)
print(b.shape)
print('\n')


c = a.squeeze(dim=0)
print(c)
print(c.shape)
print('\n')

d = a.squeeze(dim=2)
print(d)
print(d.shape)
print('\n')

unsqueeze()

"함수 시그니처"

torch.unsqueeze(input, dim)

# input: 차원을 추가할 원본 Tensor입니다.
# dim: 추가할 차원의 위치를 지정하는 정수입니다. 이 위치에 새로운 차원이 삽입됩니다.


"Method 시그니처"

Tensor.unsqueeze(dim)

# dim: 추가할 차원의 위치를 지정하는 정수입니다. 이 위치에 새로운 차원이 삽입됩니다.

unsqueeze(dim) 메서드는 Tensor의 지정된 위치 dim에 크기가 1인 새로운 차원을 추가한다.

a = torch.tensor([1, 2, 3, 4])

print(a)
print(a.shape)
print('\n')


b = a.unsqueeze(dim=0)
print(b)
print(b.shape)
print('\n')


c = a.unsqueeze(dim=1)
print(c)
print(c.shape)
print('\n')

d = a.unsqueeze(dim=0).unsqueeze(dim=0)
print(d)
print(d.shape)
print('\n')

stack()

"함수 시그니처"

torch.stack(tensors, dim=0, out=None)

# tensors: Tensor들의 시퀀스(리스트 또는 튜플). 모든 Tensor는 동일한 크기와 차원을 가져야 합니다.
# dim: 새로 추가할 차원의 위치를 지정하는 정수. 기본값은 0입니다.
# out: 선택적 매개변수로, 결과를 저장할 Tensor입니다. 기본값은 None입니다.

stack() 함수는 여러 Tensor를 새로운 차원에 따라 쌓아 올려 하나의 Tensor로 만드는 함수이다.

red_channel = torch.tensor([[255, 0, 0], [255, 0, 0]], dtype=torch.uint8)
green_channel = torch.tensor([[0, 255, 0], [0, 255, 0]], dtype=torch.uint8)
blue_channel = torch.tensor([[0, 0, 255], [0, 0, 255]], dtype=torch.uint8)

print("Red Channel:")
print(red_channel)

print("\nGreen Channel:")
print(green_channel)

print("\nBlue Channel:")
print(blue_channel)

rgb_image = torch.stack([red_channel, green_channel, blue_channel], dim=0)

print("\nStacked RGB Image:")
print(rgb_image)
print("Shape of RGB Image:", rgb_image.shape)

rgb_image = torch.stack([red_channel, green_channel, blue_channel], dim=1)

print("\nStacked RGB Image:")
print(rgb_image)
print("Shape of RGB Image:", rgb_image.shape)

rgb_image = torch.stack([red_channel, green_channel, blue_channel], dim=2)

print("\nStacked RGB Image:")
print(rgb_image)
print("Shape of RGB Image:", rgb_image.shape)

 

cat()

"함수 시그니처"

torch.cat(tensors, dim=0, out=None)

# tensors: 연결할 Tensor들의 시퀀스(리스트 또는 튜플).
# dim: 연결할 차원(축). 기본값은 0.
# out: 결과를 저장할 선택적인 Tensor (기본값은 None)

cat() 함수는 여러 Tensor를 주어진 차원에 따라 연결(concatenate)하여 하나의 Tensor로 만드는 함수이다.

stack()과 다르게 차원을 추가하지 않는다.

 

a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])

# dim=0 (첫 번째 차원)으로 연결
result = torch.cat((a, b), dim=0)

print("Tensor 'a':")
print(a)
print("Tensor 'b':")
print(b)
print("Concatenated Tensor 'result':")
print(result)

 

expand()

 

# Method 시그니처
Tensor.expand(*sizes)

# input: 크기를 확장할 원본 Tensor입니다.
# sizes: 확장할 목표 크기를 지정하는 정수 또는 정수 시퀀스입니다. 이 값들은 각 차원의 크기를 지정합니다.

 

expand() 는 PyTorch에서 Tensor의 크기를 확장하는 데 사용된다.

그러나 이 함수와 메서드는 unsqueeze와는 다르게, 기존 데이터를 복사하지 않고 Tensor의 view를 확장하여 새로운 차원에 대해 반복하는 방식으로 동작다.

 

a = torch.tensor([[1, 2, 3]])


# 차원을 확장하여 4x3 Tensor로 변경
b = a.expand(4, 3)

print("Tensor 'a':")
print(a)
print("Expanded Tensor 'b':")
print(b)
print("Shape of 'b':", b.shape)

 

repeat()

Tensor.repeat(*sizes)

# sizes: 각 차원에서 반복할 횟수를 지정하는 정수 또는 정수 시퀀스입니다. 이 값들은 새로운 Tensor의 각 차원에서 몇 번 반복할지를 정의합니다

torch.repeat() 함수는 Tensor의 내용을 반복하여 새로운 Tensor를 생성하는 데 사용된다.

expand()와 달리 view를 확장하는것이 아니라 새로운 Tensor을 만들어낸다.

a = torch.tensor([[1, 2], [3, 4]])

b = a.repeat(2, 3, 2)

print("Tensor 'a':")
print(a)
print("Shape of 'a':", a.shape)
print("Repeated Tensor 'b':")
print(b)
print("Shape of 'b':", b.shape)

 

 

'AI Tech' 카테고리의 다른 글

Linear Regression with Pytorch  (0) 2024.08.07
What is Pytorch(행렬곱)?  (0) 2024.08.07
What is Pytorch (유사도)?  (0) 2024.08.07
What is Pytroch(Ln Norm)?  (0) 2024.08.06
What is Pytroch (2)?  (0) 2024.08.06