Filter Pada Convolutional Neural Network (CNN)

Alfi Salim
BISA.AI
Published in
7 min readMay 11, 2020
Photo by Yusufk53 on Pixabay

Convolutional Neural Network (CNN) merupakan algoritma yang termasuk dalam kategori Deep Neural Network atau Deep Learning. CNN dapat menerima input-an berupa gambar yang untuk selanjutnya dapat digunakan mesin untuk belajar mengenali gambar, menentukan objek atau aspek apa saja yang terdapat dalam gambar dan lain sebagainya. Oleh sebab itu, bisa dikatakan bahwa CNN merupakan jenis Neural Network yang biasa digunakan pada data gambar.

Pada Deep Neural Network, tidak diketahui secara pasti proses apa yang terjadi di dalamnya hingga bagaimana output bisa dihasilkan, ini berlaku juga untuk CNN. Struktur pada Convolutional Neural Network dirancang untuk dapat memproses data gambar dua dimensi, di dalamnya terdapat proses yang disebut proses konvolusi, yaitu proses perkalian antara nilai input dan nilai dari filter dan akan menghasilkan output yang biasa disebut Feature Map.

Filter merupakan matriks 2 dimensi yang kita atur sebelumnya pada saat membuat arsitektur model. Secara khusus, filter tersebut dapat diperiksa dan divisualisasikan untuk mengetahui jenis fitur yang akan dideteksi oleh model. Agar lebih memahami bagaimana filter itu bekerja pada CNN, saya akan menjelaskannya melalui ilustrasi berikut:

Ilustrasi Filter CNN

Pada ilustrasi di atas, terdapat 3 buah filter dan sebuah objek yang merupakan gambar huruf H dengan ukuran 9x9, masing-masing filter berukuran 3x3. Setiap filter dapat mengekstraksi informasi yang berbeda-beda pada gambar. Seperti pada filter berwarna merah, mengekstrak informasi berupa garis horizontal yang merupakan atribut dalam gambar H. Begitu juga dengan filter biru dan filter hijau.

Tulisan ini akan memvisualisasikan filter yang digunakan pada model CNN sebagai pembelajaran. Dengan memvisualisasikan filter, diharapkan dapat memberikan pengetahuan tentang bagaimana model bekerja.

Implementasi Kode

Pertama, kita membutuhkan model untuk kita visualisasikan. Kita bisa memilih untuk membangun model dari awal ataupun menggunakan model yang telah disediakan pada library Keras. Keras menyediakan banyak model klasifikasi gambar yang memiliki performa yang sangat baik, salah satu modelnya adalah VGG16. Pada tulisan ini, kita akan menggunakan model VGG16.

Untuk membangun model VGG16, kita bisa mengikuti code dibawah ini :

from keras.applications.vgg16 import VGG16model = VGG16()
model.summary()

Import model VGG16 dari library Keras, kemudian inisialisasi variabel model sebagai model VGG16. Untuk mengetahui rangkuman dari model yang telah dibangun, gunakan perintah model.summary(). Adapun hasil dari rangkuman model dapat dilihat sebagai berikut :

Model: "vgg16" _________________________________________________________________ Layer (type)                 Output Shape              Param #    ================================================================= input_2 (InputLayer)         (None, 224, 224, 3)       0          _________________________________________________________________ block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792       _________________________________________________________________ block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928      _________________________________________________________________ block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0          _________________________________________________________________ block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856      _________________________________________________________________ block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584     _________________________________________________________________ block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0          _________________________________________________________________ block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168     _________________________________________________________________ block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080     _________________________________________________________________ block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080     _________________________________________________________________ block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0          _________________________________________________________________ block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160    _________________________________________________________________ block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808    _________________________________________________________________ block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808    _________________________________________________________________ block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0          _________________________________________________________________ block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808    _________________________________________________________________ block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808    _________________________________________________________________ block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808    _________________________________________________________________ block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0          _________________________________________________________________ flatten (Flatten)            (None, 25088)             0      _________________________________________________________________
fc1 (Dense) (None, 4096) 102764544 _________________________________________________________________ fc2 (Dense) (None, 4096) 16781312 _________________________________________________________________ predictions (Dense) (None, 1000) 4097000 ================================================================= Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0 _________________________________________________________________

Bobot model akan disimpan kedalam memory. Dari rangkuman di atas, dapat kita lihat bahwa model terstruktur dengan sangat baik. Model dibangun dari beberapa layer, layer-layer tersebut diberi nama dengan baik yang tersusun dalam block terurut.

Langkah selanjutnya adalah meninjau filter dalam model. Ini bertujuan untuk melihat apa yang harus kita lakukan sebelum dapat memvisualisasikan filter. Filter dalam model tidak dapat dilihat dari rangkuman model yang sebelumnya ditampilkan, pada rangkuman model hanya terdapat jumlah total bobot perlapisan. Untuk mengetahui filter dalam model, kita dapat mengakses semua layer dalam model dengan menggunakan properti model.layers

for i, layer in enumerate(model.layers):
if 'conv' in layer.name:
filter_, bias = layer.get_weights()
print(i, layer.name, filter_.shape, bias.shape)

