القائمة الرئيسية

الصفحات

 

تقنية نقل النمط (Neural Style Transfer)
إنَّ تقنية نقل النمط بواسطة الشبكات العصبية الإصطناعية هي عملية إجراء تأثيرات معينة على صورة بواسطة صورة أخرى تحمل نمطاً معيناً كأن تكون لوحة مشهورة لفنان مشهور, حيث تنتقل لمسات هذا الفنان إلى لوحة أو صورة نقوم نحن بإستحضارها, وبذلك نحصل على عمل فني جديد يحمل لمسات فنية رائعة.

تقنية نقل النمط

 (Neural Style Transfer)


المهندس حسن فنجان عداي

 

المقدمة:

بسم إلله الرحمن الرحيم

إنَّ تقنية نقل النمط بواسطة الشبكات العصبية الإصطناعية هي عملية إجراء تأثيرات معينة على صورة بواسطة صورة أخرى تحمل نمطاً معيناً كأن تكون لوحة مشهورة لفنان مشهور, حيث تنتقل لمسات هذا الفنان إلى لوحة أو صورة نقوم نحن بإستحضارها, وبذلك نحصل على عمل فني جديد يحمل لمسات فنية رائعة.

 

نقل النمط

 (Neural Style Transfer)

الفكرة الأساسية لهذه التقنية هي عمل تأثيرات معينة على صورة بواسطة صورة أخرى تحمل نمطاً معيناً   , مع المحافظة على معالم الصورة الأصلية, وهذا النمط قد يكون لوحة معينة مرسومة من قبل رسام أو شعار مميز أو ألوان مميزة أو أي نموذج أو أسلوب يراد له أن يؤثر على صورة أخرى منتخبة.

 تسمى هنا الصورة الأصلية المراد إجراء تحديثات عليها بال(original_image) وتضم المحتوى (content) وهو البنية الكلية العليا للصورة. أما الصورة الأخرى التي تحتوي على النمط (style) المطلوب تسمى ال(reference_image), والصورة التي يتم توليدها من جراء تطبيق هذه التقنية هي (generated_image).

تمَّ إنشاء هذه التقنية من قبل الباحث ليون غيتس وآخرون (Leon Gatys et al.) في صيف العام (2015).

على سبيل المثال في الشكل التالي تعتبر ضربات الفرشاة الدائرية باللونين الأزرق والأصفر في لوحة (Starry Night) للفنان  فنسنت فان كوخ هي النمط (style) والمباني في الصورة الأخرى تعتبر المحتوى (content).




إنَّ فكرة نقل النمط (style transfer) كانت موجودة قبل العام (2015), أي قبل تنفيذها بإستخدام التعلم العميق  في مجال الرؤية الحاسوبية (computer vision), حيث جرت محاولات لتنفيذ هذه التقنية بإستخدام طرق معالجة الصور التقليدية ولكن نجاحها كان دون الحد المطلوب, ولكن بعد إدخال التعلم العميق (deep learning) في مجال الرؤية الحاسوبية, تم تحقيق نتائج كبيرة بإستخدام هذه التقنية.

إنَّ الفكرة الأساسية في تطبيق تقنية نقل الأسلوب (style transfer) هي نفس الفكرة التي تعتبر أساسية لجميع خوارزميات التعلم العميق, حيث نقوم بتعريف دالة الخسارة (loss function) لتحديد ما نريد تحقيقه وتقليل قيمة هذه الدالة تدريجياً إثناء عملية التدريب (training), ويجب أن نكون على دراية بما نريد تحقيقه من الخوارزمية, وهنا الهدف سوف يكون هو الحفاظ على محتوى (content) الصورة الأصلية (original image) مع ضم نمط الصورة المرجعية (reference image) إليها.

إذا تمكنا من تحديد المحتوى (content) والأسلوب (style) حسابيًا ، فستكون دالة الفقد (loss function) المناسبة للتقليل إلى الحد الأدنى كما يلي:


حيث إنَّ المسافة (distance) هي عبارة عن دالة تحسب الخطأ (error) مثل الدالة الطبيعية نوع (L2).

