နားလည်ထားရမယ့် အချက်
Convolutional network တွေကို ပိုမိုနက်ရှိုင်းအောင် (deeper) တည်ဆောက်လေလေ၊ accuracy ကလည်း ပိုမိုကောင်းမွန်လာမည်လို့ မျှော်လင့်ရပါလိမ့်မယ် — layer ပိုများလေလေ representational power ပိုများလေပါပဲ။ ဒါပေမယ့် လက်တွေ့မှာတော့ သုတေသီတွေက ဆန့်ကျင်ဘက်ဖြစ်ရပ်ကို တွေ့ရှိခဲ့ကြပါတယ်— depth တစ်ခုကို ကျော်လွန်သွားရင် training accuracy ကိုယ်တိုင်ဆိုးလာတာကို တွေ့ရပါတယ်၊ overfitting ကြောင့်လည်း မဟုတ်ဘူး (test accuracy ကလည်း ဆိုးလာတာချည်းပဲ) — အလွန်နက်ရှိုင်းတဲ့ plain network တွေဟာ optimize လုပ်ဖို့ တကယ်ပဲ ခက်ခဲလာလို့ပါပဲ။ ဒါကို degradation problem လို့ခေါ်ပါတယ်။ instinct အရဆိုရင် deeper network တစ်ခုဟာ shallower network တစ်ခုနဲ့ အနည်းဆုံး တူညီရမှာပါ — extra layer တွေက identity function ကိုပဲ သင်ယူပြီး input ကို မပြောင်းလဲဘဲ ဖြတ်သန်းခွင့်ပြုလိုက်ရုံသာ လိုအပ်ပါတယ်။ ဒါပေမယ့် nonlinear convolution-ReLU layer အထပ်ထပ်ကို ဖြတ်ပြီး identity mapping ကို သင်ယူဖို့က ထင်ထားတာထက် ခက်ခဲပါတယ်— gradient တွေဟာ multiplication နဲ့ nonlinearity အများကြီးကို ဖြတ်သန်းရပြီး၊ numerical drift အသေးအမွှားတွေက စုပေါင်းလာကာ optimizer က identity solution ကို ယုံကြည်စွာ ရှာမတွေ့နိုင်တော့ပါဘူး။
ResNet ရဲ့ ဖြေရှင်းချက်ကတော့ block တစ်ခုချင်းစီကို လိုချင်တဲ့ mapping H(x) အပြည့်အစုံကို သင်ယူခိုင်းမယ့်အစား၊ residual F(x) = H(x) - x ကိုသာ သင်ယူခိုင်းပြီး၊ skip connection တစ်ခုမှတစ်ဆင့် original input ကို ပြန်ပေါင်းထည့်ခြင်းပါပဲ — output = F(x) + x။ အခုတော့ 'ဘာမှမလုပ်ခြင်း' ဖြေရှင်းချက်ဟာ ရိုးရှင်းသွားပါတယ်— block ကို weight တွေကို zero ဆီကို တွန်းလိုက်ရုံပါပဲ၊ ဒါက gradient descent အတွက် အလွန်ကောင်းမွန်တဲ့ အလုပ်တစ်ခုပါ။ ပိုအရေးကြီးတာက skip connection ဟာ backpropagation လုပ်နေစဉ်အတွင်း gradient တွေကို earlier layer တွေဆီ တိုက်ရိုက်ပြီး အဟန့်အတားမရှိ ပြန်ရောက်စေတဲ့ လမ်းကြောင်းတစ်ခု ပေးထားပါတယ်— x term ရဲ့ derivative ဟာ အတိအကျ 1 ဖြစ်နေတဲ့အတွက်၊ convolutional path ကနေ ဖြတ်လာတဲ့ gradient ဘယ်လောက်ပဲ သေးငယ်နေပါစေ၊ earlier layer တွေဆီ အားအပြည့်ရှိတဲ့ gradient signal တစ်ခုတော့ ဆက်ရောက်ရှိနေပါတယ်။ လှေကားထစ် (conv layer တွေ) က ပိတ်နေရင်တောင် တစ်ခါတည်း ဆင်းနိုင်တဲ့ express elevator တစ်ခု အနားမှာ ရှိနေသလိုပါပဲ။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Tutorial Platform မှာဆိုရင် ResNet-style backbone ဟာ profile avatar moderation pipeline အတွက် အသင့်တော်ဆုံးပါပဲ— residual block တွေက degradation problem မရှိဘဲ တကယ့် deep feature extractor ကို train လုပ်ခွင့်ပေးထားတဲ့အတွက်၊ platform ဟာ upload လုပ်လိုက်တဲ့ avatar image တိုင်းက ကြွယ်ဝပြီး ခွဲခြားနိုင်စွမ်းရှိတဲ့ embedding တွေကို ထုတ်ယူနိုင်ပြီး၊ known-flagged image များ (ကိုယ်ထည်ဖော်ပုံများ၊ copyright ရှိ logo များ၊ spam pattern များ) ဘဏ်တစ်ခုနဲ့ nearest-neighbor similarity သုံးပြီး နှိုင်းယှဉ်နိုင်ပါတယ်— shallow CNN တစ်ခုရဲ့ ရိုင်းစိုင်းတဲ့ feature တွေက လွတ်သွားနိုင်တဲ့ near-duplicate နဲ့ ပြင်ဆင်ထားတဲ့ ပုံများကို ဖမ်းမိစေပါတယ်။
အတူတူ စမ်းရေးကြည့်မယ်
import torch
import torch.nn as nn
import torch.nn.functional as F
class ResidualBlock(nn.Module):
def __init__(self, channels):
super().__init__()
self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
def forward(self, x):
out = F.relu(self.conv1(x))
out = self.conv2(out)
out = F.relu(out + x)
return out
torch.manual_seed(0)
block = ResidualBlock(channels=16)
images = torch.randn(4, 16, 32, 32) # fake batch of 4 feature maps
output = block(images)
print(output.shape)torch.Size([4, 16, 32, 32]) — residual block ဟာ channel အရေအတွက် (16) နဲ့ spatial dimension (32x32) နှစ်ခုစလုံးကို input အတိုင်း ထိန်းသိမ်းထားပါတယ်၊ convolution နှစ်ခုစလုံးဟာ padding=1 သုံးထားတဲ့အတွက် feature map size ပြောင်းလဲမသွားဘဲ၊ skip connection အတွက် addition အလုပ်လုပ်ဖို့ shape တွေ အတိအကျ ကိုက်ညီဖို့ လိုအပ်ပါတယ်။၅ မိနစ် စမ်းကြည့်
ResidualBlock ကို conv1 မှာ stride=2 သုံးအောင် (spatial size ကို ထက်ဝက်လျှော့ချအောင်) ပြင်ဆင်ပြီး၊ input ကိုလည်း stride=2 နဲ့ downsample လုပ်မယ့် 1x1 convolution 'shortcut' branch တစ်ခု ထပ်ထည့်ပါ၊ addition မလုပ်ခင် main path ရဲ့ shape နဲ့ ဆက်ကိုက်ညီနေအောင်ပါ — ဒါဟာ block တစ်ခုက spatial size ဒါမှမဟုတ် channel count ပြောင်းလဲတိုင်း တကယ့် ResNet implementation တွေ သုံးနေတဲ့ projection-shortcut နည်းလမ်းအတိအကျပါပဲ။
သတိလေးတစ်ချက်
conv1 ဒါမှမဟုတ် conv2 က channel အရေအတွက် ဒါမှမဟုတ် spatial size ကို ပြောင်းလဲပေမယ့် ကိုက်ညီတဲ့ projection shortcut မထည့်ဘဲ skip connection ကို ထည့်လိုက်ရင် `+ x` အဆင့်မှာ shape-mismatch error တက်ပါလိမ့်မယ်။
ဒုတိယ ReLU ကို မေ့သွားခြင်း (addition ပြီးမှမဟုတ်ဘဲ addition မလုပ်ခင် သုံးလိုက်ခြင်း) ဟာ block ရဲ့ အလုပ်လုပ်ပုံကို ပြောင်းလဲစေပါတယ်— standard ResNet design မှာ nonlinearity ကို residual addition ပြီးမှသာ သုံးပါတယ်၊ မလုပ်ခင်မှာ မဟုတ်ပါဘူး။
Wikipedia — Residual neural network — Computer Vision