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))