- إعداد: م. نور شرباتي
- التّدقيق العلمي: م. محمّد سرميني، م. رامي عقّاد
تشكّل الشّعارات العلامة المميّزة للشّركات والجهات العامّة، حيث تشكّل عمليّة كشفها والتّنقيب عنها ضرورة مهمّة تفيد في التّطبيقات الحياتيّة؛ كالنّقل الذّكيّ وكشف الانتهاكات ومراقبة مواقع التّواصل الاجتماعيّ، كما أن اكتشاف الشّعار في الصّور الحقيقيّة يمكن أن يمثّل تحديًّا كبيرًا لأنّ أغلب العلامات التّجاريّة تمتلك العديد من الشّعارات المختلفة والمقاييس المتنوّعة، وتغيرات في الإضاءة، والحجم، والدّقة، كما تظهر ببعض الصور بتشوّهات في الشّكل إلّا أنّ عمليّة كشف وتصنيف الشّعار تتطلّب خوارزميّات كشف أغراض فائقة الذّكاء، بحيث تكشف الشّعار مهما كان تموضعه أو حجمه أو دقّته. ومن هذه الأهميّة تبرز خوارزميّة يولو YOLO بإصداراتها المختلفة التي شكّلت نقطة تحوّل مهمّة في مجال الكشف عن الأغراض وتصنيفها، في هذا المقال سنقوم بشرح مثال عمليّ عن كشف الشّعارات باستخدام خوارزميّة يولو الإصدار السّابع.
مقدّمة:
تتكوّن الشّعارات عادةً من نصوص أو أشكال أو صور أو مزيج منها، يفيد اكتشاف وتحديد الشّعار مجموعة واسعة من التّطبيقات المهمّة في مجالات مختلفة في الحياة اليوميّة، مثل النّقل الذّكيّ ومراقبة وسائل التّواصل الاجتماعيّ واكتشاف الانتهاكات.
تتمثّل المهمّة الرّئيسيّة لاكتشاف الشّعار في تحديد موقع شعار معيّن في الصّور/مقاطع الفيديو والتّعرّف عليه.
قد تبدو مهمّة اكتشاف وتحديد الشّعار كمهمّة من مهمّات كشف وتحديد الأغراض التقليديّة، إلّا أنّ اكتشاف الشّعار في الصّور الحقيقيّة يمكن أن يمثّل تحديًّا كبيرًا لأنّ أغلب العلامات التّجاريّة تمتلك العديد من الشّعارات المختلفة والمقاييس المتنوّعة، وتغيرات في الإضاءة، والحجم، والدّقة، كما تظهر ببعض الصور بتشوّهات في الشّكل كما هو موضّح بالشّكل [1].
لمحة موجزة عن خوارزميّة يولو YOLO:
تمّ تقديم بنية نموذج يولو YOLO (اختصار لـ You Only Look One) حيث تمّ تطويرها لأوّل مرّة في عام 2015 من قبل ردمون، وعلى عكس الأنظمة الرّائدة الأخرى في ذلك الوقت _مثل نماذج Deformable Parts Model (DPM kl نموذج الأجزاء القابلة للتشوه التي تستخدم نهج النّافذة المنزلقة Sliding Window لتشغيل مصنّف في مواقع متباعدة بشكل متساوٍ على الصّورة، أو شبكات الطي العصبونية المناطقيّة (R-CNNs) Regions Convolution Neural Network _ يعيد نهج يولو YOLO صياغة اكتشاف الكائنات كمشكلة انحدار واحدة، حيث يقرأ جميع وحدات بكسل الصّورة قبل التنبّؤ بإحداثيّات المربّع المحيط Bounding Box واحتمالات الفئة.
وهذا يعني أنّه يتمّ تطبيق الشّبكة العصبونيّة المطويّة على الصّورة مرّة واحدة فقط، ممّا يجعل يولو YOLO أسرع وأقلّ كثافة من النّاحية الحسابيّة، كما أدّى استخدام يولو YOLO إلى تحسين الدّقة في مواقف معينة كما لاحظ المؤلّفون.[1]
تعمل الخوارزميّة على تقسيم الصّورة المدخلة إلى شبكة S × S. بالنسبة لكلّ خلية شبكة، يحسب النّموذج احتماليّة وجود كائن داخل تلك الشّبكة، وبعد ذلك تقوم الخوارزميّة بتجميع الشبكات ذات الاحتماليّة عالية القيمة قريبة من بعضها لالتقاط الكائن بأكمله؛ إذا وقع مركز كائن ما في خليّة شبكة، فسيتمّ تعيين خليّة الشّبكة هذه كمسؤولة عن اكتشاف هذا الكائن. تستخدم خوارزميّة يولو YOLO انحدار المربّع المحيطيّ الفرديّ single bounding box regression للتنبّؤ بارتفاع الكائنات وعرضها ومركزها وفئتها. تتنبّأ كلّ خليّة بالمربّعات المحيطة ودرجات الثّقة لتلك المربّعات؛ تعكس درجات الثّقة هذه مدى ثقة النّموذج في أنّ الصّندوق يحتوي على كائن، وكذلك مدى دقّة توقّعه للصّندوق. يمثّل تنبّؤ الثّقة التّقاطع فوق الاتّحاد Intersection Over Union (IOU) بين المربّع المتوقّع وأي مربّع مرجعي (المقدّم أثناء التّدريب)[2].
هناك العديد من الإصدارات المختلفة من خوارزميّة يولو YOLO التي تختلف عن بعضها من حيث بعض الخواص العامة تم شرح وتوضيح هيكلية الاصدار الثالث في المقال الكشف عن الأغراض باستخدام خوارزمية يولو الإصدار الثالث YOLOv3 ضمن كيراس [3]
كما تم شرح وتفصيل الإصدار السادس منها من خلال المقال خوارزميّة الكشف عن الأغراض والتعرّف على الكائنات YOLO v6 يولو الإصدار السّادس [4]
في هذا المقال سنقوم بدراسة كيفية تطبيق خوارزميّة يولوYOLO الإصدار السابع من أجل كشف وتحديد الشعار الكتابي أو الرسومي لشركة سيارات، حيث تم شرح الهيكلية العامة والإصدارات المختلفة والمفاهيم النظرية لخوارزمية يولو YOLO v7 في مقال سابق بعنوان خوارزميّة الكشف عن الأغراض والتّعرّف على الكائنات YOLO v7 يولو الإصدار السّابع [5]
التطّبيق العمليّ:
تعتمد فكرة التنفيذ العملي على خوارزميّة يولو YOLO لتصنيف نوعين من الشعار الخاص بشركة سيارات وتمييز الشعار المكتوب عن الشعار المرسوم.
حيث يتم في البداية تدريب نموذج خوارزميّة يولو الاصدار السابع على مجموعة بيانات تم اختيارها تتضمن عدد من الصور التي تحوي شعار كتابي وعدد آخر من الصور تتضمن الشعار الرسومي لشركة سيارات قد تتضمن الصور أكثر من شعار بزوايا وأحجام ودقة مختلفة، وبعد إتمام عملية التدريب سيتم اختبار النموذج المدرب على صور خارجية حيث يقوم بكشف موقع الشعار في الصورة المدخلة وتحديد نوع الشعار فيما إذا كان كتابي أم رسومي.
- استدعاء المكتبات:
في البداية لنقم باستدعاء المكتبات الهامّة التي سيتمّ استخدامها في الشيفرة البرمجيّة:
import cv2
import json
import os
import shutil
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from __future__ import unicode_literals
from sklearn.model_selection import train_test_split
CV2: المكتبةُ المفتوحةُ للرُّؤيةِ الحاسُوبيَّةِ Opencv، هي مكتبة قويّة للتّعامل مع الصّور في بايثون، وتعدّ من أهمّ المكتبات التي تستخدم في معالجة الصّورة، كما تتضمّن تحميل الصّور وعرضها ومعالجة وتصفية الصّور.
JSON: تُعنى هذه المكتبة بملفّات جسيون json وترمز إلى تدوين كائن جافا سكربت JavaScript. JSON وهو تنسيق موحّد يشيع استخدامه لنقل البيانات، ويتمّ دعمه من قبل العديد من لغات البرمجة.
Os: توفّر وحدة Python OS وظائف سهلة تسمح لنا بالتّفاعل والحصول على معلومات نظام التّشغيل، وحتّى التحكّم في العمليّات إلى الحدّ الأقصى.
TensorRT: مكتبةُ تنسور آر تي للتَّعلُّمِ العميقِ من جوجل المسرّعة عبارة عن حزمة أدوات تطوير برمجيات (SDK) تسهّل استنتاج التّعلم الآليّ عالي الأداء، وهو مصمّم للعمل بطريقة تكامليّة مع أطر التّدريب مثل مكتبةُ تنسور فلو للتَّعلُّمِ العميقِ من جوجل TensorFlow، وبايتورش PyTorch، و إم إكس نت MXNet. و يركّز بشكل خاصّ على تشغيل شبكة مدرّبة بالفعل بسرعة وكفاءة على أجهزة انفيديا NVIDIA.
ولكن قبل عمليّة الاستدعاء نحتاج إلى تحميل المكتبة من خلال التّعليمة التّالية:
!git clone https://github.com/wang-xinyu/tensorrtx
كما يقدّم الرابط التالي من الموقع الرسمي لشركة انفيديا صورة واضحة وشرحًا وافيًا عن هذه المكتبيّة وطرق تنصيبها وشروطها [4]
Shutil: توفر مكتبيّة شاتل Shutil عددًا من العمليّات عالية المستوى على الملفّات ومجموعات الملفّات، وعلى وجه الخصوص يتمّ توفير الوظائف التي تدعم نسخ الملفّات وإزالتها بالنّسبة للعمليّات على الملفّات الفرديّة.
NumPy: هي مكتبة بايثون العدديَّةُ (نمباي) تُستخدم للعمل مع المصفوفات، كما أنّ لديها وظائف للعمل في مجال الجبر الخطّيّ، وتحويل فورييه، والمصفوفات.
Pandas: هي مكتبةُ تحليلِ البياناتِ في بايثون (بانداس) تُستخدم لتحليل البيانات.
Matplotlib: هي مكتبةُ الرَّسمِ الرِّياضيِّ في بايثون (ماتبلوت) وهي مكتبة شاملة لإنشاء تصوّرات ثابتة ومتحرّكة وتفاعليّة.
- إنشاء التّوابع المساعدة بالشيفرة البرمجيّة:
الجزء الثّاني من الشيفرة البرمجيّة هو مرحلة استدعاء العديد من التّوابع التي تمّ تطويرها و التي تفيد في عمليّة تحديد أبعاد وامتداد الشّعار على الصّورة المحدّدة:
# blow out the bbox into max.min values
def expand_bbox_coords(bbox):
xmin = bbox[0]
ymin = bbox[1]
xmax = bbox[0] + bbox[2]
ymax = bbox[1] + bbox[3]
return (xmin, ymin, xmax, ymax)
def obtain_bbox_label(categories, bbox_tag):
label = categories[categories['id']==bbox_tag['category_id']]['name'].item()
label = str(label)
return (label)
أمّا التّوابع التّالية للحصول على بيانات الصّورة ذات الصّلة، حيث يتمّ قصّ الجزء المحدّد وفصل هذا الجزء استنادًا إلى القيم المستخرجة بالتّابع السّابق:
def coco_to_dict(img, annots_df):
# obtain relevant image data
img_name = os.path.basename(img['file_name'])
img_size = (img['width'], img['height'], 3)
# cut to relevant bbox annotations
img_id = img['id']
tags = annots_df[annots_df['image_id']==img_id]
# iterate through bbox annotations
bboxes = []
for _, tag in tags.iterrows():
bbox_annot = {
'label': tag['category_id'],
'xmin': tag['xmin'],
'ymin': tag['ymin'],
'xmax': tag['xmax'],
'ymax': tag['ymax']
}
bboxes.append(bbox_annot)
img_dict = {
'bboxes': bboxes,
'image_name': img_name,
'image_size': img_size
}
return img_dict
أمّا مجموعة التّوابع التّالية تفيد بتحويل صيغة البيانات الحاليّة إلى الصّيغة التي تتوافق مع دخل خوارزميّة يولو yolo؛ حيث يتمّ إنشاء ملفّات نصيّة موافقة للصّور تحوي معلومات العنوان المحدّدة سابقًا للتعرّف عليها، من خلال الخوارزميّة استعدادًا لتدريبها:
def dict_to_yolo(img_dict):
img_name = img_dict['image_name']
img_width, img_height, img_depth = img_dict['image_size']
annot_txt =[]
for box in img_dict['bboxes']:
# extract abs bbox info
lbl = box['label']
x_centre = (box['xmin'] + box['xmax']) / 2
y_centre = (box['ymin'] + box['ymax']) / 2
width = box['xmax'] - box['xmin']
height = box['ymax'] - box['ymin']
# convert bbx infor to rel
x_centre = round(x_centre / img_width, 3)
y_centre = round(y_centre / img_height, 3)
width = round(width / img_width, 3)
height = round(height / img_height, 3)
annot_txt.append(" ".join([
str(lbl), str(x_centre), str(y_centre), str(width), str(height)
]))
annot_name = os.path.splitext(img_name)[0] + '.txt'
return annot_name, annot_txt
ثمّ تابع استعراض الصّورة بعد عمليّة استدعائها من ملفٍّ محدّد، ورسمها بالبايثون وفق خواصّ cv2 المكتبةُ المفتوحةُ للرُّؤيةِ الحاسُوبيَّةِ Opencv:
def display_image(img_file, dim = (20,6)):
# load, inverting colour array to align with OpenCV behaviour
img = cv2.imread(img_file)
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
# display using matplotlib
plt.figure(figsize = dim)
plt.imshow(img)
plt.axis('off')
plt.show()
return
- تحميل ومعالجة قاعدة البيانات:
في هذه المرحلة نقوم بربط خدمة تخزين ومزامنة الملفات المقدمة من غوغل google drive مع google colabe هي خدمة Jupyter Notebook مستضافة ولا تتطلب أي إعداد لاستخدامها وتوفر وصولاً مجانيًا إلى موارد الحوسبة، بما في ذلك وحدات معالجة الرسومات ووحدات TPU.
لسهولة رفع وتحميل قاعدة البيانات ومعالجتها، وكذلك تخزين الخرج النّاتج لدينا وذلك من خلال التّعليمات التّالية:
from google.colab import drive
drive.mount('/content/drive')
في هذه المرحلة يتم طلب سماحيّة للوصول الى حساب google drive وفق للشكل (3).
تقوم دالة listdir وهي مكتبة من مكتبات نظام التشغيل os بإرجاع قائمة تحتوي على أسماء المدخلات في الدّليل المعطى، بواسطة المسار في القائمة في ترتيب عشوائيّ ولا يتضمن المداخل الخاصّة.
os.chdir("/content/drive/My Drive/Colab Notebooks")
os.listdir()
['keras.ipynb',
'ItemData.json',
'DropData.json',
'DefaultUserData.json',
'MonsterData.json',
'DungenData.json',
'EquipData.json',
'UserData.json',
'game balancing.ipynb']
ثمّ نقوم بتحميل واستدعاء ملفّ الصّور مع العناوين المرتبطة معهم، وتصنيفات العناوين ويتمّ ذلك من خلال الشيفرة البرمجيّة التّالي:
# load the annotation set
# convert annotated images json to dataframe to make slicing easier
images = pd.DataFrame(data['images'])
# convert annotated labels json to dataframe to make slicing easier
annots = pd.DataFrame(data['annotations'])
annots[['xmin', 'ymin', 'xmax', 'ymax']] = annots.apply(lambda x: expand_bbox_coords(x['bbox']), axis=1, result_type='expand')
# convert annotated images json to dataframe to make slicing easier
labels = pd.DataFrame(data['categories'])
ثمّ نقوم بعرض صورة عشوائيّة محدّدة بدليل ومسار من قاعدة البيانات حيث يتمّ الرّبط بين عنوان الصّورة مع دليلها، واستعراض الصّورة مع تحديد الشعار المحدّد، واسم الشّركة الذي يتبع لها اللّوغو، وذلك من خلال الرّبط بين ملفّ جسيون json وعناوين الصور.
# print a test annotation
img_id = 0
# take the entry for the relevant image id
test_img = images[images['id']==img_id]
# load image
path = path = '/content/drive/My Drive/Data/Label_Studio_Output_1/images/c1ee09c6-aram1.jpeg'
image = cv2.imread(path)
# ensure we are using the correct colour spectrum when displaying
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
# overlay relevant bounding boxes
relevant_annots = annots[annots['image_id']==img_id]
for index, tag in relevant_annots.iterrows():
# display bbox
cv2.rectangle(
image,
(int(tag.xmin), int(tag.ymin)), (int(tag.xmax), int(tag.ymax)),
(255, 0, 0), 2
)
# display text label
text = obtain_bbox_label(labels, tag)
cv2.putText(
image, text, (int(tag.xmin), int(tag.ymin-5)), cv2.FONT_HERSHEY_SIMPLEX, 0.9,
(255,0,0), 2
)
# display
plt.imshow(image)
plt.axis('off')
plt.show()
ملاحظة: ملفّ جسيون json يحوي ثلاثة أجزاء أساسيّة؛ هي المعلومات الخاصّة بالصّور الأساسيّة (الطّول والعرض والمعرّف id واسم الملفّ ومساره):
كما يحوي معلومات عن العنوان المحدّدة أبعاده وموقعه ونوعه وتصنيفه وأجزاء الصّورة التي تمّ تحديدها لاكتشافها وفق للشكل (4):
على الرّغم من أنّ تنسيق جسيون-كوكو COCO json الذي تمّ استيراد قاعدة البيانات فيه ملائم لأنّه يضمن احتواء جميع بيانات العناوين في ملفّ واحد، إلّا أنّه ليس التّنسيق الصّحيح لتدريب بنية نموذج يولو YOLO. قبل أن نبدأ في التّفكير في تدريب نموذج يولو YOLO، نحتاج أوّلاً إلى تحويل العناوين بتنسيق جسيون-كوكو COCO json إلى ملفّات نصيّة مناسبة بتنسيق يولو YOLO.
# define output dir (creating it if doesnt exist)
output_folder = 'data/Label_Studio_Output_2/yolo_annotations'
if not os.path.isdir(output_folder):
os.makedirs(output_folder)
# convert COCO to Yolo format
for _, image in images.iterrows():
# extract COCO annotations to Yolo format
image_dict = coco_to_dict(image, annots)
file_name, file_txt = dict_to_yolo(image_dict)
# save the file
with open(os.path.join(output_folder, file_name), 'w') as f:
for entry in file_txt:
f.write(f"{entry}\n")
نلاحظ عند تنفيذ الشّيفرة البرمجيّة السّابقة يتمّ إنشاء ملفّ يسمّى yolo_annotation الموضح بالشكل (5) والذي يحوي المعلومات النّصيّة الخاصّة بكلّ صورة، والذي تمّ استخراجها من ملفّ جسيون json في الخطوات السّابقة، وذلك من أجل تهيئتها لتكون من مدخلات شبكة يولو yolo
في المرحلة التّالية يتمّ تقسيم ملفّ قاعدة البيانات إلى ثلاثة أجزاء؛ جزء للاختبار وجزء للتّدريب وجزء للتّحقق، كما أنّ عمليّة الفصل تكون عشوائيّة ويتمّ حفظ الملفّات النّاتجة بمجلد يُسمّى logo-detection والموضح بالشكل (6):
# combine the two datasets into one
base_path_1 = 'data/Label_Studio_Output_1/'
base_path_2 = 'data/Label_Studio_Output_2/'
image_list_1 = [os.path.join(base_path_1, 'images', x) for x in os.listdir(os.path.join(base_path_1, 'images'))]
image_list_2 = [os.path.join(base_path_2, 'images', x) for x in os.listdir(os.path.join(base_path_2, 'images'))]
image_list = image_list_1 + image_list_2
annot_list_1 = [os.path.join(base_path_1, 'yolo_annotations', x) for x in os.listdir(os.path.join(base_path_1, 'yolo_annotations'))]
annot_list_2 = [os.path.join(base_path_2, 'yolo_annotations', x) for x in os.listdir(os.path.join(base_path_2, 'yolo_annotations'))]
annot_list = annot_list_1 + annot_list_2
# to be sure the files are in the same order we sort
image_list.sort()
annot_list.sort()
# confirm there are no duplicates in naming convention - from joining the two sets
assert(len(image_list) == len(set(image_list)))
assert(len(annot_list) == len(set(annot_list)))
# obtain the train and test
img_train, img_test, annot_train, annot_test = train_test_split(image_list, annot_list, test_size = 0.1, random_state = 1)
img_val, img_test, annot_val, annot_test = train_test_split(img_test, annot_test, test_size = 0.5, random_state = 1)
copy_files(img_train, annot_train, 'train', 'data/petronas_logo_detection')
copy_files(img_val, annot_val, 'val', 'data/petronas_logo_detection')
copy_files(img_test, annot_test, 'test', 'data/petronas_logo_detection')
-
مرحلة تحميل خوارزميّة يولو الإصدار السّابع yolo7 وتدريبها:
مرحلة تحميل خوارزميّة يولو yolo7: هنا نقوم بتحديد مسار محدّد للتّنصيب ضمن ملفّ التّدريب في خدمة التخزين والتزامن drive، ثمّ تبدأ عمليّة التّحميل:
!git clone https://github.com/WongKinYiu/yolov7.git
وتكون نتيجة التّحميل تضمين ملف يولو الإصدار السّابع yolo7 في خدمة التخزين والتزامن drive كما هو مبين في الشكل (7):
بعد عمليّة التحميل يجب تنصيب متطلّبات الخوارزميّة من مكتبات جاهزة وفق إصدارات محدّدة والموضحة بالشكل (8):
!pip install -r ./yolov7/requirements.txt
كما تظهر الحاجة إلى تثبيت كودا CUDA لتمكين التّدريب على وحدة معالجة الرّسومات GPU، نتحقّق من موقع بايتورش Pytorch الرّسميّ للحصول على أمر تثبيت إصدار بايتورش Pytorch مناسب مع تمكين وحدة معالجة الرّسومات GPU والموضّح بالشكل (9):
تأكّد من تحديد الإصدار الصّحيح من توافق كودا CUDA مع الإصدار المحدّد لدينا:
!pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu116
# check we have correctly installed CUDA enabled Pytorch
import torch
torch.cuda.is_available()
بعد تثبيت الأوامر الأساسيّة وتنصيب يولو الإصدار السّابع YOLO7 ضمن الملفّ المحدّد، نحتاج الآن إلى إنشاء الملفّ المعنيّ بعمليّة التّدريب وهو ملفّ يمال yaml، وذلك لتحديد التّسميات التي نرغب في أن يتعلّمها النّموذج، بالإضافة إلى تحديد بنية النّموذج وحجمه وبارامتراته والموضح بالشكل (10):
هنا نقوم بتعديل مسارات ملفّات التّدريب والاختبار والتّحقق وتعديل عدد أصناف التّصنيف وأسماء العناوين، وفق معلومات قاعدة البيانات لدينا كالتّالي الموضح بالشكل (11):
ملاحظة مهمّة: في حال كانت تصنيفات قاعدة البيانات أكثر من عنصرين يجب التّعديل على ملفّ الشّيفرة البرمجيّة الأساسيّة بإضافة التّابع التّالي:
ثمّ يتمّ اختيار النّموذج التي نرغب في استخدامه من مجموعة النّماذج حيث توجد العديد من ملفّات يمال yaml الخاصّة بالنّماذج القياسيّة في “yolov5/cfg/training/” والموضحه بالشكل (12).
تحدّد هذه العناصر البنية المتعلّقة بالنّماذج الموضّحة في مستودع جيت هب التالي ثمّ نقوم بكتابة تابع التّدريب وفق خواصّ الخوارزميّة التي قمنا باختيار الملفّ الخاصّ بها، والتي يمكن تحديد خواصّه من الجدول (1) التّالي:
الجدول (1):مقارنة بين الخواص العامة للنماذج المختلفة من خوارزميّة يولو الإصدار السابع YOLO v7.
كما نقوم باختيار ملفّ النّسخة التي سندرّب وفقًا له وعمل نسخة من الملفّ مع تغير اسمه والتّعديل بالملفّ وفق بيانات قاعدة البيانات، يتضمّن الملفّ طبقات الخوارزميّة وأوزانها وكلّ التّفاصيل عن النّموذج المستخدم والذي سنقوم بعمليّة نقل التّدريب عليه.
وأخيرًا لتحسين الأداء وتجنّب الحاجة إلى تدريب النّموذج من الصّفر، سنستفيد من عمليّة نقل التّعلُّم النّقل حيث نقوم بنقل ما تعلمته شبكة لشبكة أخرى وتم توضيح هذه الخطوة بالتفصيل في المقالة التي بعنوان نقل التعلُّم باستخدام النماذج المدرّبة مُسبقاً [5].
لتدريب نموذج اكتشاف الشّعار، لهذا سنقوم بتحميل الأوزان المدرّبة مسبقًا التي تمّ الحصول عليها من خلال التّدريب الأوّليّ للنّموذج على مجموعة بيانات كوكو COCO لعام 2017 (كما هو موضّح من قبل مطوّري النّموذج، في ورقتهم البحثيّة [6].
يتيح لنا ذلك الاستفادة من طبقات التّصفية المتنوّعة التي تعلّمها النّموذج، لتحديد الميزات الرّئيسيّة مثل الخطوط العريضة للكائنات، ثمّ ضبط طبقة التنبّؤ النهائيّة لمهمّتنا المحدّدة.
نظرًا لأنّ مجموعة البيانات التي سيتمّ تدريب النّموذج عليها صغيرة نسبيًّا، وليس لدينا العديد من الكائنات لكلّ صورة، فيمكننا البدء بالإصدار الأساسيّ من النّماذج المدرّبة مسبقًا المتاحة، مثل yolosv7.pt، لإبقاء الأمور بسيطة وتجنّب حالة المُلاءمةُ الزَّائدةُ Overfitting، سنستخدم حجم دفعة batch size يبلغ 8، بحيث سيتمّ تدريب النموذج على مُعالج الرّسوميّات GPU الخاص بأجهزة الكمبيوتر المحمولة المجانيّة الخاصّة بـ Gradient، وحجم صورة يبلغ 640، وسنتدرّب لمدّة 100 دورة تدريب epoch .
في حال ظهور عدّة مشاكل أثناء عمليّة التّدريب يمكن حلّها وفق التّالي:
استخدم حجم دفعة أصغر: جرّب حجم دفعة 2 أو 4 إذا لم يعمل 8، ولكن لا ينبغي أن يحدث هذا على وحدة معالجة الرّسوميّات المجانيّة.
استخدم شبكة أصغر: سيتمّ تشغيل النّموذج yolov7-tiny.pt بتكلفة حسابيّة أقلّ من النّموذج yolov7.pt الأساسيّ.
استخدم حجمًا أصغر للصّورة: حجم الصّورة يتوافق مباشرةً مع الحسابات أثناء التّدريب، حيث يتمّ تقليل حجم الصّور من 640 إلى 320 لخفض التّكلفة على حساب دقّة التنبّؤ.
من المحتمل أن يؤثّر تغيير أي ممّا سبق على الأداء، الحلّ الوسط هو قرار تصميم يتعيّن علينا اتخاذه اعتمادًا على حساباتنا المتاحة. قد نرغب في استخدام نسخة وحدة معالجة رّسوميّات GPU أكبر أيضًا اعتمادًا على الموقف، على سبيل المثال من شأن وحدة معالجة الرّسوميّات الأكثر قوّة مثل A100-80G أن تقلّل وقت التّدريب بشكل كبير، ولكنّها ستكون زائدة عن الحاجة بالنّسبة لمهمّة التّدريب الأصغر على مجموعة البيانات هذه.
- عمليّة التّدريب:
تبدأ عمليّة التّدريب للنّموذج الذي تمّ اختياره بالنّسبة لقاعدة البيانات المحدّدة وفق التّالي:
!python yolov7/train.py --data yolov7/data/petronas_logo.yaml --img 640 640 --cfg yolov7/cfg/training/yolov7-tiny-petronas.yaml --weights yolov7/data/yolov7-tiny.pt --hyp yolov7/data/hyp.scratch.tiny.yaml --name yolov7-petronas --workers 8 --device 0 --batch-size 16 --epochs 200
وبتفصيل معاملات تابع التّدريب نحصل على:
- workers: الحدّ الأقصى لعدد العاملين في أداة تحميل البيانات وهم الثريدات Threads.
- batch: يشير إلى حجم الدُّفعة (عدد أمثلة التّدريب المستخدمة في تكرار واحد).
- data: تشير إلى المسار إلى ملفّ يمال yaml.
- img-size: يشير إلى حجم الصّور المدخلة.
- cfg: تحديد تكوين النّموذج.
- weights: مسار الأوزان الأوّليّة.
- name: حفظ في المشروع/الاسم.
- hyp: مسار المعلمات الأساسيّة.
- epochs: تشير إلى عدد دورات التّدريب.
تمّ تدريب الشّبكة بشكل كامل مع عرض نسبة الكشف الصّحيح لكلّ نوع من الأنواع، وكما يتمّ توضيح الزّمن الكليّ للتّدريب وحفظ نموذج الشّبكة المدرّبة مع الأوزان المحفوظة في مجلد RUNS؛ الذي كذلك يعرض بعض الخواصّ العامّة للتّدريب والنتائج التي سيتمّ شرحها في التّالي:
وباستعراض النّتائج لعمليّة التّدريب الموضحة بالشكل (13) نحصل على ما يأتي:
وباستعراض مصفوفة الالتباس confusion matrix الموضحة بالشكل (14) نحصل على:
ومن أجل مرحلة الكشف نقوم بكتابة التّابع التّالي والموضح بالشكل (15)، حيث نقوم بتمرير بيانات الصّورة التي نرغب بكشفها إلى الخوارزميّة المدرّبة، ويوضح الشكل (16) نتائج اختبار الخوارزميّة لكشف الشعار في صورتين مختلفتين:
من النّتيجة نلاحظ أنّ كلّاً من نسبة الدّقة ومتوسط الدّقة( mean average precision (MAP حوالي 80% تقريبًا مع زيادة مراحل التّدريب، والتي يمكن اعتبارها نتيجة جيّدة نظرًا للحجم المحدود جدًّا لبيانات التّدريب لدينا. بالنظر إلى مصفوفة الخطأ يمكننا أن نرى أن الدّقة الإجماليّة للتنبّؤ بالشّعار تميل إلى أن تكون أفضل من دقّة النّص.
ويدعم هذا إلى حدّ كبير النّمط الذي نراه في الأمثلة المذكورة أعلاه، حيث توجد حالات عديدة لنص يظهر ولكن لم يتمّ اكتشافه بواسطة النّموذج، من المحتمل أن يرجع ذلك إلى أنّ الطّبقات المدرّبة مسبقًا لنموذجنا تمّ تدريبها على مجموعة بيانات كوكو COCO، لذا فهي موجّهة أكثر نحو تحديد الخطوط العريضة للكائنات بدلاً من كتل النّص.
وغنيٌّ عن القول أنّ زيادة حجم بيانات التّدريب وحجم النّماذج والمعلمات مثل حجم الدّفعة من المرجّح أن تزيد الدّقة، إذا كنت تتطلّع إلى نشر نموذج مدرّب مخصّص في بيئة إنتاج.
الخلاصة:
شكّل موضوع كشف الشّعار الخاصّ بعلامة تجاريّة موضوعًا مهمًّا للبحث والتّطوير، وذلك لأهمّيته في العديد من التّطبيقات الحياتيّة المهمّة، إلّا أنّه يتطلّب نوعًا معيّناً من المعالجة وذلك لتحقيق كشف دقيق وواضح عن الشّعار، بغضّ النّظر عن حالته وتموضعه وزاوية دورانه في الصّور، حيث حقّقت خوارزميّة يولو الذّكيّة نتائج مبهرة في هذا المجال وذلك من خلال الاختبار والمقارنة مع نماذج أخرى، وعلى الرّغم من ذلك ما زال موضوع كشف وتصنيف الشّعار موضوعًا بحثيًّاً مهمًّا قابلًا للتّطوير.