본 포스트는 처음부터 딥 러닝 3이것은 당신이 배우고 본 것에 대한 개인 연구를 위해 작성된 게시물이라는 것을 기반으로 합니다.
자세한 내용은 교재 구매를 적극 권장합니다.
이 단계에서는 이전 단계에서 사용된 Dataset 클래스를 자세히 살펴보겠습니다.
사용자가 실제로 사용하는 데이터셋은 베이스 클래스를 상속받아 구현됩니다.
먼저 기본 클래스 코드를 살펴보겠습니다.
__getitem__ 및 __len__ 메서드는 Dataset 클래스에서 중요합니다.
len 함수를 사용할 때 __len__ 메소드가 호출되며, __getitem__ 메소드는 지정된 인덱스의 데이터를 얻기 위해 사용됩니다.
기본적으로 딥러닝 학습에는 데이터와 레이블이 필요하므로 생성자에서 지정해줍시다.
또한 데이터 세트 사전 처리 중에 변환을 사용하십시오. 많은 경우 학습 전에 데이터에서 일부 값을 제거하거나 수평 반전과 같이 인위적으로 데이터 수를 늘립니다.
이러한 전처리 기술에 대처하기 위해 변환 함수가 추가됩니다.
변환이 요소로 존재하지 않으면 원본 데이터가 람다 x: x를 통해 변경되지 않은 상태로 반환됩니다.
class Dataset:
def __init__(self, train=True, transform=None, target_transform=None):
self.train = train
self.transform = transform
self.target_transform = target_transform
if self.transform is None:
self.transform = lambda x: x
if self.target_transform is None:
self.target_transform = lambda x: x
self.data = None
self.label = None
self.prepare()
def __getitem__(self, index):
assert np.isscalar(index)
if self.label is None:
return self.transform(self.data(index)), None
else:
return self.transform(self.data(index)),\
self.target_transform(self.label(index))
def __len__(self):
return len(self.data)
def prepare(self):
pass
이제 위의 Dataset 클래스를 상속받아 나선형 데이터셋을 구현해 보겠습니다.
사실 핵심 데이터 구조는 get_spiral 메소드에 구현되어 있는데, 이런 방식으로 Dataset 클래스를 상속받아 구현한다는 것만 알 수 있습니다.
class Spiral(Dataset):
def prepare(self):
self.data, self.label = get_spiral(self.train)
데이터 세트가 매우 크면 다른 접근 방식을 사용해야 합니다.
예를 들어, 데이터 디렉토리와 레이블 디렉토리는 각각 100만 개의 데이터를 저장하고 있으며, BigData 클래스를 초기화할 때 데이터를 읽는 것이 아니라 데이터에 액세스할 때 데이터를 읽습니다.
np.load는 53단계에 설명이 있다고 합니다.
class BigData(Dataset):
def __getitem__(index):
x = np.load('data/{}.npy'.format(index))
t = np.load('label/{}.npy'.format(index))
return x, t
def __len__():
return 1000000
이제 학습으로 넘어 갑시다.
이전과 다른 점은 Dataset을 불러올 때 클래스를 사용한다는 것입니다.
또한 Spiral 클래스에서 데이터의 미니 배치를 가져오는 코드가 다릅니다.
따로 살펴보자.
import math
import numpy as np
import dezero
import dezero.functions as F
from dezero import optimizers
from dezero.models import MLP
max_epoch = 300
batch_size = 30
hidden_size = 10
lr = 1.0
train_set = dezero.datasets.Spiral(train=True)
model = MLP((hidden_size, 3))
optimizer = optimizers.SGD(lr).setup(model)
data_size = len(train_set)
max_iters = math.ceil(data_size / batch_size)
for epoch in range(max_epoch):
index = np.random.permutation(data_size)
sum_loss = 0
for i in range(max_iters):
batch_index = index(i * batch_size:(i + 1) * batch_size)
batch = (train_set(i) for i in batch_index)
batch_x = np.array((example(0) for example in batch))
batch_t = np.array((example(1) for example in batch))
y = model(batch_x)
model.cleargrads()
loss = F.softmax_cross_entropy(y, batch_t)
loss.backward()
optimizer.update()
sum_loss += float(loss.data) * len(batch_t)
avg_loss = sum_loss / data_size
print('epoch %d, loss %.2f' % (epoch + 1, avg_loss))
먼저 인덱스를 지정하여 미니 배치를 검색합니다.
다음으로 인덱스에 따라 여러 데이터를 목록으로 일괄 저장합니다.
다음으로 batch_x 및 batch_t를 ndarray 인스턴스로 변환하고 할당합니다.
이 프로세스를 반복하여 미니 배치를 신경망에 공급합니다.
train_set = dezero.datasets.Spiral()
batch_index = (0, 1, 2) # 0번째에서 2번째까지의 데이터 꺼내기
batch = (train_set(i) for i in batch_index)
# batch = ((data_0, label_0), (data_1, label_1), (data_2, label_2))
batch_x = np.array((example(0) for example in batch))
batch_t = np.array((example(1) for example in batch))
print(x.shape)
print(t.shape)
(3, 2)
(삼,)
위에서 소개한 데이터 전처리 변환은 dezero/transform.py에서 여러 변환 프로세스를 준비한다고 합니다.
책에는 명시되어 있지 않습니다.
관심 있으신 분들은 참고만 하시면 됩니다.