الدالة (style)  هي الدالة التي تقوم بإستقبال صورة (image) ثم تقوم بحساب النمط (style) لها.

الدالة (content)  هي الدالة التي تقوم بإستقبال صورة (image) ثم تقوم بحساب المحتوى (content) لها.

إن عملية تقليل قيمة ال(loss function) تؤدي إلى إقتراب نمط (style) الصورة المتولدة (generating_image) من نمط الصورة المرجعية (reference_image), وكذلك تؤدي إلى إقتراب محتوى (content) الصورة المتولدة (generating_image) من محتوى الصورة الأصلية (original_image), وهذا معناه أن الهدف من هذا العمل سوف يتحقق وهو نقل النمط الى الصورة الأصلية مع الحفاظ على محتواها.

لحسن الحظ فإنَّ الشبكات العصبية الإلتفافية (Convolutional Neural Networks) تسهل علينا عملية حساب قيمة النمط (style) وكذلك قيمة المحتوى (content) لأي صورة (image). وسوف نوضح كيف يتم حساب هذه القيم وكما يلي:

حساب قيمة دالة الفقد في المحتوى (The content loss):

مثلما نعلم فإن مخارج (Activations) الطبقات الإلتفافية الأولية (Earlier Convolutional layers) والتي تكون على شكل مصفوفات خصائص (Feature Maps), هذه ال (Activations) تستخلص المظاهر الخارجية للصورة من حواف ودوائر وخطوط أفقية وأخرى عمودية وغير ذلك من الأشكال الهندسية, أما الطبقات الإلتفافية العليا (Higher Layers) فتكون مخارجها محتوية على التفاصيل الدقيقة للصورة أي محتوى الصورة (content). بمعنى آخر إنَّ الصورة المدخلة إلى النموذج المدرب على عملية تصنيف الصور سيتم تحليلها وتفكيكها إلى أشكال خارجية وكذلك إلى محتويات وبأحجام مختلفة على إمتداد الطبقات الإلتفافية المختلفة.

لذلك فإننا نتوقع بأن محتوى الصورة (content) سوف يتم إلتقاطه من قبل الطبقات الأخيرة من النموذج المدرب, وبالتالي يمكننا حساب قيمة الفقد في المحتوى (content loss) من خلال حساب قيمة محتوى الصورة الأصلية (original image) لإحدى الطبقات العليا (upper layer) وكذلك حساب قيمة محتوى الصورة المتولدة (generated image) لنفس الطبقة, ثم نقوم بحساب الخطأ (error) عن طريق دالة (L2 norm). كلما كان الفرق (error) صغيراً كلما كانت الصورة المتولدة محافظة على محتوى الصورة الأصلية.

حساب قيمة دالة الفقد في النمط (The style loss):

كما إتضح من خلال ماذكرناه في الفقرة السابقة إنَّ حساب قيمة الفقد في المحتوى (content loss) يتم من خلال طبقة عليا مفردة (single upper layer), أما حساب قيمة دالة الفقد في النمط (style loss) فإنه يتم من خلال طبقات أولية متعددة (earlier layers) كما إقترح مطور هذه التقنية (Gatys et al.), حيث إن هذه الطبقات مجتمعة سوف تقوم بإلتقاط المظهر الخارجي للصورة وبأحجام مختلفة (spatial scales) وليس حجماً مفرداً.

إستخدم المطور (Gatys et al.) لحساب قيمة دالة الفقد في النمط (style loss) تقنية رياضية تسمى (Gram matrix), وهي عملية ضرب منقولة المصفوفة (transpose) في المصفوفة نفسها لأجل ضرب المعاملات الداخلية فقط والتي تعتبر بمثابة تمثيل للإرتباطات بين الطبقات التي تحتوي على الخصائص المطلوبة.

