* 원티드 프리온보딩 AI/ML 코스에서 학습한 것을 정리한 내용입니다.
Pytorch tutorial(1)
pytorch 사용 이유
더보기
딥러닝 분야에서 파이토치를 많이 사용하는데, 그 이유는 아래와 같다.
- 간단한 모델 학습
- 그래프를 쌓고, 실행하고, 역전파를 통해 학습하는 과정들이 파이토치에서는 매우 간편하다.
- 간편한 병렬 학습 방법
- DistributedDataPararell의 사용
- tensor 구조의 데이터를 다룬다.
- np.ndarray처럼 n차원의 array이지만, 추가적으로 tensor 그래프와 미분값을 가지고 있다는 차이점이 있다.
- 신경망 층을 쌓으면, 그 신경망 층 안에 있는 값들이 모두 tensor 형태로 저장되어 있고,
- backward()라는 메소드를 수행함으로써 모든 그래프에 대한 미분값이 자동으로 계산된다. (Autograd)
- tensor를 GPU 메모리에 올려서 사용 가능하다.
Tensor 생성
1. 기존 list 또는 np.ndarray를 tensor로 변환
x = [[1],[2]]
print(f"x data type: {type(x)}")
# list to tensor
x_tensor = torch.tensor(x)
print(f"x_tensor data type: {type(x_tensor)}")
# list to numpy array
x_np = np.array(x)
print(f"x_np data type: {type(x_np)}")
# numpy array to tensor
x_tensor = torch.from_numpy(x_np)
print(f"x_tensor data type: {type(x_tensor)}")
2. 특정 shape의 tensor 생성
ex) shape = (2, 3, )인 2차원의 tensor 생성
2-1. 난수 생성해서 tensor 생성
- torch.rand(shape) : [0,1) 범위의 균등 분포에서 임의의 값을 추출해서 shape을 채운다.

- torch.randn(shape) : 정규 분포에서 임의의 값 추출해서 shape을 채운다.

2-2. Zero나 One을 채우는 방법
- torch.zeros(shape)
- torch.ones(shape)
2-3. 특정 범위의 랜덤한 정수로 채우는 방법
- torch.randint(low=0, high, size) : size(tuple)에 맞춰 [low, high) 범위의 int값을 임의 추출해 tensor를 생성한다.
>>> torch.randint(3, 10, (2, 2)) # type of 'size' is tuple
tensor([[4, 5],
[6, 7]])
2-4. 1차원 tensor를 생성하는 경우
- torch.arange(start=0, end, step=1) : start ~ end 범위 안에 있는 값들로 일정한 step 간격을 가진 1차원의 텐서 데이터를 만든다.
>>> torch.arange(1*2*3) = torch.arange(6)
tensor([0, 1, 2, 3, 4, 5]) # default: start=0, step=1
>>> torch.arange(1, 2.5, 0.5)
tensor([ 1.0000, 1.5000, 2.0000])
- tensor.view(shape) : 원소의 수를 유지하면서 tensor의 shape 변경
- ex) 0~5까지의 value를 가진 tensor를 특정 shape의 tensor로 만들어주고 싶을 때
>>> x = torch.arange(1*2*3) = tensor.arange(6)
>>> print(x)
tensor([0, 1, 2, 3, 4, 5]) # torch.Size([6])
# tensor shape 변경
>>> x.view(1,2,3)
tensor([[0,1,2],[3,4,5]])
Tensor 정보
Rank
- dimension 개수
- Rank = 1(선), Rank = 2(평면), Rank = 3(공간), ...
- tensor의 Rank 구하기 : len(tensor.shape)
Shape
- 각 dimension의 value 개수
- 행(row)의 수, 열(column)의 수 , 높이(층)의 수
- axis=0의 수, axis=1의 수, axis=2의 수
- tensor의 Shape 구하기 : tensor.shape
Axis
- 특정 dimension 지칭 (dimension을 가리키는 index 같은 개념)
- 방향이 중요하다. 3차원 tensor 연산시, 어떤 방향으로 더하는가에 따라 결과가 달라지기 때문.
- axis=0으로 더할 것인지, axis=1로 더할 것인지.
- axis=0 ⇒ 행, 1차원
- axis=1 ⇒ 열, 2차원
- axis=2 ⇒ 공간, 3차원
Shape 변경
-1의 의미
- Case 1) x.view(-1, 2, 2)에서 -1 의 의미
- Size가 [4, 3, 2]인 3차원의 tensor인 경우 (총 value 수 : 24)
- axis = 1(두번째 axis, 열)는 3 → 2로,
- axis = 2는 2 → 2로, (변경 X)
- 이후, axis=0에 해당하는 dimension을 총 value 수는 유지하면서, 알아서 변화에 맞게 변경하라는 의미.
- Size가 [4, 3, 2]인 3차원의 tensor인 경우 (총 value 수 : 24)
- Case 2) xx = x.view(4, 6, -1)일 때, xx.shape
# 예시 tensor 생성
>>> x = torch.rand(4,3,2)
# case 1
>>> x.view(-1, 2, 2).shape
torch.Size([6, 2, 2]) # view에서 -1로 지정된 axis=0의 dimension은 shape 변경 이후에도 총 value 수를 유지하기 위해 6으로 변경됨
# case 2
>>> xx = x.view(4, 6, -1)
>>> xx.shape
torch.Size([4, 6, 1])
Rank 변경
- squeeze() : 필요 없는 차원(dimension)을 날려라
- ex) xx.shape ⇒ torch.Size([4, 6, 1])
- ex) xx.squeeze().shape ⇒ torch.Size([4,6])
- unsqueeze() : 원하는 차원에 차원수 1을 추가해라
- ex) xxx = xx.squeeze() 일 때, xxx.unsqueeze(dim=-1).shape ⇒ torch.Size([4,6,1])
- 맨 뒤에 있는 dimension(dim=-1)에 1을 추가해줘.
data type 확인
- dtype
- ex) x.dtype ⇒ torch.float32
Tensor가 올라가있는 device(cpu/gpu) 확인
- device
- ex) x.device ⇒ 'cpu' or 'gpu'
Tensor 인덱싱
- tensor 인덱싱으로 특정 차원의 특정 행, 열의 값을 변경할 수 있다.
- ex) x = torch.rand(2, 3)인 경우
- 1st row : {x[0]}
- 1st column : {x[:,0]}
- last column : {x[:,-1]}
- 브로드캐스팅(broadcasting)
- ex) x[:-1] = 0 일 때, last column에 0을 broadcasting 한다.
- shape이 맞지 않아도, 어떤 값을 assign(할당) 하겠다는 의미
- cf. 할당하거나, 대소비교같은 연산을 하는 경우에는 반드시 tensor의 shape이 동일해야한다.
- 그러나 스칼라 값이 한 번 나올 땐,
- tensor의 shape이 동일하지 않더라도
- 자동적으로 왼쪽에 있는 텐서(x)와 동일한 shape으로 생각하고 연산을 하게 되는데,
- 이것을 broadcasting이라고 한다.
- 대소비교 연산
- 결과값이 True/False로 나온다
- ex) x > 0.5 ⇒ tensor([[True, False, False], [True, True, False]])
- 대소비교 연산을 활용한 마스킹
- tensor의 value 중 0이 넘지 않는 value는
- tensor를 다시 곱해도 0이 되도록(=마스킹 처리) 0으로 표시한다.
- ex) x * (x > 0.5) ⇒ tensor([[0.9..., 0.0000, 0.0000], [0.7, 0.5, 0.0000]])
- 결과적으로 마스킹 조건(x > 0.5)를 충족시키는 value만 남게 된다.
- tensor의 value 중 0이 넘지 않는 value는
- 특정 인덱스 얻기
- nonzero()
- ex) (x > 0.5).nonzero()
- 대소비교 연산 후, True인 value의 인덱스(위치 정보)를 반환한다.
- 이 때, as_tuple=True를 통해 각 값을 axis0, axis1 변수에 할당한다.
- 이후 for문을 사용해 Tensor x의 value 중 True인 value만 확인한다.
- nonzero()