Pada kode di atas, dari semua layer yang terdapat dalam model, seleksi semua layer konvolusi. Selanjutnya ambil bobot filter dan bias yang terdapat dalam layer konvolusi dan print agar kita bisa meninjau filter dalam model.

  1. Looping semua layer yang terdapat dalam model yang telah kita bangun dengan menggunakan properti model.layers.
  2. Seleksi kondisi, hanya pilih layer yang memiliki kata ‘conv’ pada nama layer-nya. Kata ‘conv’ berarti menunjukkan bahwa layer tersebut merupakan layer konvolusi.
  3. Ambil bobot dalam layer yang telah diseleksi. Pada layer konvolusi terdapat 2 set bobot, yaitu bobot filter dan bobot bias. Untuk mendapatkan bobot tersebut, bisa menggunakan fungsi get_weights(). Simpan dalam variabel filter_ untuk bobot filter dan variabel bias untuk bobot bias.
  4. Cetak index, nama layer, shape pada filter dan shape bias. Sehingga output akan terlihat seperti berikut :

Berdasarkan output di atas, dapat kita ketahui bahwa semua layer konvolusi pada model menggunakan filter dengan ukuran 3x3. Aturan pada arsitektur CNN adalah bahwa kedalaman antara filter dan input harus sesuai. Contohnya adalah pada jumlah channel. Pada input kita ketahui bahwa gambar input memiliki 3 channel, maka setiap filter harus memiliki 3 channel juga agar sesuai dengan aturan arsitektur CNN.

Jika kita cetak semua nilai bobot, kemungkinan nilai bobot bisa bernilai positif ataupun negatif yang berpusat pada 0,0. Untuk itu, kita perlu mengkonversi nilai-nilai tersebut menjadi range 0 dan 1 dengan menggunakan min-max standardization untuk membuatnya mudah divisualisasikan dengan mengikuti kode berikut:

filter_, bias = model.layers[1].get_weights()
fmin, fmax = filter_.min(), filter_.max()
filter_ = (filter_-fmin)/(fmax-fmin)

Pada tulisan ini kita hanya mencoba memvisualisasikan layer pertama pada model. Konversi menggunakan min-max standardization dengan rumus berikut :

  1. Ambil bobot filter pada layer pertama menggunakan fungsi get_weights().
  2. Tentukan nilai terkecil dan nilai terbesar menggunakan fungsi min() dan max(), kemudian simpan pada variabel fmin untuk nilai terkecil dan fmax untuk nilai terbesar.
  3. Hitung min-max standardization menggunakan rumus di atas.

Pada tulisan ini, kita akan memvisualisasikan 5 filter pertama dari 64 filter yang terdapat dalam layer pertama pada model. Plot masing-masing channel pada setiap filter. Kita atur filter sebagai baris baru dalam subplot dan tiap channel adalah kolom dari masing-masing filter. Cara memplot filter dan channelnya dapat mengikuti kode berikut:

import matplotlib.pyplot as pltjum_filter, index = 5, 1for i in range(jum_filter):
f = filter_[:, :, :, i]
for j in range(3):
axs = plt.subplot(jum_filter, 3, index)
axs.set_xticks([])
axs.set_yticks([])

plt.imshow(f[:, :, j], cmap='gray')
index = index + 1
plt.show()
  1. Import library matplotlib untuk memplot setiap filter beserta channel-nya.
  2. Inisialisasi variabel jum_filters dan index sebagai integer dengan nilai 5 untuk variabel jum_filter dan 1 untuk variabel index.
  3. Looping sebanyak nilai jum_filter, inisialisasi variabel f sebagai filter ke-n, sesuai dengan nilai i pada looping.
  4. Looping sebanyak 3 kali sebagai channel pada masing-masing filter.
  5. Tentukan subplot sebagai wadah untuk memvisualisasikan masing-masing filter dengan menggunakan library matplotlib, atur jumlah baris dan kolomnya serta indeks dari plotnya.
  6. Hapus list lokasi koordinat sumbu x dan y dengan menggunakan fungsi set_xticks([]) dan set_yticks([]).
  7. Tampilkan filter dengan menggunakan fungsi imshow() dan atur cmap sebagai gray.
  8. Buat variabel index menjadi increment 1 dengan menambahkannya pada setiap perulangan.
  9. Terakhir, tampilkan seluruh plot-plot yang telah diatur dengan menggunakan fungsi show(). Adapun tampilan dari visualisasi filter akan menjadi seperti berikut :

Dari visualisasi filter di atas, kita dapat mengambil kesimpulan bahwa beberapa filter sama pada tiap channel-nya dan filter yang lain berbeda pada tiap channel-nya. Kita juga bisa mengetahui bahwa filter pertama mendeteksi gradient dari cahaya kiri atas dan terus menjadi gelap di kanan bawah. Gambar kotak yang gelap menunjukkan bobot kecil dan gambar terang menunjukkan bobot yang besar.

Alasan saya hanya memvisualisasikan 5 dari 64 filter adalah sebagai pembelajaran agar lebih mudah dipahami. Semakin sedikit filter divisualisasikan maka akan semakin mudah terlihat detail dari filter tersebut. Jika kita jabarkan, saat kita mulai beralih ke layer kedua, pada layer kedua masih terdapat 64 filter juga namun dengan jumlah channel sebanyak 64 channel. Maka untuk memvisualisasikan seluruh filter pada layer kedua kita membutuhkan plot sebanyak 64x64, yang berarti 4.096 plot. Jika ini dilakukan mungkin akan menyulitkan kita untuk melihat detail filter dari hasil visualisasi.

Semoga bermanfaat!

Referensi:

[1] Samek, Wojciech et al. 2017. “Evaluating the Visualization of What a Deep Neural Network Has Learned.” IEEE Transactions on Neural Networks and Learning Systems 28(11): 2660–73.

--

--