معماری RegNet
آموزش‌های پیشرفته هوش مصنوعیبینایی ماشین

معرفی معماری RegNet؛ ساده، سریع و قدرتمند

0

در مقاله پیش‌رو به بررسی معماری RegNet می‌پردازیم.

مرحله اول معماری مولد ResNet

در ابتدا ساختار کلی ResNet را بررسی می‌کنیم. بررسی کردن ساختار ResNet به ما کمک می‌کند مدل‌های AnyNet که در مقاله مذکور به آن‌ها اشاره شده را ایجاد کنیم.

معماری RegNet

تصویر ۱ – معماری پایه ResNet

همان‌گونه که در تصویر ۱ نشان داده شده، معماری ResNet از یک بلاک Stem، یک بلاک Layer و یک بلاک Head تشکیل شده است.

Stem

Stem از یک لایه پیچشی با stride=2 و سایز فیلتر ۳، نرمال سازی دسته ای Batch Normalization (BN) و فعال ساز ReLU تشکیل شده است. تعداد فیلترهای خروجی بسته به الزمات (بلوک قرمز در تصویر ۱) می‌تواند ۳۲ یا ۶۴ فیلتر باشد.

Layer

معماری RegNet

تصویر ۲ – زنجیره بلوک‌های residual موجود در Layer Block ( بلوک زردرنگ در تصویر ۱)

  • Layer Block شامل زنجیره‌ای از بلوک‌های residual است (بلوک آبی‌رنگ در تصویر ۲). تعداد بلوک‌های موجود در یک لایه را با d (Depth یا همان عمق) نشان می‌دهیم. تعداد کانال‌های موجود در هر لایه در سرتاسر یک Layer Block ثابت باقی می‌ماند. تعداد کانال‌های موجود در هر لایه با w ( width یا همان پهنا) نشان داده می‌شود.
  • هر لایه یک نگاشت ویژگی W1×R×R را به عنوان ورودی دریافت می‌کند ( همان‌گونه که در تصویر ۲ نشان داده شده است، اولین بلوک هر لایه کانال‌های W1 را به W2 تبدیل می‌کند و سپس تمامی بلوک‌ها همان تعداد کانال W2 را به عنوان خروجی ارائه می‌دهند) و همان‌گونه که در تصویر ۲ نشان داده شده است نگاشت ویژگی W2×R/2×R/2 را به عنوان خروجی ارائه می‌دهد.
  • همان‌گونه که در تصویر مقابل نشان داده شده است، بلوک residual ( بلوک آبی در تصویر ۲) ساختاری گلوگاه Bottleneck یا ساده خواهد داشت.

 

معماری RegNet

تصویر ۳- نمایش ساختار ساده (سمت چپ) و گلوگاه (سمت راست) در تک تک بلوک‌های residual ( بلوک آبی در تصویر ۲)

  • از ساختار کاهش نمونه داده شده Downsample فقط در اولین بلوک residual هر لایه استفاده می‌شود. و همان‌گونه که در تصویر ۳ نشان داده شده است، ساختار سایر لایه‌ها گلوگاه خواهد بود.

نکته: با توجه به این‌که ساختار گلوگاه، معماری پایه AnyNet در نظر گرفته می‌شود، در ادامه این مقاله فقط به بررسی این ساختار می‌پردازیم.

  • همان‌گونه که در تصویر ۳ نشان داده شده است، در این معماری از دو متغیر استفاده می‌شود. متغیر اول نسبت گلوگاه b است و متغیر دوم اندازه گروه پیچشی g است.
  • از متغیر نسبت گلوگاه به منظور کاهش تعداد کانال‌های نگاشت ویژگی ورودی استفاده می‌شود و از متغیر اندازه گروه برای پردازش گروهی پیچشی به صورت موازی استفاده می‌شود.

Head

  • Head شامل ساختاری ساده از AveragePool2D و یک لایه کامل متصل است. طبقه‌بندی مدل در این بخش اتفاق می‌افتد.

نکته: با تغییر پارامترهای d، w، نسبت گلوگاه b و اندازه گروه g می‌توان مدل‌های متفاوتی از AnyNet ساخت.