Tensor 연산
덧셈
>>> x = torch.ones(3, 2, 4)
>>> x.shape
torch.Size([3, 2, 4])
- 파라미터 dim : 특정 차원의 value를 하나로 합치겠다고 지정해준다. 해당 차원의 shape이 1로 변경된다.
- ex) x.sum(dim=0, keepdim=True)
- dim=0 : 1차원에 대한 연산
- keepdim=True : size가 1인 dimension이라도 유지한다.
- output : [1, 2, 4]
- ex) x.sum(dim=0, keepdim = False)
- keepdim = False : size가 1인 dimension을 squeeze한다. (=날려버린다.)
- output : [2, 4]
- ex) x.sum(dim=0, keepdim=True)
곱셈
>>> shape = (2,1)
>>> x = torch.randint(10,shape)
>>> y = torch.randint(10,shape)
x : tensor([[9], [4]])
y : tensor([[8], [6]])
- torch.matmul(x, y.T)
- matmul : 행렬 곱 (matrix multiplication)
- y.T : 2*1 행렬 y의 Transpose 행렬
- 2*1 행렬은 같은 2*1 행렬과 곱할 수 없기 때문에, 행렬 y를 1*2의 역행렬로 변형
- matmul은 @로 나타낼 수 있다. ⇒ x@y.T
- torch.mul(x,y)
- mul : matmul과 완전히 다르다. elment-wise 곱으로, 같은 위치에 있는 value끼리 곱해버리는 연산
- 따라서 행렬 y를 transpose 하지 않아도 된다.
- mul은 *로 나타낼 수 있다. ⇒ x*y
- Dot Product
- torch에서는 1D vector의 dot product만 지원한다.
- 따라서 output의 형태가 스칼라이다.
- 따라서 아래 세 연산은 모두 같은 결과를 내는 연산이다.
- torch.dot(x, y)
- x@y
- (x*y).sum()
Tensor 병합 및 분리
병합
- x = torch.randint(10, (1,2)) ⇒ tensor([[9, 8]])
- x_concat = torch.cat([x, x, x], dim=1)
- [x, x, x] : 3개의 x vector를 dim=1 즉, 2차원(axis=1, 열)의 value가 늘어나게끔 붙이겠다는 의미
- x_concat ⇒ [[9, 8, 9, 8, 9, 8]]
- x_concat.shape ⇒ torch.Size([1, 6])
Reference
'원티드 프리온보딩 AI•ML (NLP)' 카테고리의 다른 글
Week1-4. NLP의 Transfer Learning의 학습 방식 (0) | 2022.02.25 |
---|---|
Week1-3. NLG와 extractive summarization task (4) | 2022.02.23 |
Week1-2. NLU와 Semantic Textual Similarity (5) | 2022.02.22 |
NLP와 벤치마크 데이터셋 (0) | 2022.02.22 |
Week1-1. NLP Sub-Task 탐색 (3) | 2022.02.21 |