Ada banyak sekali penerapan machine learning dalam dunia nyata. Salah satunya yaitu teknologi pengenalan tulisan tangan. Ada sejumlah tantangan tersendiri dalam kasus ini yaitu banyaknya variasi tulisan tangan. Mengingat setiap tangan manusia bersifat unik sehingga hampir setiap orang mempunyai karakter/goresan pena yang berbeda untuk menulis.
Namun demikian sangat menarik sekali topik pembahasan machine learning menggunakan teknik deep machine learning dengan convolutional network, yups.
Deep Learning
Contents
Deep Learning merupakan salah satu bagian dari Machine Learning yang perkembangannya cukup pesat. Deep Learning dikenal juga dengan Deep Structured Learning atau Hierarchical Learning. Perbedaan terlihat jelas bahwa Deep Learning ini merupakan otak utama yang dapat menciptakan Artificial Intelligence yang lebih cerdas dan semakin mirip dengan manusia. Dalam Deep Learning, algoritma yang biasa digunakan adalah algoritma pemodelan abstraksi dengan memanfaatkan sekumpulan fungsi transformasi non linear yang berlapis dan mendalam.
Algoritma Deep Learning
Algoritma deep learning saat ini terbagi menjadi 2 yaitu
Artificial Neural Networks (ANN): Artificial Neural Networks yang biasa disingkat dengan ANN adalah bagian yang paling ajaib ajaib dari deep learning. ANN ini mensimulasikan kerja otak kita yang tersusun jaringan saraf yang disebut neuron. Sama seperti sistem otak manusia, dalam jaringan artificial neural network ini si mesin menerima informasi pada titik-titik yang disebut nodes yang terkumpul pada satu layer untuk kemudian diteruskan dan diproses ke layer selanjutnya yang disebut hidden layers.
Cara kerja ANN, misalkan kita mempunyai gambar berupa tulisan tangan angka 9 berukuran 28×28 pixel. Setiap piksel dari gambar ini kemudian dipecah menjadi nodes dalam layer input. Sehingga kita memiliki 784 nodes. Lalu untuk mengetahui angka apa itu, kita harus menset nodes output sebanyak 10 (0-9). Dalam hidden layers informasi tersebut difilter hingga akhirnya diteruskan dan informasi masuk di nodes output 9. Dalam kasus supervised learning, kita tak perlu mengatur algoritma yang ada di hidden layers. Yang perlu kita lakukan memasukkan angka yang ditulis tangan sebanyak mungkin dan menentukan outputnya sehingga terbentuk suatu pola dalam hidden layers. Jika pola dalam hidden layers sudah terbentuk, kita tinggal mengetes sejauh mana si mesin dapat mengenali gambar.
Convolutional Neural Networks (CNN): Dalam kasus image recognition untuk gambar objek kucing di atas, metode yang digunakan sudah lebih canggih lagi dari ANN yang disebut Convolutional Neural Networks (CNN). Secara komputasi, metode CNN ini lebih irit daya, bayangkan jika gambar kucing tersebut berukuran 1920×1080 pixel. Ini berarti ada 2.073.600 nodes yang harus dibuat pada layer input.
Pengenalan Angka Tulisan Tangan menggunakan Deep Learning
Pengenalan Angka Tulisan Tangan yang akan buat sangat mudah karena cukup menggunakan package/library yang sudah ada. Adapaun dataset Pengenalan Angka Tulisan Tangan berasal dari MNIST. Kalian akan belajar secara sekilas penerapannya, untuk itu kalian harus install dulu tensorflow dan keras. Pada tulisan ini dibuat menggunakan versi
- Python -3.6.3 Anaconda
- Spyder-3.2.4
- tensorflow-1.8.0
- keras-2.1.6
- OpenCV-4.1.0
- Numpy-1.17.4
- Matplotlib-3.1.1
- PIL-6.1.0
Untuk mempermudah install python, kalian gunakan saja anaconda yaitu : https://repo.continuum.io/archive/ kalian pilih yang Anaconda3-5.0.1-Windows-x86_64.exe. Koq jadi banyak sekali ya modulnya, tapi tenang saja untuk kalian yang belum tahu cara instal dan setup Python bisa kalian beli buku saya disini, Untuk cara install menggunakan PIP bisa ke link disini. Pengenalan Angka Tulisan Tangan dengan Deep Learning convolutional network yang dibuat kali ini menggunakan deep learning dengan library tensorflow dan keras yang sudah banyak dibahas hanya saja ditulisan ini dikembangkan dengan menerima input dari mouse agar lebih mudah digunakan sesuai dengan ilustrasi diatas. Adapun dataset terdiri dari angka 0-9 dari MNIST berupa tulisan tangan, tenang saja kalau kalian sudah install Keras sudah ada koq tinggal di load saja (pastikan kalian punya koneksi internet ya). Sebelum membaca postingan ini, sebaiknya anda perlu tahu dasar-dasar python terlebih dahulu. Secara umum tahapan aplikasi ini disingkat saja menjadi 3 tahap yaitu
- Persiapan Dataset
- Kompilasi Model
- Testing
Persiapan Dataset
Dataset diambil dari MNIST yang berisi tulisan tangan 0 s.d 9 dengan 60 ribu data training dan 10 ribu data testing dengan ukuran 28×28, untuk cara download datanya di load menggunakan kode berikut
import keras from keras.datasets import mnist #load mnist dataset (X_train, y_train), (X_test, y_test) = mnist.load_data()
Alangkah lebih bagusnya disimpan saja dalam format *.npy via spyder
Kompilasi Model
Berikut kode lengkapnya mengenai kompilasi model
- X merupakan input berupa array 28×28
- Y merupakan target dengan format kelas kategori/target kelas misalkan untuk kelas 3 dibuat menjadi vektor [0, 0, 0, 1, 0, 0, 0, 0, 0, 0] atau disebut dengan one hot encoding, kalian bisa baca disini
# -*- coding: utf-8 -*- """ Created on Sat May 26 22:04:42 2018 """ import keras from keras.layers.convolutional import Conv2D from keras.layers.convolutional import MaxPooling2D from keras.layers import Dense from keras.layers import Dropout from keras.layers import Flatten from keras.layers import Activation import numpy as np from keras.models import Sequential X_train = np.load('X_train.npy') #database untuk training y_train = np.load('y_train.npy') X_test = np.load('X_test.npy') #database untuk testing y_test = np.load('y_test.npy') img_cols = 28 #ukuran gambar img_rows = 28 X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1) #diubah menjadi 4 dimensi X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1) #idem input_shape = (img_rows, img_cols, 1) X_train = X_train.astype('float32') X_test = X_test.astype('float32') X_train /= 255 X_test /= 255 num_category = 10 # convert class vectors to binary class matrices y_train = keras.utils.to_categorical(y_train, num_category) y_test = keras.utils.to_categorical(y_test, num_category) model = Sequential() #convolutional layer with rectified linear unit activation model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape)) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) #randomly turn neurons on and off to improve convergence model.add(Dropout(0.25)) #flatten since too many dimensions, we only want a classification output model.add(Flatten()) #fully connected to get all relevant data model.add(Dense(128, activation='relu')) #one more dropout for convergence' sake :) model.add(Dropout(0.5)) #output a softmax to squash the matrix into output probabilities model.add(Dense(num_category, activation='softmax')) model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy']) batch_size = 128 num_epoch = 5 #model training model_log = model.fit(X_train, y_train, batch_size=batch_size, epochs=num_epoch, verbose=1, validation_data=(X_test, y_test)) score = model.evaluate(X_test, y_test, verbose=0) print('Test loss:', score[0]) #Test loss: 0.0296396646054 print('Test accuracy:', score[1]) #Test accuracy: 0.9904 #Save the model # serialize model to JSON model_digit_json = model.to_json() with open("model_digit.json", "w") as json_file: json_file.write(model_digit_json) # serialize weights to HDF5 model.save_weights("model_digit.h5") print("Saved model to disk") print ('done')
Kalian run dengan Spyder, waktu yang digunakan cukup lama pada sesi pelatihan ini yaitu hampir 10 menit untuk 5 epoch saja! Boros RAM dan prosesor. Biasanya sih saya pakai Google Colab biar lebih cepat karena komputasi Cloud nya udah pakai VGA Titan yang harga per 1 biji nya saat ini cukup buat beli mobil 1 biji yaitu cuman 100 jutaan saja! Mungkin kalian ingin beli satu biji buat koleksi dimeja kerja. Kalau duit cekak, ya paling running pas malam-malam saja biar ditunggu sampai siang pun belum tentu kelar kalau menggunakan iterasi 1000x
Hal ini wajar saja karena loading data berupa 60.000 data x 28 baris x 28 kolom jika masing-masing menggunakan type data float32 (8bit) maka dibutuhkan 60.000 x 28 x 28 = 47.040.000 float32 yang cukup menguras sumber daya RAM
Berikut hasil pelatihan, kalian melihat informasi waktu dan akurasinya dengan tiap epoch akan naik akurasinya!
Train on 60000 samples, validate on 10000 samples Epoch 1/5 60000/60000 [==============================] - 231s 4ms/step - loss: 0.2731 - acc: 0.9168 - val_loss: 0.0647 - val_acc: 0.9782 Epoch 2/5 60000/60000 [==============================] - 220s 4ms/step - loss: 0.0953 - acc: 0.9715 - val_loss: 0.0442 - val_acc: 0.9853 Epoch 3/5 60000/60000 [==============================] - 202s 3ms/step - loss: 0.0705 - acc: 0.9788 - val_loss: 0.0343 - val_acc: 0.9876 Epoch 4/5 60000/60000 [==============================] - 203s 3ms/step - loss: 0.0566 - acc: 0.9832 - val_loss: 0.0368 - val_acc: 0.9879 Epoch 5/5 60000/60000 [==============================] - 197s 3ms/step - loss: 0.0494 - acc: 0.9846 - val_loss: 0.0298 - val_acc: 0.9896 Test loss: 0.029829543634658784 Test accuracy: 0.9896 Saved model to disk done
Kalian bisa melihat hasil pelatihannya berupa 2 file yaitu model_digit.json (format JSON) dan model_digit.h5 (format HDF5) Kalau kalian buka *.json akan berisi keterangan deep learning model seperti berikut
{"class_name": "Sequential", "config": [{"class_name": "Conv2D", "config": {"name": "conv2d_5", "trainable": true, "batch_input_shape": [null, 28, 28, 1], "dtype": "float32", "filters": 32, "kernel_size": [3, 3], "strides": [1, 1], "padding": "valid", "data_format": "channels_last", "dilation_rate": [1, 1], "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "VarianceScaling", "config": {"scale": 1.0, "mode": "fan_avg", "distribution": "uniform", "seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Conv2D", "config": {"name": "conv2d_6", "trainable": true, "filters": 64, "kernel_size": [3, 3], "strides": [1, 1], "padding": "valid", "data_format": "channels_last", "dilation_rate": [1, 1], "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "VarianceScaling", "config": {"scale": 1.0, "mode": "fan_avg", "distribution": "uniform", "seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_3", "trainable": true, "pool_size": [2, 2], "padding": "valid", "strides": [2, 2], "data_format": "channels_last"}}, {"class_name": "Dropout", "config": {"name": "dropout_5", "trainable": true, "rate": 0.25, "noise_shape": null, "seed": null}}, {"class_name": "Flatten", "config": {"name": "flatten_3", "trainable": true}}, {"class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "VarianceScaling", "config": {"scale": 1.0, "mode": "fan_avg", "distribution": "uniform", "seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dropout", "config": {"name": "dropout_6", "trainable": true, "rate": 0.5, "noise_shape": null, "seed": null}}, {"class_name": "Dense", "config": {"name": "dense_6", "trainable": true, "units": 10, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "VarianceScaling", "config": {"scale": 1.0, "mode": "fan_avg", "distribution": "uniform", "seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}], "keras_version": "2.1.5", "backend": "tensorflow"}
Sedangkan model_digit.h5 berisi angka bobot dan bias yang ukurannya sangat besar sekali yaitu 4.7 MB berupa format penyimpanan HDF5 yang bisa kalian pelajari disini . kalau kalian tertarik deep learning cnn (convolutional network) bisa dipelajari di http://cs231n.github.io/convolutional-networks/
Testing Pengenalan Angka Tulisan Tangan
Kalian tentu ingin segera mencobanya untuk dataset asing, nah kalian bisa coba dengan kode berikut
from matplotlib import pyplot as plt from keras.models import model_from_json import numpy as np X_test = np.load('X_test.npy') y_test = np.load('y_test.npy') img_cols = 28 img_rows = 28 X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1) input_shape = (img_rows, img_cols, 1) X_test = X_test.astype('float32') X_test /= 255 # Model reconstruction from JSON file with open('model_digit.json', 'r') as f: model = model_from_json(f.read()) # Load weights into the new model model.load_weights('model_digit.h5') no_sample = 15 #membuat input 4 dimensi n2=np.full([1,img_rows,img_cols,1],X_test[no_sample]) hasil = model.predict(n2) plt.imshow(X_test[no_sample,:,:,0],cmap='gray') #mencari nilai maksimalnya plt.title('Prediksi Angka : '+str(np.argmax(hasil)))
Hasil akan ditampilkanya menggunakan Matplotlib
Wow cukup berhasil bukan bahwa Pengenalan Angka Tulisan Tangan dengan convolutional network sudah kalian lakukan dengan baik! Mari kalian coba dengan gambar lainnya
Pembuatan Painter Pengenalan Angka Tulisan Tangan
Tentu aplikasi diatas yang berbasis CLI (cuman kode doank) tidak menarik, harus kalian kembangkan menjadi sebuah aplikasi yang bagus, Contohnya kalian bisa membuat aplikasi painter seperti berikut ini
Aplikasi diatas bisa kalian namakan dengan Painter yang menggunakan mouse untuk menggambar di Canvas TKinter, kode lengkap sebagai berikut
from tkinter import * from tkinter.colorchooser import askcolor class Paint(object): DEFAULT_PEN_SIZE = 5.0 DEFAULT_COLOR = 'black' def __init__(self): self.root = Tk() self.pen_button = Button(self.root, text='pen', command=self.use_pen) self.pen_button.grid(row=0, column=0) self.brush_button = Button(self.root, text='brush', command=self.use_brush) self.brush_button.grid(row=0, column=1) self.color_button = Button(self.root, text='color', command=self.choose_color) self.color_button.grid(row=0, column=2) self.eraser_button = Button(self.root, text='eraser', command=self.use_eraser) self.eraser_button.grid(row=0, column=3) self.choose_size_button = Scale(self.root, from_=1, to=10, orient=HORIZONTAL) self.choose_size_button.grid(row=0, column=4) self.c = Canvas(self.root, bg='white', width=600, height=600) self.c.grid(row=1, columnspan=5) self.setup() self.root.mainloop() def setup(self): self.old_x = None self.old_y = None self.line_width = self.choose_size_button.get() self.color = self.DEFAULT_COLOR self.eraser_on = False self.active_button = self.pen_button self.c.bind('<B1-Motion>', self.paint) self.c.bind('<ButtonRelease-1>', self.reset) def use_pen(self): self.activate_button(self.pen_button) def use_brush(self): self.activate_button(self.brush_button) def choose_color(self): self.eraser_on = False self.color = askcolor(color=self.color)[1] def use_eraser(self): #self.activate_button(self.eraser_button, eraser_mode=True) #self.c.config(fg='white') #self.c = Canvas(self.root, bg='white', width=600, height=600) self.c.create_rectangle(0,0, 600,600,outline="#fb0", fill="white") def activate_button(self, some_button, eraser_mode=False): self.active_button.config(relief=RAISED) some_button.config(relief=SUNKEN) self.active_button = some_button self.eraser_on = eraser_mode def paint(self, event): self.line_width = self.choose_size_button.get() paint_color = 'white' if self.eraser_on else self.color if self.old_x and self.old_y: self.c.create_line(self.old_x, self.old_y, event.x, event.y, width=self.line_width, fill=paint_color, capstyle=ROUND, smooth=TRUE, splinesteps=36) self.old_x = event.x self.old_y = event.y def reset(self, event): self.old_x, self.old_y = None, None if __name__ == '__main__': Paint()
Pembuatan Painter dengan Pengenalan Tulisan Angka
Sekarang kalian akan sedikit mengubah Painter diatas menjadi lebih cerdas yang mampu mengenali tulisan angka tangan secara baik menggunakan algoritma deep learning lebih tepatnya Pengenalan Angka Tulisan Tangan dengan convolutional network yang telah dilatih, sehingga Painter tersebut pada saat loading akan meload model dan bobot terlebih dahulu sebelum digunakan. Selain itu kalian akan mengubah Canvas menjadi sebuah file gambar berbentuk *.jpg didalam disk sebelum dibaca oleh Machine Learning. Beginilah tampilkan aplikasi Painter yang sudah ‘pinter’
Menarik bukan? Kalian bisa mendapatkan kode lengkap dengan cara subcribe dan follow blog ini terlebih dahulu agar makin banyak content yang menarik buat kalian semuanya, kalau sudah subcribe dan follow kirim saja email kesini.