Fashion-MNIST에 대한 설명은 아래 링크로 대신하겠습니다.
Fashion-MNIST is a dataset of Zalando‘s article images—consisting of a training set of 60,000 examples and a test set of 10,000 examples. Each example is a 28×28 grayscale image, associated with a label from 10 classes. We intend Fashion-MNIST to serve as a direct drop-in replacement for the original MNIST dataset for benchmarking machine learning algorithms. It shares the same image size and structure of training and testing splits.

본 예제 코드는 데이터셋을 학습해서 입력되는 이미지가 어떤 분류에 속하는지를 예측해보는 것입니다. Fashion-MNIST 데이터셋을 벡터 공간에 표시하면 위와 같은 이미지로 분류할 수 있습니다.
이제 학습을 위해 해당 데이터셋을 다운로드합니다.
# Define a transform to normalize the data
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])
# Download and load the training data
train_loader = torch.utils.data.DataLoader(datasets.FashionMNIST('../F_MNIST_data/', download=True, train=True, transform=transform), batch_size=128, shuffle=True)
# Download and load the test data
test_loader = torch.utils.data.DataLoader(datasets.FashionMNIST('../F_MNIST_data/', download=True, train=False, transform=transform), batch_size=128, shuffle=True)
다운로드한 데이터가 어떤 이미지가 있는지 살펴보기 위해서 랜덤하게 몇개의 샘플을 추출해서 표시해보겠습니다. 해당 이미지들은 10개 [‘t-shirt’, ‘trouser’, ‘pullover’, ‘press’, ‘coat’, ‘sandal’, ‘shirt’, ‘sneaker’, ‘bag’, ‘ankleboot’]로 분류할 수 있는 패션 아이템들입니다.
x_train, y_train = next(iter(train_loader))
x_valid, y_valid = next(iter(test_loader))
fig, ax = plt.subplots(5,5)
fig.set_size_inches((20,14))
for i in range(5):
for j in range(5):
idx = numpy.random.randint(128)
ax[i][j].imshow(x_train[idx,0,:])
ax[i][j].set_xlabel(label[y_train[idx].item()])
ax[i][j].set_xticklabels([])
ax[i][j].set_yticklabels([])

학습을 위한 모델을 선언합니다. 이전 MNIST 데이터셋을 테스트했을 때와 같은 모델을 재활용했습니다.
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.convs = nn.Sequential(
nn.Conv2d(1, 10, kernel_size=3), # input_channel, output_channel, kernel_size
nn.ReLU(),
nn.BatchNorm2d(10),
nn.Conv2d(10, 20, kernel_size=3, stride=2),
nn.ReLU(),
nn.BatchNorm2d(20),
nn.Conv2d(20, 40, kernel_size=3, stride=2)
)
self.layers = nn.Sequential(
nn.Linear(40*5*5, 500),
nn.Dropout(p=0.2),
nn.ReLU(),
nn.BatchNorm1d(500),
nn.Linear(500,250),
nn.Linear(250,100),
nn.Dropout(p=0.2),
nn.ReLU(),
nn.BatchNorm1d(100),
nn.Linear(100,50),
nn.Linear(50, 10),
nn.Softmax(dim=-1)
)
def forward(self, x):
x = self.convs(x)
x = x.view(-1, 40*5*5)
return self.layers(x)
cnn = Net().to(DEVICE)
이전 MNIST 코드는 하나의 mini batch 데이터만 학습했다면 이번에는 전체 데이터를 대상으로 학습을 진행합니다. 많은 학습을 거친다면 모델의 정확도가 높아지겠지만 성능을 높이는 테스트가 아니기 때문에 최소한의 학습 epcohs만 수행합니다.
optimizer = optim.Adam(cnn.parameters())
criterion = nn.CrossEntropyLoss()
hist_loss = []
hist_accr = []
epochs = 30
for epoch in range(epochs):
for idx, (data, label) in enumerate(train_loader):
data, label = data.to(DEVICE), label.to(DEVICE)
output = cnn(data)
loss = criterion(output, label)
predict = torch.argmax(output, dim=-1) == label
accuracy = predict.float().mean().item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
hist_loss.append(loss.item())
hist_accr.append(accuracy)
if idx % 100 == 0:
print('Epoch {}, idx {}, Loss : {:.5f}, Accuracy : {:.5f}'.format(epoch, idx, loss.item(), accuracy))
학습이 완료되고 학습의 진행이 어떻게 되었는지 알기 위해서 사전에 정의한 hist_loss와 hist_accr을 사용해서 시각화 해보겠습니다.
fig, ax = plt.subplots(2,1)
fig.set_size_inches((12,8))
ax[0].set_title('Loss')
ax[0].plot(hist_loss, color='red')
ax[0].set_ylabel('Loss')
ax[1].set_title('Accuracy')
ax[1].plot(hist_accr, color='blue')
ax[1].set_ylabel('Accuracy')
ax[1].set_xlabel('Epochs')

학습이 완료된 후에 테스트 데이터를 사용해서 모델의 정확도를 확인해보았고 결과 값으로 Accuracy : 0.93750를 얻었습니다.
cnn.eval()
with torch.no_grad():
for idx, (data, label) in enumerate(test_loader):
data, label = data.to(DEVICE), label.to(DEVICE)
output = cnn(data)
loss = criterion(output, label)
predict = torch.argmax(output, dim=-1) == label
accuracy = predict.float().mean().item()
print('Accuracy : {:.5f}'.format(accuracy))