مرحله دوم ساخت مدل‌های جمعیتی AnyNet

در این مرحله ساختار کلی AnyNet ساخته می‌شود.

  • نویسندگان مقاله طراحی فضاهای طراحی شبکه، از ساختار مولد معماری ResNet برای شناخت و طراحی جمعیت‌های مختلف مدل‌های AnyNet استفاده کرده‌اند.
  • با تغییر چهار پارامتری که در مرحله اول به آن‌ها اشاره شد می‌توانیم معماری‌های گوناگونی از AnyNet ایجاد کنیم. در ادامه فرایند پیکربندی پارامترها به همراه مقادیر ورودی توضیح داده شده است.

نویسندگان این مقاله در حوزه هوش مصنوعی از میان تمامی ترکیبات ممکن و با نمونه‌گیری یکنواخت Log uniform sampling از چهار پارامتر یادشده ، N ( = 500 در مقاله) مدل برای هر یک از خانواده‌های AnyNet ایجاد می‌کنند.

مجموع درجه آزادی مدل‎های AnyNetX، ۱۶ است (با استفاده از چهار پارامتر مذکور می‌توان در چهار لایه و هر لایه به صورت جداگانه تغییر ایجاد کرد).

  • در مقاله مذکور پنج مدل AnyNet معرفی شده است. در این قسمت هر یک از این مدل‌ها را به صورت جداگانه معرفی می‌کنیم.
  1. AnyNetXA
  • AnyNetXA معماری مولد و بدون محدودیت ResNet است (مرحله اول) و تمامی مقادیر ممکن چهار پارامتر یادشده را شامل می‌شود.
  • مجموع ساختارهای ممکن در AnyNetXA برابر با ۴( ۶ * ۳* ۱۲۸* ۱۶) است که به طور تقریبی برابر با ۱۰۱۸ ساختار است.
  1. AnyNetXB
  • برای ساخت مدل AnyNetXB می‌توانیم از مدل AnyNetXA زیر استفاده کنیم

b(Layer 1) =b(Layer 2) =b(Layer 3) =b(Layer 4)

  • مجموع ساختارهای ممکن در AnyNetXB برابر با ۳* ۴ (۶ * ۱۲۸ * ۱۶) است که به طور تقریبی برابر با ۱۰۱۶ است.
  1. AnyNetXC
  • AnyNetXC را می‌توان با استفاده از AnyNetXB به صورت زیر ایجاد کنیم

g(Layer 1) =g(Layer 2) =g(Layer 3) =g(Layer 4)

  • تعداد کل ساختارهای ممکن در AnyNetXC برابر با ۶* ۳* ۴(۱۲۸ * ۱۶) است که به طور تقریبی برابر با ۱۰۱۴ ساختار است.
  1. AnyNetXD
  • AnyNetXD را می‌توان با استفاده از AnyNetXC به صورت زیرساخت

w(Layer 1) ≤w(Layer 2) ≤w(Layer 3) ≤w(Layer 4).

  • تعداد کل ساختارهای ممکن در AnyNetXD برابر با ۴/ ۶ * ۳ ۴(۱۲۸ * ۱۶) است که به طور تقریبی برابر با ۱۰۱۳ ساختار است.
  1. AnyNetXE
  • AnyNetXE را می‌توان با استفاده از AnyNetXD به صورت زیر ایجاد کنیم

d(Layer 1) ≤ d(Layer 2) ≤ d(Layer3)≤d(Layer 4)(Not always for the last layer).

  • تعداد کل ساختارهای ممکن در AnyNetXE = (4) / 6 * 3 ۴(۱۲۸ * ۱۶) است که به طور تقریبی برابر با ۱۰۱۱ ساختار است.

نکته: با در نظر گرفتن یعضی از محدودیت ها، نویسندگان مقاله توانسته اند فضای طراحی را به O(10۷) نسبت به مدل AnyNetXA model کاهش دهند.

مرحله سوم ساخت مدل‌های RegNet  – RegNetX و RegNetY

در این مرحله می‌توانیم معماری‌های RegNetX و RegNetY را ایجاد کنیم.

  • نویسندگان این مقاله از مدل‌های AnyNetXE برای ایجاد RegNetX و RegNetY استفاده کردند.
  • نویسندگان این مقاله پس از اعمال مقادیر مختلف به پارامترها و بررسی دقت آن‌ها متوجه ترندها و مجموعه‌ای از معادلات مشابه شدند که به یافتن بهترین مدل RegNetX با استفاده از ورودی پیکربندی‌هایی که به آن‌ها اشاره شده کمک می‌کند.
  1. پهنای اولیه Degree of freedom w0: پهنای اولین لایه در معماری ResNet است.
  2. پارامتر شیب Initial width wa: برای پیدا کردن روند خطی بهترین مدل‌ها استفاده می‌شود.
  3. پارامتر کمی کردن Slope parameter wm: از این پارامتر برای کمی‌ کردن روند خطی استفاده می‌شود.
  4. عمق شبکه D: مجموع عمق تمامی لایه‌ها di{ i= 1,2,3,4}
  5. نسبت گروه و گلوگاه g و b
ایجاد مدل RegNetX

نکته: در این مطلب قصد داریم معماری RegNet را توضیح دهیم و به همین دلیل وارد جزئیات معادله نمی‌شویم.

  • برای تکمیل کردن معماری RegNet به عمق d و پهنای w هر چهار لایه نیاز داریم. چگونه می‌توانیم عمق و پهنای چهار لایه را به دست آوریم؟ عمق d و پهنا w را می‌توانیم با استفاده از سه معادله کوچک محاسبه کنیم.
  • با ذکر یک مثال کوچک مقادیر یادشده را محاسبه می‌کنیم.
۱- یافتن پهناهای u برای یک شیب مشخص wa و پارامتر پهنای اولیه w0.

معماری RegNet

معادله ۱. معادله پهناهای پارامترسازی‌شده

۲- پیدا کردن اندازه احتمالی بلوک s بر اساس پهنای محاسبه شده u، پهنای اولیه w0 و پارامتر تدریجی‌شده Quantize wm.

معماری RegNet

معادله ۲. معادله بلوک‌های پارامتر‌سازی شده

۳ – پیدا کردن پهناهای w کمی‌شده از طریق گِرد کردن Rounding اندازه‌های بلوک پارامتر‌سازی‌شده s. البته باید مطمئن شویم که پهناهای w تدریجی‌شده بر ۸ تقسیم ‌پذیر هستند.

معماری RegNet

معادله ۳. پهناهای w تدریجی‌شده از پهناهای u ممکن

۴ – پیدا کردن فهرست عمق d. برای پیدا کردن عمق d، تعداد دفعات وقوع هر یک از پهناهای w تدریجی‌شده را محاسبه می‌کنیم. برای محاسبه فهرست نهایی پهنای w، فقط از مقادیر منحصر به فرد استفاده می‌کنیم.
۵ – فهرست پهنای w ایجاد شده باید مضرب اندازه گروه g باشد. پهناهای ایجادشده ممکن است به دلیل نسبت گلوگاه b، مغایر باشند. برای تصحیح آن‌ها، مطابق مراحل زیر عمل کنید.
۶ – فهرست نهایی پهناهای w و عمق d ایجاد شد. در این مرحله، مقادیر w، d، b و g را به معماری ResNet وارد می‌کنیم تا مدل ReNetX ایجاد شود.

  • همزمان با افزایش تعداد پهنا و عمق‌ها، مدت زمانی که مدل برای محاسبه نیاز دارد، نیز افزایش پیدا می‌کند. مدلی که ایجاد کردیم RegNetX 200MF است. منظور از ۲۰۰MF، ۲۰۰ میلیون عملیات ممیز شناور در ثانیه FLOPs است.
  • با مراجعه به مقاله اصلی می‌توانید RegNetX-ABC MF/ GF را مشاهده کنید.

ایجاد مدل RegNetY

  • تفاوت مدل RegNetX و RegNetY در این است که در مدل RegNetY یک لایه Squeeze و Excitation افزوده می‌شود. RegNetY = RegNetX + SE
  • همان‌گونه که در تصویر مقابل نشان داده شده است، پس از هر لایه پیچشی ۳×۳ در بلوک residual معماری ResNet، ماژول توجه متصل می‌شود.
معماری RegNet

تصویر ۴. ماژول SE در بلوک residual

  • همزمان با افزایش تعداد پهنا و عمق‌ها، مدت زمانی که مدل برای محاسبه نیاز دارد، نیز افزایش پیدا می‌کند. مدلی که ایجاد کردیم RegNetX 200MF است. منظور از ۲۰۰MF، ۲۰۰ میلیون عملیات ممیز شناور در ثانیه[۱] است.
  • با مراجعه به مقاله اصلی می‌توانید RegNetX-ABC MF/ GF را مشاهده کنید.

 

ایجاد مدل RegNetY

  • تفاوت مدل RegNetX و RegNetY در این است که در مدل RegNetY یک لایه Squeeze و Excitation افزوده می‌شود. RegNetY = RegNetX + SE
  • همان‌گونه که در تصویر مقابل نشان داده شده است، پس از هر لایه پیچشی ۳×۳ در بلوک residual معماری ResNet، ماژول توجه متصل می‌شود.
معماری RegNet

تصویر ۵. ماژول SE به‌کاررفته در RegNetY

  • مراحل ایجاد RegNetY و RegNetX یکسان هستند. تنها تفاوت این دو معماری در این است که در RegNetY پارامتر جدید Se-ration q افزوده می‌شود. Range: 0 ≤ q ≤ ۱.
مرحله چهارم پیاده‌سازی پای تورچ مدل‌های RegNetX/ RegNetY
۱

”’

