Membahas mengenani operasi convolution yang merupakan inti dari feature extraction. Operasi konvolusi (convolution) dalam PyTorch, seperti yang biasanya dilakukan dalam jaringan saraf tiruan (neural networks), umumnya dilakukan menggunakan modul torch.nn.Conv2d untuk data 2D dan torch.nn.Conv3d untuk data 3D. Konvolusi adalah proses matematis yang melibatkan penjumlahan produk titik dari bagian-bagian tumpang tindih dari dua himpunan data.
Mari kita lihat cara kerjanya dalam konteks pengolahan gambar, yang merupakan salah satu penggunaan umum dari konvolusi dalam deep learning:
- Pengenalan Kernel: Kernel adalah matriks kecil yang “digulirkan” (convolved) melintasi gambar. Ini merupakan representasi parameter dari lapisan konvolusi yang akan dipelajari oleh model.
- Convolution Operation: Kernel tersebut digeser (convolved) secara berulang-ulang di atas seluruh gambar. Pada setiap langkah, elemen kernel dikalikan dengan elemen gambar yang berada di bawahnya, dan hasilnya dijumlahkan. Operasi ini disebut juga sebagai operasi dot product atau inner product.
- Striding: Striding adalah seberapa jauh kernel digeser setiap kali. Striding biasanya 1, yang berarti kernel digeser satu langkah ke kanan setiap kali. Namun, Anda juga dapat menentukan striding lain, seperti 2, 3, dan seterusnya.
- Padding: Padding adalah menambahkan nilai nol di sekitar gambar. Ini dilakukan untuk memastikan bahwa ukuran output dari konvolusi sama dengan ukuran input atau memiliki dimensi yang diinginkan. Padding dapat ‘valid’ (tanpa padding) atau ‘same’ (padding sehingga output memiliki ukuran yang sama dengan input).
- Channel: Konvolusi biasanya diterapkan pada setiap channel (misalnya, R, G, B dalam gambar warna). Jika input memiliki banyak channel, maka kernel juga akan memiliki banyak channel. Konvolusi dilakukan secara independen pada setiap channel, dan hasilnya ditambahkan.
Persamaan matematika untuk operasi konvolusi dalam PyTorch dapat dinyatakan sebagai berikut:
Misalkan
- adalah input,
- adalah kernel,
- adalah output,
- adalah bias,
- adalah fungsi aktivasi (opsional), dan ∗∗ menunjukkan operasi konvolusi. Dalam kasus 2D, kita dapat menulisnya sebagai:
Di mana:
- adalah tensor input dengan dimensi ,
- di mana ( adalah ukuran batch,
- adalah jumlah channel input, dan
- serta
- adalah tinggi dan lebar gambar.
- adalah tensor kernel dengan dimensi
- di mana adalah jumlah channel output, dan
- serta adalah tinggi dan lebar kernel.
- di mana adalah jumlah channel output, dan
- adalah tensor output dengan dimensi (N,Cout,Hout,Wout),
- di mana dan adalah tinggi dan lebar output.
- adalah bias dengan dimensi yang di-broadcast pada setiap elemen dalam output.
- adalah fungsi aktivasi seperti ReLU atau tanh.
Operasi konvolusi dilakukan dengan menggeser kernel melintasi tensor input dan menghitung dot product antara elemen kernel dan bagian tensor input yang tumpang tindih di setiap langkah. Selanjutnya, bias ditambahkan ke setiap channel output, dan jika ada, fungsi aktivasi diterapkan.
Convolution di OpenCV
Contents
Sebelum melangkah lebih jauh, di OpenCV juga sudah ada operasi convolution. Kernel/filter yang kita gunakan pun bisa di custom sesuai keperluan seperti efek blur, sharpening, edge dan yang lainnya. Di OpenCV (Open Source Computer Vision Library), operasi konvolusi dapat dilakukan menggunakan fungsi cv2.filter2D()
. Fungsi ini memungkinkan Anda menerapkan filter kernel ke citra untuk melakukan konvolusi. Operasi ini berbasis numpy array
import cv2 import numpy as np # Baca citra image = cv2.imread('gambar.jpg',0) #baca sebagai grayscale # Definisikan kernel kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]) # Terapkan operasi konvolusi filtered_image = cv2.filter2D(image, -1, kernel) # Tampilkan citra asli dan hasilnya cv2.imshow('Original Image', image) cv2.imshow('Filtered Image', filtered_image) cv2.waitKey(0) cv2.destroyAllWindows()
Perbandingan Convolutional di OpenCV dan Pytorch
Operasi convolutional pada di OpenCV dan Pytorch sebenarnya sama, hanya saja di Pytorch menggunakan skala gambar PIl Image yaitu 0 sampai 1 sedangkan OpenCV menggunakan skala 0 sampai 256 dalam mempresentasikan gambar.
Misalkan saja saya mempunyai sebuah kernel/filter blur sebagai berikut
kernel = np.ones((5, 5), np.float32) / 25
Mari kita lakukan operasi convolutional nya
import torch import torch.nn as nn import numpy as np import torchvision.transforms as transforms import cv2 import numpy as np from matplotlib import pyplot as plt from PIL import Image file = '/Users/mulkansyarif/Downloads/image2.jpg' I = cv2.imread(file,0) #baca gambar mode gray I = cv2.resize(I,(600,400)) kernel = np.ones((5, 5), np.float32) / 25 result = cv2.filter2D(src=np.float64(I), ddepth=-1, kernel=kernel) final = np.hstack((I,np.uint8(result))) plt.figure() plt.imshow(final,cmap='gray') plt.show()
Convolutional di Pytorch
kita tidak menggunakan PIL Image untuk loading gambar ke dalam tensor, namun menggunakan numpy sebagai array di Pytorch sehingga tetap terjaga nilai pixel nya dari 0 sampai 255
I2 = torch.from_numpy(I).unsqueeze(0)
Selanjutnya kita wajib mengubah nya kedalam batch
I3 = torch.reshape(I2, (1,1,400,600))
itu artinya 1 batch, 1 channel, dengan ukuran gambar 400 x 600. Kemudian kita buat function saja agar lebih mudah dalam operasi convolutionalnya di Pytorch.
def do(image_tensor): kernel = np.ones((5, 5), np.float32) / 25 kernel = torch.from_numpy(kernel) kernel = torch.reshape(kernel,(1,1,5,5)) d = kernel.shape[-1] conv = torch.nn.Conv2d(in_channels=1,out_channels=1, kernel_size=(d, d), padding=0, bias=False) with torch.no_grad(): conv.weight[:] = kernel.float() result = conv((image_tensor).float()) return result
Kemudian kita proses saja
I4 = do(I3)
variabel I4 masih dalam bentuk tensor batch, kita wajib urai dulu
result2 = I4.squeeze(0)
nah kita gunakan function permute (walaupun ini masih ada bugs nya – https://discuss.pytorch.org/t/why-does-pytorch-rotate-a-numpy-image-when-converted-to-tensor/155231)
result3 = torch.permute(result2,(2,1,0)).detach().numpy()
kita ubah ke numpy lagi
result4 = np.uint8(result3)
kita rotate lagi karena ada bugs di permutate
result4 = cv2.rotate(result4, cv2.ROTATE_90_CLOCKWISE)
nah variabel diatas sudah dalam bentuk numpy dan siap di tampilkan hasilnya
plt.figure() plt.imshow(result4,cmap='gray') plt.show()
ukuran dimension akhir akan berbeda (kalian bisa menambahkan padding=’same’ yang semula padding=0)
sesuai keterangan dari sana yaitu
ref:
https://github.com/TomasBeuzen/deep-learning-with-pytorch/tree/main
Weight dan Kernel/Filter
Sekedar info saja, bahwa kernel/filter pada operasi convolutional didalam function conv2d itu disebut dengan weight yang sifatnya random mengikuti distribusi gaussian/normal.
Mari kita cek sesuai dengan referensi https://machinelearningmastery.com/a-gentle-introduction-to-normality-tests-in-python/ Jika mengikuti garis Memahami dan Menggunakan Quantile-Quantile Plot (Q-Q Plot) untuk Uji Normalitas Populasi maka data tersebut mengikuti distribusi normal, mari kita coba dengan ukuran 10 x 10 atau 100 record.
import numpy as np import torch import torch.nn as nn from statsmodels.graphics.gofplots import qqplot d = 10 conv = torch.nn.Conv2d(1, 1, kernel_size=(d, d), padding=1) kernel = conv.weight[:] # ubah ke numpy untuk hitung QQ plot # https://machinelearningmastery.com/a-gentle-introduction-to-normality-tests-in-python/ kernel = kernel.squeeze(0)[0].detach().numpy() qqplot(kernel.reshape(-1), line='s') pyplot.show()
Kesimpulan
Dari tulisan diatas, kita dapat menyimpulkan bahwa
- Operasi Convolutional pada OpenCV dan Pytorch adalah sama cara kerjanya
- Jika menggunakan Conv2d, maka secara default kernel/filter yang digunakan bersifat random mengikuti distribusi normal
- kernel/filter pada conv2d menggunakan istilah/term bobot/weight, kalian bisa baca Pytorch Apa itu Operasi Linear, Bobot, dan Bias pada Algoritma CNN
Kalian juga bisa baca Penerapan Convolution 1D pada Sinyal