Operasi Convolution pada Pytorch – Filter – Kernel – Weight

By | May 6, 2024
568 Views

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.
See also  Backend Deep Learning dengan MPS GPU Apple M1

Persamaan matematika untuk operasi konvolusi dalam PyTorch dapat dinyatakan sebagai berikut:

Misalkan

  • X adalah input,
  • K adalah kernel,
  • Y adalah output,
  • b adalah bias,
  • f adalah fungsi aktivasi (opsional), dan ∗∗ menunjukkan operasi konvolusi. Dalam kasus 2D, kita dapat menulisnya sebagai:

Y=f(X∗K+b)

Di mana:

  • X adalah tensor input dengan dimensi (N,C_{in},H_{in},W_{in}),
    • di mana (N adalah ukuran batch,
    •  C_{in} adalah jumlah channel input, dan
    •  H_{in} serta
    •  W_{in} adalah tinggi dan lebar gambar.
  • K  adalah tensor kernel dengan dimensi (C_{out},C_{in},H_{k},W_{k})
    • di mana C_{out} adalah jumlah channel output, dan
      • H_{k} serta W_{k} adalah tinggi dan lebar kernel.
  • Y adalah tensor output dengan dimensi (N,Cout,Hout,Wout),
    • di mana H_{out} dan W_{out} adalah tinggi dan lebar output.
  • b adalah bias dengan dimensi C_{out} yang di-broadcast pada setiap elemen dalam output.
  • f adalah fungsi aktivasi seperti ReLU atau tanh.

Operasi konvolusi dilakukan dengan menggeser kernel K melintasi tensor input X 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

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.

See also  Nilai Loss yang turun tajam setelah loading Checkpoint

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.

See also  Perbandingan Hasil Segmentasi Otsu vs UNet Deep Learning

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