파이토치 설치
https://he11owor1d.tistory.com/33
첫 번째 신경망
가정
- 나는 동영상 서비스 업체인 원더무비에서 일하고 있음
- 학습에 사용할 데이터셋은 1개 피처만을 갖는다.
- 이 피처는 원더무비 플랫폼에서 영화를 시청한 사용자의 평균 영화 관람 시간이다.
- 원더무비는 사용자의 다음 주 영화 관람 시간을 예측하고자 한다.
첫 번 째 신경망은 다음과 같은 블록으로 구성된다.
- 데이터 준비: 입출력 데이터를 담는 텐서를 생성한다.
- 학습 파라미터 생성: get_weights 함수는 임의의 수로 채워진 텐서를 제공한다. 신경망은 이 Tensor를 최적화함으로써 영화 관람 시간 예측 문제를 해결한다.
- 네트워크 모델: simple_network 함수는 입력 데이터에 선현 규칙을 적용한 출력을 만든다.
*선형 규칙: 입력 데이터에 가중치를 곱한 후 Bias항을 추가한 모델 (y = Wx + b) - 오차: loss_fn 함수는 모델 정확도에 대한 정보를 제공한다.
- 옵티마이저: optimizer 함수는 초기에 생성된 임의의 가중치를 조정해 모델이 더욱 정확하게 목푯값을 계산하도록 돕는다.
데이터 준비
- 파이토치는 데이터를 추상화하는 Tensor와 Variable을 제공한다.
- Tensor는 Numpy와 유사한 클래스이다.
- Tensor와 Numpy는 GPU에서도 동작하며, GPU에서 더 향상된 성능을 제공한다.
- 데이터를 Tensor로 표현하면 특정 연산에서 성능이 향상된다. 그리고 데이터가 Tensor로 표현될 경우에만, 머신 러닝 알고리즘은 데이터의 형태를 이해할 수 있다.
- Tensor 클래스는 파이썬 배열과 유사하다.
스칼라
- 0차원 텐서
- 1개 요소만을 갖는 텐서
x = torch.rand(10)
x.size()
벡터
- 1차원 텐서.
- 요소의 배열
- 예를 들어, 지난주의 평균 온도를 벡터에 저장할 수 있다.
temp = torch.FloatTensor([23,24,24.5,26,27.2,23.0])
temp.size()
행렬
- 2차원 텐서
- 다음 데이터 셋은 예시로, 샘플의 갯수는 506개이고 각 샘플은 13개의 피처로 표현된다. 따라서 506*13 사이즈의 행렬
from sklearn.datasets import load_boston
boston = load_boston()
print(boston.data.shape)
boston.feature_names
boston_tensor = torch.from_numpy(boston.data)
boston_tensor.size()
boston_tensor[:2]
boston_tensor[:10,:5]
3차원 텐서
- 3차원 텐서
- 여러 행렬을 결합해 한 개의 3차원 텐서를 만들 수 있다.
- 이미지 같은 데이터를 표현할 때 사용된다.
from PIL import Image
panda = np.array(Image.open('../images/B09301_03_12.jpg').resize((224,224)))
panda_tensor = torch.from_numpy(panda)
panda_tensor.size()
plt.imshow(panda);
텐서 슬라이싱
Tensor 객체의 가장 일반적인 작업 중 하나는 Tensor 객체를 잘라 작은 Tensor 객체를 만드는 것이다.
1차원 Tensor 객체인 sales에서 첫 번째 5개 요소를 선택하기
sales = torch.FloatTensor([1000.0,323.2,333.4,444.5,1000.0,323.2,333.4,444.5])
sales[:5]
# out
# tensor([1000.0000, 323.2000, 333.4000, 444.5000, 1000.0000])
sales[:-5]
# out
# tensor([1000.0000, 323.2000, 333.4000])
판다 이미지를 잘라보기
plt.imshow(panda_tensor[:,:,0].numpy());
plt.imshow(panda_tensor[25:175,60:130,0].numpy());
4차원 텐서
- 4차원 텐서
- 대표적인 예는 이미지 배치: 한 번에 한 개 이미지를 처리하는 방식보다 여러 이미지를 배치로 묶어 처리하는게 더 효율적이다.
*배치 크기를 결정하는 것: 여러 가지 요소에 영향을 받기 때문에 배치 크기를 결정하는 것은 간단하지 않다. 일반적으로 가장 중요한 제약은 GPU 메모리 크기. 일반적으로 사용되는 배치 크기는 16, 32, 64 - 예를 들어 244*244 사이즈의 고양이 이미지를 배치 크기 64로 잡으면 64*244*244*3를 메모리에 로딩할 수 있다.
5차원 텐서
- 5차원 텐서
- 대표적인 예는 동영상 데이터: 총 30개의 프레임을 갖는 244*244 사이즈 30초 동영상 데이터는 1*30*244*244*3 인 텐서로 표현되고, 이런 동영상의 배치는 형상이 32*30*244*244*3인 텐서로 표현할 수 있다.
GPU 지원 Tensor
- 텐서 형태의 데이터를 가지고 일반적으로 수행하는 연산은 덧셈, 뺄셈, 곱셈, 내적과 행렬 곱이다.
- 파이토치는 cuda()라는 함수를 제공해 CPU에서 동작하는 텐서 객체를 복사해 GPU에서 동작하도록 만들 수 있다.
Variable
- 일반적으로 딥러닝 알고리즘은 계산 그래프로 표현된다
- Variable 클래스의 컴포넌트 구성: data, grad, creator
예제
from torch.autograd import Variable
import torch
x = Variable(torch.ones(2, 2), requires_grad=True)
y = x.mean()
y.backward()
print(x.grad)
# out: tensor([[0.2500, 0.2500],
# [0.2500, 0.2500]])
print(x.grad_fn)
# out: none
print(x.data)
# out: tensor([[1., 1.],
# [1., 1.]])
print(y.grad_fn)
# out: <MeanBackward1 at 0x1a2035d7b8>
신경망에 사용할 데이터 생성하기
def get_data():
train_X = np.asarray([3.3,4.4,5.5,6.71,6.93,4.168,9.779,6.182,7.59,2.167,
7.042,10.791,5.313,7.997,5.654,9.27,3.1])
train_Y = np.asarray([1.7,2.76,2.09,3.19,1.694,1.573,3.366,2.596,2.53,1.221,
2.827,3.465,1.65,2.904,2.42,2.94,1.3])
dtype = torch.FloatTensor
X = Variable(torch.from_numpy(train_X).type(dtype),requires_grad=False).view(17,1)
y = Variable(torch.from_numpy(train_Y).type(dtype),requires_grad=False)
return X,y
- 예제로 사용하는 신경망에서 학습 파라미터는 w와 b이고, 고정 파라미터는 x와 y이다.
- 위의 get_data() 함수로 변수 x와 y를 만든다.
- 변수 x와 y의 크기는 각각 (17, 1)과 (17)이다.
학습 파라미터 생성
def get_weights():
w = Variable(torch.randn(1),requires_grad = True)
b = Variable(torch.randn(1),requires_grad=True)
return w,b
신경망 모델
- 전통적인 프로그래밍에서는 함수 입력을 처리해 의도한 값을 반환하는 로직을 개발자가 직접 구현하는 반변, 딥러닝과 머신 러닝에서는 이 로직을 학습시킨다.
- 첫 신경망 예제의 입출력은 선형 관계임을 가정한다.
- 선형 관계는 y = wx + b로 표현되고, 여기서 w와 b는 학습 파라미터이다.
- 앞으로 개발할 신경망은 w와 b값을 학습해, wx + b의 결과가 실제 y 값에 근접하도록 만들 것이다.
네트워크 구현
def simple_network(x):
y_pred = torch.matmul(x,w)+b
return y_pred
- w와 x의 행렬 곱을 계산하고, 그 결과에 편향 b를 합한다. 이 값이 예측값 y이다.
- 파이토치가 제공하는 고수준 추상화 컴포넌트를 '레이어'라고 하며, 이 컴포넌트는 torch.nn에 포함되어 신경망에서 사용하는 대부분의 일반 기술과 연관된 기본적인 초기화 기능과 연산을 대부분 처리한다.
앞에서 구현한 모델은 torch.nn 레이어를 사용해 다음과 같이 표현할 수 있다.
import torch.nn as nn
f = nn.Linear(17,1) # 훨씬 단순해짐
오차 함수
def loss_fn(y,y_pred):
loss = (y_pred-y).pow(2).sum()
for param in [w,b]:
if not param.grad is None: param.grad.data.zero_()
loss.backward()
return loss.data[0]
- 처음에 파라미터 w와 b는 임의의 값으로 초기화되기 때문에 모델의 결과인 y_pred와 실제 y 값의 차이는 상당히 클 것이다.
- 현재 회귀 문제를 다루고 있으므로 SSE라는 오차 함수를 사용한다: 예측값 y와 실제값 y 사이의 차이를 구하고, 그 결과를 제곱한다.
- backward 메서드는 학습 마라미터 w와 b의 변화 정도를 기울기로 계산한다.
- 오차 함수를 한 번 이상 호출해야 한다면, grad.data.zero_()를 호출해 앞에서 계산했던 기울기를 먼저 제거해야 한다. 처음으로 backward 함수를 호출하면 기울기가 None이므로, 예외처리를 해준다.
- 이 프로세스는 한 에폭(전체 데이터셋)에 대해 반복된다.
신경망 최적화
- 대부분 딥러닝 실제 사레에서 전체 데이터셋은 작은 데이터셋으로 분할돼 반복적으로 처리되며, 이 반복 처리별로 최적화가 수행된다.
- 오차가 계산되면 오차를 줄이기 위해 계산된 기울기 값을 이용해 학습 파라미터를 최적화한다. 아래는 최적한 과정을 구현한 코드이다.
def optimize(learning_rate):
w.data -= learning_rate * w.grad.data
b.data -= learning_rate * b.grad.data
- learning rate, 학습률은 대표적인 하이퍼 파라미터로, 학습 파라미터의 값을 조정할 때 사용하는 기울기의 적용 비율이다. 여기서 기울기는 각 학습 파라미터를 조정하는 크기와 방향을 나타낸다.
- Adam, RmsProp, SGD와 같은 다양한 옵티마이저가 이미 파이토치에 구현되어 있다. 이 옵티마이저는 torch, optim 패키지에서 이용할 수 있다.
데이터 로딩
- 파이토치는 멀티 스레딩을 통한 데이터 병렬화, 데이터 증식 및 배치 처리와 같은 여러 복잡한 작업을 추상화하는 여러 유틸리티 클래스를 제공한다.
- 아래에서는 유틸리티 클래스의 핵심인 dataset 클래스와 DataLoader 클래스를 살펴본다.
데이터셋 클래스
- 사용자 정의 데이터셋 클래스를 만들기 위해서는 Dataset 클래스를 상속하고, __len__(self)와 __getitem__(self, idx) 메서드를 구현해야한다.
from torch.utils.data import Dataset
class DogsAndCatsDataset(Dataset):
def __init__(self,):
pass
def __len__(self):
pass
def __getitem__(self,idx):
pass
- __init__ 메서드: 사용자 정의 데이터셋 클래스에 테이블 인덱스 읽기와 이미지 파일명 읽기와 같은 초기화 작업이 필요하다면, 이러한 로직인 __init__ 메서드에 구현한다.
- __len__ 메서드: 데이터셋의 최대 요소 수를 반환한다.
- __getitem__ 메서드: 데이터셋에 idx번째 요소를 반환한다.
DogsAndCatsDataset 클래스는 다음과 같이 구현될 수 있다.
class DogsAndCatsDataset(Dataset):
def __init__(self,root_dir,size=(224,224)):
self.files = glob(root_dir)
self.size = size
def __len__(self):
return len(self.files)
def __getitem__(self,idx):
img = np.asarray(Image.open(self.files[idx]).resize(self.size))
label = self.files[idx].split('/')[-2]
return img,label
위와 같이 DogsAndCatsDataset 클래스를 생성했다면, 다음과 같이 객체를 생성하고, 이 객체를 기반으로 반복을 수행할 수 있다.
for image, label in dogsdset:
# 데이터셋에 딥러닝 적용
DataLoader 클래스
- DataLoader 클래스는 파이토치의 utils 모듈에 위치한다.
- 이 객체는 SequentialSampler, RandomSampler와 같은 다양한 샘플러와 함께 데이터셋 객체를 결합해 만든다.
- DataLoader 객체는 단일 프로세스 반복자 또는 다중 프로세스 반복자를 위한 배치 이미지를 제공한다.
개와 고양이 데이터셋의 DataLoader 예제 코드
from torch.utils.data import Dataset, DataLoader
#dataloader = DataLoader(DogsAndCatsDataset,batch_size=32,num_workers=2)
#for imgs , labels in dataloader:
#학습 데이터셋에 딥러닝 네트워크 적용
# pass
- imgs의 텐서 크기는 (32, 224, 224, 3)이다. 여기서 32는 배치 크기를 의미함.
요약
2장에서는
- 파이토치가 제공하는 다양한 데이터 구조와 연산
- 파이토치의 기본 블록으로 사용되는 주요 컴포넌트 구현
- 알고리즘에 사용될 텐서 객체 구현
3장에서는
- 신경망과 딥러닝 알고리즘의 동작
- 오차 함수와 최적화를 구축하기 위해 파이토치가 제공하는 다양한 내장 모듈
- 실제 데이터셋에 파이토치가 제공하는 내장 모듈 적용
'IT 도서 리뷰' 카테고리의 다른 글
PyTorch로 시작하는 딥러닝 - CH7 생성적 신경망 (0) | 2021.11.14 |
---|---|
PyTorch로 시작하는 딥러닝 - CH6 시퀀스 데이터와 텍스트 딥러닝 (0) | 2021.11.12 |
PyTorch로 시작하는 딥러닝 - CH5 컴퓨터 비전 딥러닝 (0) | 2021.11.11 |
PyTorch로 시작하는 딥러닝 - CH4 머신 러닝 입문 (0) | 2021.11.11 |
Pytorch로 시작하는 딥러닝 (0) | 2021.10.26 |