RNN untuk Image Recognition
RNN mempunyai keunggulan yang tidak dimiliki oleh model CNN yaitu kemampuan untuk menangani data yang bersifat time serial/berbasis waktu yang artinya data yang diolah akan dipengaruhi dari sequence sebelumnya.
Sehingga RNN sangat cocok sekali digunakan pada Natural Language Processing, seperti dibahas pada dasar-dasar RNN sebelumnya, saya akan memberikan contoh sederhana untuk kasus yang lain seperti tugas recognition sehingga RNN yang digunakan dengan jenis one to one
Model RNN ini sangat sederhana, bahkan kalian bisa pelajari lebih lengkap di referensi yang saya cantumkan dibawah ini. Studi kasus recognition yang sudah menjadi kebiasaan secara umum yaitu untuk mengenali character pada dataset MNIST.
Dataset MNIST
Contents
Merupakan dataset yang terdiri dari tulisan tangan 0 sampai 9 dengan ribuan data. Kalian cukup download saja dengan format yang ringkas yaitu ubyte https://softscients.com/2021/06/01/format-ubyte-dan-tfrecorddataset/ . Tapi nggak usah galau, bagaimana dataset nanti dibaca. Agar lebih mudah, kita langsung import semua kebutuhan package nya
from tqdm import tqdm import torch.nn as nn import torch import torchvision import torchvision.transforms as transforms from torch.utils.data import Dataset from PIL import Image import glob from torch.utils.data.dataloader import DataLoader import numpy as np from matplotlib import pyplot as plt import torch.optim as optim # Device device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Kemudian kita langsung saja download yang akan dimasukan kedalam folder bernama data, sehingga kita setting True agar bisa perintah proses download.
BATCH_SIZE = 64 # list all transformations transform = transforms.Compose([transforms.ToTensor()]) # download and load training dataset trainset = torchvision.datasets.MNIST(root='./data', train=True,download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=BATCH_SIZE,shuffle=True, num_workers=2) # download and load testing dataset testset = torchvision.datasets.MNIST(root='./data', train=False,download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=BATCH_SIZE,shuffle=False, num_workers=2)
Oiya untuk dataset nya nanti kita bisa tersendiri Pytorch General Dataset bila ingin menggunakan data selain MNIST. Oiya untuk ukuran dataset berupa gambar dengan ukuran 28 x 28 ya, mari kita bisa telisik lebih jauh dengan memanggil dataset tersebut
dataiter = next(iter(trainloader)) images, labels = dataiter print(images.shape,labels)
hasilnya kalian bisa melihat 1 batch dengan jumlah 64 file gambar dengan format grayscale alias 1 layer serta ukuran 28 x 28. Target berisi angka 0 sampai 9
torch.Size([64, 1, 28, 28]) tensor([9, 9, 2, 9, 9, 9, 4, 8, 4, 8, 4, 9, 3, 1, 0, 8, 4, 3, 1, 2, 6, 7, 6, 1, 2, 8, 0, 1, 9, 1, 2, 3, 7, 9, 0, 8, 2, 0, 6, 3, 5, 1, 3, 4, 1, 1, 8, 8, 4, 4, 2, 6, 9, 4, 4, 6, 6, 1, 5, 7, 0, 6, 3, 4])
Model RNN
Penerapan RNN ada banyak versi, kita menggunakan versi yang sederhana dulu dan memang terbukti bisa digunakan pada kasus dataset MNIST serta jangan kaget bila model RNN dibawah ini belum tentu cocok untuk dataset yang lainnya karena based on karakteristik dataset yang kalian gunakan.
class ImageRNN(nn.Module): def __init__(self, batch_size, n_steps, n_inputs, n_neurons, n_outputs): super(ImageRNN, self).__init__() self.n_neurons = n_neurons self.batch_size = batch_size self.n_steps = n_steps self.n_inputs = n_inputs self.n_outputs = n_outputs self.basic_rnn = nn.RNN(self.n_inputs, self.n_neurons) self.FC = nn.Linear(self.n_neurons, self.n_outputs) def init_hidden(self,): # (num_layers, batch_size, n_neurons) return (torch.zeros(1, self.batch_size, self.n_neurons)) def forward(self, X): # transforms X to dimensions: n_steps X batch_size X n_inputs X = X.permute(1, 0, 2) self.batch_size = X.size(1) self.hidden = self.init_hidden() # lstm_out => n_steps, batch_size, n_neurons (hidden states for each time step) # self.hidden => 1, batch_size, n_neurons (final state from each lstm_out) lstm_out, self.hidden = self.basic_rnn(X, self.hidden) out = self.FC(self.hidden) return out.view(-1, self.n_outputs) # batch_size X n_output
Paramater
Kita gunakan parameter yang terdiri dari berikut ini
# parameters N_STEPS = 28 N_INPUTS = 28 N_NEURONS = 150 N_OUTPUTS = 10 N_EPHOCS = 50
Langsung saja kita panggil serta sekalian buat loss function dengan tipe cross entropy
# Model instance model = ImageRNN(BATCH_SIZE, N_STEPS, N_INPUTS, N_NEURONS, N_OUTPUTS) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001)
Mari kita coba masukan data gambar kedalam model tersebut
inputs = images.view(-1,28,28) outputs = model(inputs) print('output',torch.argmax(outputs,dim=1)) print('target',labels)
hasilnya bisa kalian lihat dengan hasil masih salah
output tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) target tensor([8, 9, 7, 8, 0, 7, 9, 3, 9, 3, 3, 8, 6, 7, 0, 2, 5, 2, 0, 7, 6, 6, 9, 8, 2, 7, 0, 3, 5, 5, 3, 5, 4, 1, 8, 9, 6, 6, 6, 7, 2, 9, 1, 8, 5, 0, 6, 0, 0, 8, 1, 9, 4, 5, 1, 1, 3, 4, 2, 1, 3, 3, 7, 2])
Kalian jangan bingung dengan perintah
torch.argmax(outputs,dim=1)
yang merupakan output dengan array jumlah 10, sehingga akan dicari nilai maksimal mengingat output dari model emang dibuat 10 array lihat saja perintah pada model diatas.
return out.view(-1, self.n_outputs) # batch_size X n_output
Kita bisa mengambil kesimpulan bahwa input dengan ukuran 28 x 28 akan dijadikan output 1 x 10 saja sehingga loss function yang digunakan berupa cross entropy.
Proses Training
Bila sudah siap semuanya, kita langsung lakukan proses training
loss_list = list() for epoch in tqdm(range(N_EPHOCS)): train_running_loss = 0.0 train_acc = 0.0 model.train() # TRAINING ROUND for i, data in enumerate(trainloader): optimizer.zero_grad() # reset hidden states model.hidden = model.init_hidden() # get the inputs inputs, labels = data inputs = inputs.view(-1, 28,28) # forward + backward + optimize outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() loss_list.append(loss.item()) print("epoch: ",epoch," loss: ",loss.item())
hasilnya kita plotkan saja langsung
#tampilkan grafik epoch untuk loss function plt.figure() plt.plot(np.array(loss_list)) plt.xlabel('epoch') plt.ylabel('loss') plt.title('Grafik Loss tiap epoch') plt.show()
Proses Validasi
Sekarang kita lanjutkan dengan proses validasi menggunakan dataset testing dengan hasil sebagai berikut
#lakukan evaluasi model.eval() jumlah_benar = 0 jumlah_data = 0 for i, data in enumerate(tqdm(testloader)): inputs, labels = data inputs = inputs.view(-1, 28, 28) outputs = model(inputs) prediksi = torch.argmax(outputs,dim=1) benar = (prediksi==labels).sum() jumlah_benar = jumlah_benar+benar jumlah_data = len(labels)+jumlah_data acc = (jumlah_benar/jumlah_data)*100 acc = np.round(acc.item(),decimals=2) print("\n akuarasi acc : ",acc," %")
akuarasi acc : 96.89 %
Dapat disimpulkan RNN untuk Image Recognition dapat digunakan untuk mengenail dataset MNIST
Catatan Init Hidden
Selain menggunakan init hidden bernilai ZEROS (torch.zeros(1, self.batch_size, self.n_neurons))
kalian juga bisa menggunakan bilangan random seperti return nn.init.kaiming_uniform_(torch.empty(1, self.batch_size, self.n_neurons))
Ref: