Compound Scaling در EfficientNet و انتخاب Architecture مناسب CNN
EfficientNet سه بُعد اصلی شبکه را همزمان Scale میکند: Depth، Width و Input Resolution. متن کتاب ضریب Scale عمومی را با φ و ضرایب سه بُعد را با α، β و γ نشان میدهد؛ بنابراین Depth، Width و Resolution بهترتیب تقریباً با αφ، βφ و γφ Scale میشوند. در متن، برای این ضرایب شرط α > 1، β > 1، γ > 1 و رابطهٔ تقریبی α + β² + γ² ≈ 2 ذکر شده است. مقدارهای مناسب به Architecture وابستهاند. نویسندگان برای EfficientNetB0 با φ=1 Grid Search اجرا کردند و به α=1.2، β=1.1 و γ=1.1 رسیدند؛ سپس با افزایش φ، مدلهای EfficientNetB1 تا EfficientNetB7 را ساختند.
با وجود این همه Architecture، انتخاب Model به چیزی که برای پروژه مهمتر است وابسته است: Accuracy، Model Size برای Mobile، سرعت Inference روی CPU یا GPU، تعداد Parameterها و محدودیت Memory. جدول 14-3 کتاب Modelهای Pretrained موجود در Keras را بر اساس Size مرتب میکند و Top-1/Top-5 Accuracy روی ImageNet، تعداد Parameter و زمان Inference برای Batch 32 را گزارش میکند. زمانهای جدول روی یک CPU قدرتمند AMD EPYC و Nvidia Tesla A100 اندازهگیری شدهاند، بنابراین عدد مطلق روی Hardware دیگر تغییر میکند ولی Trade-off نسبی مفید است.
جدول 14-3. مدلهای Pretrained موجود در Keras، مطابق متن منبع| Class name | Size (MB) | Top-1 acc | Top-5 acc | Params | CPU (ms) | GPU (ms) |
| MobileNetV2 | 14 | 71.3% | 90.1% | 3.5M | 25.9 | 3.8 |
| MobileNet | 16 | 70.4% | 89.5% | 4.3M | 22.6 | 3.4 |
| NASNetMobile | 23 | 74.4% | 91.9% | 5.3M | 27.0 | 6.7 |
| EfficientNetB0 | 29 | 77.1% | 93.3% | 5.3M | 46.0 | 4.9 |
| EfficientNetB1 | 31 | 79.1% | 94.4% | 7.9M | 60.2 | 5.6 |
| EfficientNetB2 | 36 | 80.1% | 94.9% | 9.2M | 80.8 | 6.5 |
| EfficientNetB3 | 48 | 81.6% | 95.7% | 12.3M | 140.0 | 8.8 |
| EfficientNetB4 | 75 | 82.9% | 96.4% | 19.5M | 308.3 | 15.1 |
| InceptionV3 | 92 | 77.9% | 93.7% | 23.9M | 42.2 | 6.9 |
| ResNet50V2 | 98 | 76.0% | 93.0% | 25.6M | 45.6 | 4.4 |
| EfficientNetB5 | 118 | 83.6% | 96.7% | 30.6M | 579.2 | 25.3 |
| EfficientNetB6 | 166 | 84.0% | 96.8% | 43.3M | 958.1 | 40.4 |
| ResNet101V2 | 171 | 77.2% | 93.8% | 44.7M | 72.7 | 5.4 |
| InceptionResNetV2 | 215 | 80.3% | 95.3% | 55.9M | 130.2 | 10.0 |
| EfficientNetB7 | 256 | 84.3% | 97.0% | 66.7M | 1578.9 | 61.6 |
بزرگتر بودن Model معمولاً Accuracy را بالا میبرد، اما همیشه چنین نیست. کتاب بهطور مشخص اشاره میکند که EfficientNetB2 هم کوچکتر و هم دقیقتر از InceptionV3 است، ولی InceptionV3 روی CPU تقریباً دو برابر سریعتر است؛ همچنین InceptionResNetV2 روی CPU سریع است و ResNet50V2 و ResNet101V2 روی GPU Latency بسیار خوبی دارند. بنابراین تصمیم نهایی باید بر اساس معیار Deployment واقعی گرفته شود، نه صرفاً Accuracy.
پیادهسازی ResNet-34 با Keras
ResNet را میتوان با یک Custom Layer کوتاه پیادهسازی کرد. Residual Unit دو Conv3×3 دارد و اگر Stride یا تعداد Filter تغییر کند، Skip Path از Conv1×1 استفاده میکند:
from functools import partial
DefaultConv2D = partial(
tf.keras.layers.Conv2D,
kernel_size=3, strides=1, padding="same",
kernel_initializer="he_normal", use_bias=False)
class ResidualUnit(tf.keras.layers.Layer):
def __init__(self, filters, strides=1, activation="relu", **kwargs):
super().__init__(**kwargs)
self.activation = tf.keras.activations.get(activation)
self.main_layers = [
DefaultConv2D(filters, strides=strides),
tf.keras.layers.BatchNormalization(),
self.activation,
DefaultConv2D(filters),
tf.keras.layers.BatchNormalization()
]
self.skip_layers = []
if strides > 1:
self.skip_layers = [
DefaultConv2D(filters, kernel_size=1, strides=strides),
tf.keras.layers.BatchNormalization()
]
def call(self, inputs):
Z = inputs
for layer in self.main_layers:
Z = layer(Z)
skip_Z = inputs
for layer in self.skip_layers:
skip_Z = layer(skip_Z)
return self.activation(Z + skip_Z)
سپس چند ResidualUnit با تعداد Filterهای ۶۴، ۱۲۸، ۲۵۶ و ۵۱۲ Stack میشوند. این مثال نشان میدهد Subclassing API میتواند Architecture برندهٔ Competition را با کد نسبتاً کوتاه بازسازی کند؛ با این حال در پروژهٔ واقعی معمولاً Model آمادهٔ Pretrained استفاده میشود.
استفاده از Modelهای Pretrained Keras
مثلاً ResNet-50 Pretrained روی ImageNet:
model = tf.keras.applications.ResNet50(weights="imagenet")
هر Architecture Preprocessing مورد انتظار خودش را دارد. برای ResNet از Function مربوط در tf.keras.applications.resnet50 استفاده میشود و سپس Predictionها با decode_predictions() به Labelهای قابلخواندن تبدیل میشوند:
images_resized = tf.image.resize(images, [224, 224])
inputs = tf.keras.applications.resnet50.preprocess_input(
images_resized * 255)
Y_proba = model.predict(inputs)
top_K = tf.keras.applications.resnet50.decode_predictions(
Y_proba, top=3)
Model هزار Probability برای Classهای ImageNet تولید میکند. اگر Dataset جدید Classهای متفاوت دارد، Top Classifier اصلی معمولاً کنار گذاشته میشود و Feature Extractor Reuse میشود.
Transfer Learning با Xception
مثال کتاب Dataset گلها را از TensorFlow Datasets Load میکند. Imageها Resize/Preprocess و برای Training Data Augmentation میشوند. سپس Xception Pretrained بدون Top Classification Layer Load میشود:
base_model = tf.keras.applications.Xception(
weights="imagenet", include_top=False)
avg = tf.keras.layers.GlobalAveragePooling2D()(base_model.output)
output = tf.keras.layers.Dense(n_classes, activation="softmax")(avg)
model = tf.keras.Model(inputs=base_model.input, outputs=output)
در شروع Training، Weightهای Base Model Freeze میشوند تا Random Classifier جدید Featureهای Pretrained را خراب نکند:
for layer in base_model.layers:
layer.trainable = False
بعد از Train شدن Layerهای جدید میتوان بخشی از Layerهای بالایی Base را Unfreeze کرد و با Learning Rate بسیار پایین Fine-Tune کرد. هرچه Dataset جدید کوچکتر باشد، Fine-Tuning باید محافظهکارانهتر باشد.
Classification همراه Localization
برای یک Object در Image، علاوه بر Class میتوان Bounding Box را نیز Predict کرد. یک Representation رایج چهار مقدار است، مثلاً Center X/Y و Width/Height، یا مختصات دو Corner. بنابراین Model دو Head دارد: Head طبقهبندی با Softmax و Head Regression با چهار Output.
برای Training Bounding Box میتوان MSE یا Huber Loss استفاده کرد، اما Metric مهمتر Intersection over Union یا IoU است:
IoU = area(intersection) / area(union)
شکل 14-24. معیار IoU برای Bounding Box
IoU برابر ۱ یعنی Box کاملاً منطبق و صفر یعنی هیچ همپوشانی. در Keras/TensorFlow Operationهای لازم برای Box و IoU موجود است. برای Training واقعی باید Dataset دارای Annotation Bounding Box باشد؛ Labeling Manual میتواند با ابزارهای Annotation یا سرویسهای Crowdsourcing انجام شود. با چند Object در یک Image مسئله به Object Detection تبدیل میشود که در مقالهٔ بعد بررسی میشود.