إنَّ المصفوفات الناتجة من هذه العملية الرياضية  والتي تسمى ميزة الإرتباطات (feature correlations) تقوم بعمل إحصاء للنماذج (patterns) الموجودة في  حجم معين من أحجام الأنماط  وهذه النماذج تمثل بمجموعها البنية الكاملة الموجودة لهذا الحجم. وبالتالي فإنَّ قيمة الفقد للنمط (style loss) تهدف إلى المحافظة على الإرتباطات الداخلية المتشابهة ضمن المخارج (activations) للطبقات المختلفة في حالة الصورة الحاوية على النمط (style-reference image). وهذا بدوره يضمن أن تكون البنية الموجودة في الأحجام المكانية المختلفة متشابهة مابين الصورة الحاوية على النمط (style-reference image) والصورة التي تم إنشاؤها (generated image).

نقوم الآن بإنشاء تطبيق يقوم على تنفيذ هذه الخوارزمية وكما يلي:

الأسطر من (1) إلى (5): لإستدعاء بعض المكتبات ذات الصلة بتطبيقنا.


الأسطر من (1) إلى (7): لإنشاء دالة سوف نستخدمها لاحقاً لتحويل أي مصفوفة من نوع (Tensorflow) إلى بيانات صورة إعتيادية لكي تكون صالحة للعرض.

الأسطر من (1) إلى (12): لإنشاء دالة تقوم بقراءة بيانات الصورة من الملف الخاص بالصورة المعنية.

السطر رقم (2): لتحديد أعلى قياس للصورة من حيث الإرتفاع أو العرض.

السطر رقم (3): لقراءة بيانات الصورة على هيئتها من حيث نوع التنسيق (Format) حيث إنَّ البيانات التي نحصل عليها تكون مرمزة أو مجفرة (coding).

السطر رقم (4): لأجل فك الترميز وإعادة بيانات الصورة إلى حالتها الصحيحة, ولكن نوع البيانات تكون على شكل (uint8).

السطر رقم (5): لتحويل نوع البيانات إلى (Float32).

السطر رقم (6): لإستخلاص حجم الصورة من حيث الإرتفاع والعرض, وتحويل القيمتين الى قيم كسرية من نوع (Float32) لحاجتنا لها في حساب قيمة المقياس (Scale) في الأسطر القادمة.

السطر رقم (7): لمعرفة أيهما الأكبر الإرتفاع أم العرض للصورة لغرض إستخدامه في حساب ال (Scale).

السطر رقم (8): لحساب قيمة المقياس (Scale). هذا المقياس نحتاجه لأجل جعل الصورتين متقاربتين من حيث الحجم (size) وهذا يساعد في سهولة العمليات الحسابية للخوارزمية.

السطر رقم (9): لحساب الحجم الجديد للصورة, حيث يتم ضرب كلٌ من الإرتفاع والعرض للصورة بقيمة المقياس (Scale), وكذلك تحويل قيم الحجم الجديد إلى (Integer).

السطر رقم (10): لتغيير حجم الصورة إلى الحجم الجديد الذي قمنا بحسابه في السطر السابق.

السطر رقم (11): إضافة بعد رابع للصورة لكي تكون بيانات الصورة مناسبة للنموذج (Model).

الأسطر من (1) إلى (6): إنشاء دالة تقوم بعرض الصور, وكذلك إضافة العناوين (Titles) لها.

السطر رقم (3): لإلغاء البعد الرابع إذا كانت بيانات الصورة ذات أربعة أبعاد (Dimensions).

السطر رقم (4): إستخدام الدالة (imshow) من المكتبة (matplotlib.pyplot) لغرض عرض الصورة.

السطر رقم (6): لعرض العنوان (Title) مع الصورة فيما لو مررناه عند إستدعاء الدالة.

السطر رقم (1): لتحميل بيانات الصورة الخاصة بالمحتوى (Content image) وذلك عن طريق إستدعاء الدالة (load_img) التي قمنا بإنشاءها حيث نقوم بتمرير إسم الملف الخاص بالصورة والذي قمنا بوضعه في المجلد الخاص بالتطبيق.

السطر رقم (2): لتحميل بيانات الصورة الخاصة بالنمط (Style reference image).

السطر رقم (3): لتحديد المساحة التي نريد أن نعرض فيها مجموعة صور, حيث يكون القياس بالإنج.

السطر رقم (4): لتحديد مكان الصورة الأولى التي سوف تعرض في المساحة التي قمنا بتحديدها, حيث إنَّ الرقم (1) من اليسار يدل على عدد الصفوف التي نستخدمها, والوسط يدل على عدد الأعمدة التي نستخدمها, أما الرقم الأيمن فهو لتسلسل الصورة التي سوف تعرض.

السطر رقم (5): لعرض الصورة الخاصة بالمحتوى قبل تنفيذ الخوارزمية, عن طريق إستدعاء الدالة (imshow) التي قمنا بإنشاءها.

بعد تنفيذ الكود تظهر لنا الصورتان اللتين سوف نستخدمهما في الخوارزمية:


السطر رقم (1): لإختيار الطبقة التي سوف نستخدم مصفوفات الخصائص التابعة لها في إستخراج المحتوى (Content) لكل من الصورة الأصلية الخاصة بالمحتوى (Content image) وكذلك للصورة المتولدة (Generated image). وقد تم وضع هذه الطبقة في مصفوفة (List).

السطر رقم (2): لإختيار الطبقات التي سوف نستخدم مصفوفات الخصائص التابعة لها في إستخراج النمط (Style)  لكلٍّ من الصورة الأصلية الخاصة بالنمط (Style reference image) وكذلك للصورة المتولدة (Generated image). وقد تم وضع هذه الطبقات في مصفوفة (List).

السطر رقم (7): لحساب عدد الطبقات المنتخبة لأجل إستخراج المحتوى (Content), وقد إخترنا طبقة واحدة فقط.

السطر رقم (8): لحساب عدد الطبقات المنتخبة لأجل إستخراج النمط (Style), وقد إخترنا خمسة طبقات.


السطر رقم (1): إنشاء النموذج المشهور (VGG19) وتحميل الأوزان الخاصة به. مع ملاحظة اننا إخترنا عبارة (include_top=False) لأننا نحتاج الطبقات الإلتفافية (Convolutional Layers) منه فقط. وهذا النموذج يكون مدرباً على مجموعة البيانات المشهورة (ImageNet).

السطر رقم (2): جعل معاملات هذا النموذج من أوزان (Weights) وقيم إنحياز (Biases) غير قابلة للتدريب.

السطر رقم (3): لدمج أسماء الطبقات التي إخترناها من النموذج لأجل إستخلاص المحتوى (Content) والنمط (Style).

السطر رقم (4): لإستخلاص المخرجات الخاصة بالطبقات التي إخترناها وهذه الطبقات عددها (6) واحدة خاصة بالمحتوى (Content) وخمسة خاصة بالنمط (Style).

السطر رقم (5): لإنشاء النموذج الخاص بنا وسميناه (my_model) وذلك عن طريق الكلاس (Model), والذي نمرر له شكل الإدخال والذي سوف نستخلصه من شكل الإدخال الخاص للنموذج الأصلي (VGG19), ونمرر له كذلك قائمة بالمخرجات والتي حصلنا عليها من السطر السابق والتي سميناها (outputs). حيث إنَّ هذا النموذج الذي أنشأناه تكون له طبقة إدخال (Input layer) واحدة ولكنه يحتوي على ست طبقات إخراج (Output layers) بعدد الطبقات التي إخترناها.

السطر رقم (6): لجعل نموذجنا غير قابل للتدريب.


الأسطر من (1) إلى (5): إنشاء دالة تقوم بحساب مصفوفة (Gram matrix) الضرورية في عملية حساب قيمة الفقد (loss) بالنسبة إلى النمط (style).

السطر رقم (2): لحساب مصفوفة غرام (Gram matrix) للمصفوفة الداخلة إلى الدالة (input_tensor).  حيث إستخدمنا الدالة (einsum) المنتمية إلى الدوال الخاصة بالجبر الخطي من مكتبة (Tensorflow) وهذه الدوال تسمى(linalg). إن عبارة (einsum) تعني طريقة إختصار لمعادلات الجبر الخطي أنشأها العالم آينشتاين.

السطر رقم (3): لإستخلاص أبعاد المصفوفة (input_tensor shape).

السطر رقم (4): إستخراج الإرتفاع والعرض وإيجاد حاصل ضربهما وتحويل القيم إلى نوع (Float32).

السطر رقم (5): قسمة مصفوفة غرام على الإرتفاع والعرض لمصفوفة الخصائص (Feature map) لأجل إستخراج المعدل.

الأسطر من (1) لغاية (17): لإنشاء دالة تقوم  بإستخلاص قيم كل نيورون من نيورونات مصفوفات الخصائص (Feature maps) التابعة للطبقات الخاصة بكل من المحتوى (Content) وكذلك النمط (Styleلأي صورة من الصور الثلاث أي (Content image & Style-reference image & Generated image), وتقوم بوضع هذه القيم في مصفوفة من نوع (Dictionary) لكل من ال (Content) و ال (Style) ثم جمع هاتين المصفوفتين في مصفوفة واحدة من نوع (Dictionary) أيضاً.

السطر رقم (3): ضرب قيم بيانات الصورة المراد إدخالها إلى النموذج بالعدد (255) لضرورات المعالجة والتهيئة اللاحقة.

السطر رقم (4): القيام بمعالجة بيانات الصورة المراد إدخالها إلى النموذج بما يتلائم وطبيعة هذا النموذج.

السطر رقم (5): للحصول على مخرجات الطبقات الستة من النموذج بعد إدخال بيانات الصورة التي تمت تهيئتها في الخطوة السابقة, حيث يتم إيداع هذه المخرجات في مصفوفة هي (outputs).

السطر رقم (6): عزل المخرجات التي تخص النمط (Style) عن تلك التي تخص المحتوى (Content). حيث إنَّ العناصر الخمسة الأولى من المصفوفة (outputs) تخص النمط (Style), أما العنصر السادس من المصفوفة فإنه يخص المحتوى (Content).

السطر رقم (9): إنشاء حلقة تكرارية تتكرر بعدد المخرجات الخاصة بالنمط (Style) والتي عددها خمسة وذلك لأجل تحويل مخرجات كل طبقة منها إلى (Gram matrix)  عن طريق إستدعاء الدالة (gram_matrix) التي قمنا بإنشاءها سابقاً.

السطر رقم (11): نقوم بإستبدال كل عنصر من عناصر المصفوفة الخاصة بمخرجات النمط (style_outputs) بالقيمة الجديدة التي نحصل عليها بعد تنفيذ الدالة (gram_matrix). حيث إنَّ المتغير (count) يمثل الدليل (index) لهذه المصفوفة.

السطر رقم (13): نقوم بتكوين مصفوفة من نوع (dictionary) خاصة بمخرجات المحتوى (Content) حيث إن المفتاح (key) لكل عنصر هو إسم الطبقة (layer)  والقيمة (value) تمثلها مخرجات الطبقة, حيث يتم المزاوجة بين مخرجات كل طبقة (content_outputs) وإسم تلك الطبقة (content_layer) عن طريق الدالة (zip)  العائدة إلى لغة بايثون. وبما إننا قد إستخدمنا طبقة واحدة تخص المحتوى, لذلك فإنَّ هذه المصفوفة تضم عنصراً واحداً فقط.

السطر رقم (15): نفس الخطوة السابقة ولكن هذه المرة فيما يخص مخرجات النمط (Style), علماً إنَّ عدد عناصر المصفوفة سوف يكون خمسة بعدد الطبقات التي إخترناها سابقاً لإستخلاص النمط.

السطر رقم (17): لدمج كلا المصفوفتين (content_dict & style_dict) في مصفوفة واحدة من نوع (Dictionary) أيضاً حيث إنها تمثل القيمة الراجعة للدالة.


السطر رقم (1): للحصول على قيم مخرجات النمط لصورة النمط المرجعية (Style-reference imge) وذلك عن طريق إستدعاء الدالة السابقة (style_content_activations) وتمرير بيانات هذه الصورة لها (style_image) وإختيار الجزء المتعلق بالنمط عن طريق إستخدام المفتاح (style).

السطر رقم (2): كما في السطر السابق ولكن هنا متعلقة بمخرجات صورة المحتوى (Content image).

السطر رقم (3): إنشاء المتغير الخاص بالصورة المتولدة (Generated image) وذلك بالإستفادة من نفس الصورة الخاصة بالمحتوى (Content image) لكي لانقوم بتوليدها من الصفر حيث نقوم بتحديثها فقط لاحقا,

وقد سمينا هذا المتغير (image).

السطر رقم (4): إنشاء أداة التحسين (Optimizer) وقد إخترنا الخوارزمية المسماة (Adam) وقد مررنا لها بعض المعاملات الضرورية. تقوم هذه الأداة بعملية التحديث لقيم بكسلات الصورة المتولدة.

السطر رقم (5): لتحديد نسبة مساهمة قيمة الفقد الخاصة بالنمط في عملية التحديث للصورة المتولدة.

السطر رقم (6): لتحديد نسبة مساهمة قيمة الفقد الخاصة بالمحتوى في عملية التحديث للصورة المتولدة.


السطر رقم (1): تستخدم هذه الجملة من الكود لتسريع الأداء وذلك بتحويل العمليات (operations) إلى رسوم (graphs) وذلك لتخطي التقنية المسماة بالتنفيذ الحريص (Eager execution) التي تتميز بها مكتبة (Tensorflow) الإصدار الثاني. يفضل في هذا النوع من الدوال إستخدام المصفوفات من نوع (tensorflow) وليس من نوع (numpy).

الأسطر من (2) لغاية (17): لإنشاء دالة تقوم بعملية حساب قيمة الفقد (Loss) لكل من المحتوى (content_loss) وكذلك للنمط (style_loss), بعدها تقوم بحساب قيمة الفقد النهائي (loss) والذي هو عبارة عن حاصل جمع كلا الفقدين (style_loss + content_loss). كذلك تقوم هذه الدالة بحساب قيمة المشتقة (Gradient) لقيمة الفقد بالنسبة لكل بكسل من بكسلات الصورة المتولدة (generated image) وكذلك القيام بعملية التحديث (upgrade) لكل بكسل لهذه الصورة.

السطر رقم (3): إستدعاء الدالة (GradientTape) التي تقوم بمراقبة وتسجيل قيم المتغيرات الواقعة تحتها, وفي حالتنا تقوم بتسجيل مايحدث لقيم الفقد (loss) الثلاثة والتي هي (style_loss, content_loss & loss).

السطر رقم (4): للحصول على مخرجات كل من المحتوى والنمط للصورة المتولدة (Generated image) عن طريق إستدعاء الدالة (style_content_activations) التي أنشأناها سلفاً وتمرير بيانات هذه الصورة لها.

وقد قمنا بإيداع هذه المخرجات في متغير سميناه (outputs).

السطر رقم (5): إستخلاص المخرجات الخاصة بالنمط للصورة المتولدة, وأودعناها في متغير سميناه (style_outputs).

السطر رقم (6): إستخلاص المخرجات الخاصة بالمحتوى للصورة المتولدة, وأودعناها في متغير سميناه (content_outputs).

السطر رقم (7): حساب قيمة الفقد الخاص بالنمط (style_loss), حيث عملية الحساب تتم كما يلي:

1 – style_outputs[name] – style_targets[name]   ومعنى هذا إننا نقوم بطرح المخرجات الخاصة بالنمط للصورة القياسية للنمط (Style-reference imge) من المخرجات الخاصة بالنمط للصورة المتولدة  (Generated image) لطبقة بعد الأخرى حسب المفتاح (name) والذي نحصل عليه من حلقة التكرار الموجودة في نفس السطر. تكون هذه القيمة عبارة عن متجه (Vector) عدد عناصره بعدد جميع النيورونات التي تحويها جميع مصفوفات الخصائص (Feature maps) في كل طبقة.

2 – نقوم بتربيع القيمة التي حصلنا عليها من السطر السابق.

3 – إستخراج المتوسط الحسابي لقيم المتجه الناتج من السطر السابق وجعلها قيمة واحدة تمثل قيمة الفقد (Loss) لطبقة واحدة, وذلك بإستخدام الدالة (tf.reduce_mean).

4 – نقوم بجمع قيم الفقد للطبقات لتصبح لدينا قيمة واحدة تمثل قيمة الفقد للنمط (style_loss). يتم ذلك بإستخدام الدالة (tf.add_n).

السطر رقم (9): نقوم في هذا السطر بعمليتين حسابيتين الأولى نقوم بقسمة قيمة الفقد الخاص بالنمط على عدد الطبقات التي إخترناها لإستخلاص بيانات النمط (num_style_layers) وذلك لإيجاد معدل قيمة الفقد الخاص بالنمط (Style). والعملية الحسابية الأخرى هي عملية ضرب القيمة الناتجة بالوزن (style_weight) والذي يحدد نسبة مساهمة هذا الفقد بعملية تحديث قيم بكسلات الصورة المتولدة.

الأسطر من (10) لغاية (12): لإجراء نفس الحسابات كما في السطرين السابقين ولكن فيما يخص قيمة الفقد للمحتوى (content_loss).

السطر رقم (13): حساب قيمة الفقد الكلي وذلك بجمع كلا الفقدين (style_loss + content_loss), وتم إيداع القيمة الناتجة في متغير سميناه (loss).

السطر رقم (14): حساب المشتقة (Gradient) لقيمة الفقد بالنسبة لكل بكسل من بكسلات الصورة المتولدة وذلك عن طريق الدالة (gradients). حيث نحصل مصفوفة من قيم المشتقة حجمها بحجم الصورة المتولدة.

السطر رقم (15): القيام بعملية التحديث على بكسلات الصورة المتولدة (Generating image) وذلك بإستخدام أداة التحديث (opt) التي أنشأناها سابقاً  وعن طريق الدالة (applay_gradients).

السطر رقم (16): لإستحداث عينة من الصورة بعد كل خطوة تحديث تحدد فيها أقل قيمة  وأعلى قيمة لبكسلات الصورة المتولدة وذلك عن طريق الدالة (tf.clip_by_value) .

السطر رقم (17): تعين القيمة التي حصلنا عليها في السطر السابق إلى بكسلات الصورة المتولدة (Generating image) لغرض التحديث.



السطر رقم (1): الإعلان عن متغير يسجل عدد خطوات التحديث.

السطر رقم (2): إنشاء حلقة تكرارية تتكرر عشر مرات تمثل الحقب (Epochs).

السطر رقم (3): إنشاء حلقة تكرارية تتكرر مئة مرة تمثل خطوات التحديث (Upgrading steps).

السطر رقم (4): إضافة خطوة واحدة على سجل الخطوات.

السطر رقم (5): إستدعاء الدالة (train_step) وتمرير بيانات الصورة المتولدة (Generated image) إليها.

السطر رقم (6): لإنشاء خط تقدم التنفيذ إثناء تنفيذ الكود.

السطر رقم (8): للقيام بعملية تطبيع لبيانات الصورة لجعلها قابلة للعرض مثل إجراء زيادة على قيم بكسلات الصورة وكذلك للتخلص من البعد الرابع وتحويل بيانات الصورة إلى مصفوفة قابلة للعرض.

عند تنفيذ الخوارزمية على الصورتين أعلاه نحصل على الصورة التالية:


 

 

وبهذا نكون قد إنتهينا من هذه المقالة التي خصصناها لموضوع مهم من المواضيع التي تعتبر من تطبيقات التعلم العميق (Deep Learning) في مجال الفن, ألا وهو الموضوع المسمى تقنية نقل النمط بواسطة الشبكات العصبية (Neural Style Transfer), حيث قمنا بتوضيح الفكرة الأساسية له وكذلك قمنا بإنشاء وتنفيذ أحد التطبيقات لزيادة التوضيح.

أرجو أن أكون قد وفقت للمساهمة بتوضيح هذا الموضوع, ومن ألله تعالى نستمد العون والتسديد.

 

المهندس حسن فنجان عداي. 

 


 







هل اعجبك الموضوع :

تعليقات

تعليق واحد
إرسال تعليق
  1. شرح جيد اتمنى لك التوفيق
    سابقا تم انشاء مكتبة من برمجتي لهذه التقنية باسطر مختزلة وسريعة
    بامكانك تجربتها من مستودع مكتبات البايثون بأسمي

    https://pypi.org/project/StyleTransferArt/

    ردحذف

إرسال تعليق