۲Name: Shreejal Trivedi
۳
۴Description: Generation Script of RegNetX and RegNetY models
۵
۶References: Designing Network Design Spaces from Facebook AI March’2020
۷
۸”’
۹
۱۰#Importing Libraries
۱۱import torch
۱۲import torch.nn as nn
۱۳import torch.nn.functional as F
۱۴import numpy as np
۱۵import argparse
۱۶
۱۷#Downsampling used in first bottleneck block of every layer in RegNet
۱۸class Downsample(nn.Module):
۱۹  def __init__(self, in_filters, out_filters, stride):
۲۰    super(Downsample, self).__init__()
۲۱
۲۲    self.conv1x1 = nn.Conv2d(in_filters, out_filters, kernel_size=1, stride=stride, bias=False)
۲۳    self.bn = nn.BatchNorm2d(out_filters)
۲۴
۲۵  def forward(self, x):
۲۶    return self.bn(self.conv1x1(x))
۲۷
۲۸ 
۲۹ #SE Attention Module for RegNetY
۳۰class SqueezeExcitation(nn.Module):
۳۱
۳۲    def __init__(self, in_filters, se_ratio):
۳۳        super(SqueezeExcitation, self).__init__()
۳۴       
۳۵        #Calculate bottleneck SE filters
۳۶        out_filters = int(in_filters * se_ratio)
۳۷
۳۸        #Average Pooling Layer
۳۹        self.avgpool = nn.AdaptiveAvgPool2d(output_size=1)
۴۰       
۴۱        #Squeeze
۴۲        self.conv1_1x1 = nn.Conv2d(in_filters, out_filters, kernel_size=1, bias=True)
۴۳       
۴۴        # Excite
۴۵        self.conv2_1x1 = nn.Conv2d(out_filters, in_filters, kernel_size=1, bias=True)
۴۶
۴۷    def forward(self, x):
۴۸     
۴۹        out = self.avgpool(x)
۵۰        out = F.relu(self.conv1_1x1(out))
۵۱        out = self.conv2_1x1(out).sigmoid()
۵۲        out = x * out
۵۳        return out
۵۴ 
۵۵#Bottleneck Residual Block in Layer
۵۶class Bottleneck(nn.Module):
۵۷  def __init__(self, in_filters, out_filters, bottleneck_ratio, group_size, stride=1, se_ratio=0):
۵۸    super(Bottleneck, self).__init__()
۵۹
۶۰    #۱×۱ Bottleneck Convolution Block
۶۱    bottleneck_filters = in_filters // bottleneck_ratio
۶۲    self.conv1_1x1 = nn.Conv2d(in_filters, bottleneck_filters, kernel_size=1, bias=False)
۶۳    self.bn1 = nn.BatchNorm2d(bottleneck_filters)
۶۴
۶۵    #۳×۳ Convolution Block with Group Convolutions —> ResNext alike structure
۶۶    num_groups = bottleneck_filters // group_size
۶۷    self.conv2_3x3 = nn.Conv2d(bottleneck_filters, bottleneck_filters, kernel_size=3, stride=stride, padding=1, groups=num_groups, bias=False)
۶۸    self.bn2 = nn.BatchNorm2d(bottleneck_filters)
۶۹
۷۰    #Squeeze-Exictation Block: Only for RegNetY
۷۱    self.se_module = SqueezeExcitation(bottleneck_filters, se_ratio) if se_ratio < 1 else None
۷۲
۷۳    #Downsample if stride=2
۷۴    self.downsample = Downsample(in_filters, out_filters, stride) if stride != 1 or in_filters != out_filters else None
۷۵
۷۶    #۱×۱ Convolution Block
۷۷    self.conv3_1x1 = nn.Conv2d(bottleneck_filters, out_filters, kernel_size=1, bias=False)
۷۸    self.bn3 = nn.BatchNorm2d(out_filters)
۷۹
۸۰  def forward(self, x):
۸۱    residual = x
۸۲   
۸۳    out = F.relu(self.bn1(self.conv1_1x1(x)))
۸۴    out = F.relu(self.bn2(self.conv2_3x3(out)))
۸۵
۸۶    if self.se_module is not None:
۸۷      out = self.se_module(out)
۸۸   
۸۹    out = self.bn3(self.conv3_1x1(out))
۹۰
۹۱    if self.downsample is not None:
۹۲      residual = self.downsample(x)
۹۳   
۹۴    out += residual
۹۵    out = F.relu(out)
۹۶
۹۷    return out
۹۸ 
۹۹class Stem(nn.Module):
۱۰۰  def __init__(self, out_filters, in_filters=3):
۱۰۱    super(Stem, self).__init__()
۱۰۲
۱۰۳    self.conv3x3 = nn.Conv2d(in_filters, out_filters, kernel_size=3, stride=2, padding=1, bias=False)
۱۰۴    self.bn = nn.BatchNorm2d(out_filters)
۱۰۵
۱۰۶  def forward(self, x):
۱۰۷    return F.relu(self.bn(self.conv3x3(x)))
۱۰۸ 
۱۰۹class Layer(nn.Module):
۱۱۰  def __init__(self, in_filters, depth, width, bottleneck_ratio, group_size, se_ratio):
۱۱۱    super(Layer, self).__init__()
۱۱۲   
۱۱۳    self.layers = []
۱۱۴
۱۱۵    #Total bottleneck blocks in a layer = Depth d
۱۱۶    for i in range(depth):
۱۱۷      stride = 2 if i == 0 else 1
۱۱۸      bottleneck = Bottleneck(in_filters, width, bottleneck_ratio, group_size, stride, se_ratio)
۱۱۹      self.layers.append(bottleneck)
۱۲۰      in_filters = width
۱۲۱
۱۲۲    self.layers = nn.Sequential(*self.layers)
۱۲۳ 
۱۲۴  def forward(self, x):
۱۲۵    out = self.layers(x)
۱۲۶    return out
۱۲۷ 
۱۲۸class Head(nn.Module):
۱۲۹
۱۳۰  def __init__(self, in_filters, classes):
۱۳۱
۱۳۲    super(Head, self).__init__()
۱۳۳
۱۳۴    self.avgpool = nn.AdaptiveAvgPool2d(output_size=1)
۱۳۵    self.fc = nn.Linear(in_filters, classes)
۱۳۶     
۱۳۷
۱۳۸  def forward(self, x):
۱۳۹
۱۴۰      out = self.avgpool(x)
۱۴۱      out = torch.flatten(out, 1)
۱۴۲      out = self.fc(out)
۱۴۳      return out
۱۴۴   
۱۴۵class RegNet(nn.Module):
۱۴۶  def __init__(self, paramaters, classes=2):
۱۴۷    super(RegNet, self).__init__()
۱۴۸
۱۴۹    #Model paramater initialization
۱۵۰    self.in_filters = 32
۱۵۱    self.w, self.d, self.b, self.g, self.se_ratio = parameters
۱۵۲    self.num_layers = 4
۱۵۳
۱۵۴    #Stem Part of the generic ResNet/ResNeXt architecture
۱۵۵    self.stem = Stem(self.in_filters)
۱۵۶    self.body = []
۱۵۷
۱۵۸    for i in range(self.num_layers):
۱۵۹      layer = Layer(self.in_filters, self.d[i], self.w[i], self.b, self.g, self.se_ratio)
۱۶۰      self.body.append(layer)
۱۶۱      self.in_filters = self.w[i]
۱۶۲   
۱۶۳    #Body Part: Four Layers containing bottleneck residual blocks
۱۶۴    self.body = nn.Sequential(*self.body)
۱۶۵
۱۶۶    #Head Part: Classification Step FC + AveragePool
۱۶۷    self.head = Head(self.w[-1], classes)
۱۶۸
۱۶۹  def forward(self, x):
۱۷۰
۱۷۱    out = self.stem(x)
۱۷۲    out = self.body(out)
۱۷۳    out = self.head(out)
۱۷۴    return out
۱۷۵ 
۱۷۶def generate_parameters_regnet(D, w0, wa, wm, b, g, q):
۱۷۷
۱۷۸  u = w0 + wa * np.arange(D) # Equation 1
۱۷۹  s = np.log(u / w0) / np.log(wm) # Equation 2
۱۸۰
۱۸۱  s = np.round(s) #Rounding the possible block sizes s
۱۸۲  w = w0 * np.power(wm, s) # Equation 3
۱۸۳  w = np.round(w / 8) * 8 # Make all the width list divisible by 8
۱۸۴
۱۸۵  w, d = np.unique(w.astype(np.int), return_counts=True) #Finding depth and width lists.
۱۸۶
۱۸۷  gtemp = np.minimum(g, w//b)
۱۸۸  w = (np.round(w // b / gtemp) * gtemp).astype(int) #To make all the width compatible with group sizes of the 3×3 convolutional layers
۱۸۹  g = np.unique(gtemp // b)[0]
۱۹۰
۱۹۱  return (w, d, b, g, q)
۱۹۲
۱۹۳if __name__ == ‘__main__’:
۱۹۴
۱۹۵  parser = argparse.ArgumentParser(description=”RegNetX | RegNetY Models Generation”)
۱۹۶
۱۹۷  parser.add_argument(‘-D’, default=13, type=int, help=’Network Depth: Range::[12, 13, …, 28]’)
۱۹۸  parser.add_argument(‘-w0′, default=24, type=int, help=’Initial Width of the First Layer > 0’)
۱۹۹  parser.add_argument(‘-wa’, default=36, type=int, help=’Slope Parameter: Range::[0, 1, 2, …, 255]’)
۲۰۰  parser.add_argument(‘-wm’, default=2.5, type=float, help=’Quantization Parameter: Range::[1.5, 3]’)
۲۰۱

  parser.add_argument(‘-b’, default=1, type=int, help=’Bottleneck Ratio: Range::{1, 2, 4}’)

۲۰۲  parser.add_argument(‘-g’, default=8, type=int, help=’Group Size: Range::{1, 2, 4, 8, 16, 32} OR {16, 24, 32, 40, 48, 56, 64}’)
۲۰۳  parser.add_argument(‘-q’, default=1, type=float, help=’0 <= SE Ratio < 1′)
۲۰۴  args = parser.parse_args()
۲۰۵
۲۰۶  parameters = generate_parameters_regnet(args.D, args.w0, args.wa, args.wm, args.b, args.g, args.q)
۲۰۷  model = RegNet(parameters)

آموزش هوش مصنوعی با تقلید از مغز انسان

مقاله قبلی

انقلاب هوش مصنوعی در پزشکی

مقاله بعدی

شما همچنین ممکن است دوست داشته باشید

نظرات

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *