متعة تعلم الألة Machine Learning – الجزء 3

الـ Deep learning والـ Convolutional Neural Networks

1٬195

هل سئمت من كثرة القراءة عن الـ deep learning ومع ذلك لا تعلم ماذا يعني؟ لنغير هذا المفهوم.

في هذا الدرس سنتعلم كيف نكتب برامج للتعرف علي الـ objects داخل الصور بإستخدام الـ deep learning. سنقوم بتوضيح الصندوق السحري الذي يسمح ل Google Photos بالبحث في صورك بناءً علي ما بداخلها:

كما كان في الجزء 1 والجزء 2، هذا الدرس متاح للجميع الشغوفون لتعلم الـ machine learning ولكن ليس لديهم فكرة عن البداية.

ربما قد رأيت ال xkcd الهزلي الشهير من قبل.

الطفل ذو الثلاث سنوات يمكنه التعرف علي صورة طائر، لكن اللغز المحير لأفضل العلماء علي مدار خمسون عاماً هو كيف أن نجعل الحاسب الآلي قادر علي ذلك أيضاً.

في السنوات القليلة الماضية، توصلنا إلي طريقة جيدة للتعرف علي الأشياء بإستخدام deep convolutional neural networks. لنقم كتابة برنامج للتعرف علي الطيور.

 

بداية سهلة

قبل أن نبدأ في التعرف علي صور الطيور، لنتعلم كيف نتعرف علي شيئ أسهل وهو رقم 8 المكتوب يدوياً.

في الجزء 2، تعلمنا أن الـ neural networks يمكنها حل مشاكل معقدة بربط العديد من الـ neurons معاً. قمنا بإنشاء neural network بسيطة لتخمين سعر منزل بإستخدام معلومات مثل عدد الغرف، الحجم، والجيران.

عرفنا أيضاً أن فكرة الـ machine learning هي أن هناك خوارزميات معممة يمكننا إعادة إستخدامها مع بيانات مختلفة لحل مشاكل كثيرة. لنقم بنغيير تلك الشبكة لنجعلها تتعرف علي الأرقام المكتوبة يدوياً. لجعل الأمر أبسط، سنتعرف فقط علي الرقم 8.

الـ machine learning تعمل فقط حينما يكون لديك بيانات، وحبذا إن كانت كثيرة. لذلك نريد العديد من الصور للرقم 8 مكتوباً يدوياً. قاعدة البيانات MNIST بها 60,000 صورة لأرقام مكتوبة يدوياً كل منها بحجم 18×18. في الصورة التالية يوجد بعض الأمثلة للرقم 8.

 

كل الأشياء تعتبر أرقام

الـ neural networks التي قمنا بعملها من قبل في الجزء 2 فقط إستقبلت ثلاث أرقام كمدخلات. لكننا نريد أن نعمل مع الصور الآن. كيف نقم بإدخال الصورة كمدخلات للـ neural networks بدلاً من فقط بعض الأرقام كما في السابق؟

الأإجابة بسيطة جداً. الـ neural network تستقبل أرقام كمدخلات. للحاسب الآلي، الصورة تتكون من مصفوفة من الأرقام التي تعير عن إضاءة كل pixel بداخلها.

لإدخال صورة كمدخل لـ neural network، نتعامل مع الصورة بحجم 18×18 علي أنها مصفوفة بها 324 رقم:

للتعامل مع الـ 324 مدخل، سنقم فقط بتكبير الـ neural network حتي يكون لديها 324 مدخل:

احظ أن للـ neural network لديها ايضاً مخرجين فقط بدلاً من واحد. المخرج الأول يعبر عن إحتمال وجود رقم 8 داخل الصورة والمخرج الثاني يعبر عن إحتمال عدم وجود 8 داخل الصورة. بوجود مخرج منفصل لكل حالة، يمكننا أن نجعل الـ neural network تقوم بتصنيف العديد من الـ objects في مجموعات منفصلة.

الـ neural network ضخمة مقارنة بالمرة السابقة لأنه يوجد 324 مدخل بدلاً من فقط 3. لكن أي حاسب آلي حديث يمكنه معالجة مثل هذه البيانات في وقت قصير جداً. حتي أن الأمر يعمل جيداً في الهواتف المحمولة.

يبقي فقط تدريب الـ neural network بصور تحتوي علي الرقم 8 وصور أخري لا تحتوي علي الرقم 8. عندما نُدخل فقط صور بها الرقم 8، فإن الـ neural network فإنها تعتقد أن إحتمال وجود صورة بها الرقم 8 هو 100% وإحتمال عدم وجود صورة بها الرقم 8 هو 0%. وأيضاً العكس يتم بإدخال فقط صورة لا يوجد بها الرقم 8.

ها هي بعض بيانات التدريب:

يمكننا تدريب الـ neural network بهذه البيانات في دقائق فقط علي حاسب آلي حديث. بعد الإنتهاء من الأمر، أصبح لدينا neural network تستطيع التعرف علي الصور التي بها الرقم 8 بدقة عالية.

 

مدهش أن نقوم بالتعرف علي الصور. فقط نقوم بإدخال الـ pixels كمدخلات للـ neural network.

لكن الأمر ليس بهذه البساطة.

أولاً، الأخبار السارة أن الـ neural network تتعرف جيداً علي الصور التي بها الرقم 8 موجوداً في وسط الصورة:

لكن الأخبار السيئة:

تفشل الـ neural network بالتعرف علي الرقم 8 حينما لا يكون الرقم موجوداً بمنتصف الصورة. مع أبسط التغييرات الدقة تتغير كثيراً.

السبب أن الـ neural network تعلمت فقط أنماط الصورة التي بها الرقم 8 موجوداً بمنتصف الصور. لكنها لا تعلم شيئاً علي الإطلاق عن الصور التي بها الرقم ليس موجوداً بالمنتصف. إنها تعلم نمط واحد فقط.

لكن المشاكل الموجودة بالواقع مختلفة عن ذلك. نريد أن نعرف كيف أن نجعل الـ neural network قادرة علي التعرف علي الرقم 8 بغض النظر عن موقعة أكان بالمنتصف أو لا.

 

الفكرة الأولي: إستخدام Sliding Window

قمنا بعمل برنامج جيد للتعرف علي الرقم 8 الموجود بمنتصف الصورة. ماذا لو قمنا بالبحث عن الرقم 8 بكل جزء بالصورة، جزء بجزء حتي نجده؟

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

 

الفكرة الثانية: بيانات أكثر مع Deep Neural Network

لنجعل الشبكة تتعرف علي الرقم 8 الموجود في أي مكان بالصورة، يمكننا تدريب الشبكة بصور بها الرقم 8 موجود في أماكن مختلفة.

لا نحتاج لمزيد من اليانات لأنه يمكننا أن نحصل علي صور بها الرقم 8 في أماكن مختلفة من خلال Script يستطيع قص ولصق الرقم 8 في أماكن مختلفة بالصورة.

بإستخدام هذه الطريقة، يمككنا إنشاء عدد لا نهائي من الصور لتدريب الشبكة.

إستخدام العديد من البيانات يجعل الأمر أصعب علي الـ neural network لإيجاد حل. لكننا يمكننا تفادي هذه المشكلة بجعل الـ neural network أكبر وبالتالي تستطيع التعرف علي أنماط معقدة.

لجعل الـ neural network أكبر، يمككنا فقط إضافة العديد من ال neurons.

نسمي هذا ال deep neural network والسبب أنها بها العديد من ال layers مقارنة بالسابق.

هذه الفكرة كانت موجودة من أواخر الستينات لكنها أصبحت مشهورة الآن بفضل وجود أجهزة لديها قدرة حسابية فائقة مقارنة بالأجهزة الموجودة بالسابق. كارت NVIDIA GeForce GTX 1080 يمكنه تدرديب الـ neural network الموجودة في مثالنا بسرعة.

بإنتاج العديد من الصور وإستخدام neural network ضخمة تتدرب علي أجهزر عالية السرعة يمكننا أن نحل المشكلة السابقة. لكن عليها أن نكون أذكي في طريقة معالجة الصور.

لا يجب أن نجعل معالجة الصورة التي تحتوي علي الرقم 8 في أعلي الصورة مختلفة تماماً عن الرقم 8 الموجود بأسف الصورة.

يجب أن نجد طريقة لتعليم الـ neural network أن تتعرعف علي الرقم 8 أياً كان مكانه داخل الصورة بدون تدريبها كثيراً.

 

الحل هو الـ convolution

الإنسان يعلم أن الصور مهيكلة أو شبه مهيكلة. بالنسبة للصورة التالية:

 

الأنسان يستطيع التعرف علي هيكل تلك الصورة كالتالي:

  • أرضية مغطاة بالأسمنت والعشب.
  • يوجد طفل.
  • الطفل يجلس علي حصان هزاز.
  • الحصان الهزاز أعلي العشب.

يمكننا التعرف أنه يوجد طفل بغض النظر علي السطع الموجود عليه. لا نحتاج لإعادة مع كل سطح جديد.

لكن الـ neural network الموجودة حالياً لا تستطيع ذلك. حينما يتواجد الرقم 8 في مكان جديد فإنها تعتبره أنه حالة جديدة مختلفة عن ما سبق. إنها لا تعلم أن فقط تحريك الرقم من مكانه لا يُغير فكرة وجود الرقم داخل الصورة.

نريد إعطاء ال neural network طريقة لنجعلها translation invariance أي لا تعتمد علي مكان واحد فقط للرقم 8.

ما سنقوم به هو convolution. الفكرة جزء منها من علوم الحاسب والجزء الآخر من البيولوجي.

 

كيف تعمل الـ Convolution؟

بدلاً من إدخال الصورة للـ neural network علي أنها شبكة من الأرقام، سنقوم بإدخالها بشكل آخر حتي نستفيد من فكرة أن الـ object يظل كما هو مهما إختلف مكانه في الصورة.

سنعرض كيف لهذا أن يعمل خطوة بخطوة

الخطوة 1: تقسييم الصورة إلي أجزاء متداخلة

شبيهاً بـ sliding window، يمكننا إستخدام sliding window علي كل الصورة ونحفظ كل ناتج بشكل منفصل .مصورة أصغر

بعمل هذا، تك تحويل الصورة إلي 77 جزء متساوي.

الخطوة 2: قم بإدخال كل جزء من الصورة إلي neural network صغيرة.

سابقاً، قمنا بإدخال الصورة كلها إلي الـ neural network لمعرفة إذا ما كان هناك 8 بها. سنفعل نفس الشيئ لكن بإدخال كل جزء صغير علي حدي.

الميزة من هذا أنه سيوجد فقط neural network واحدة صغيرة يتم إستخدامها بنفس الأوزان مع كل تلك الأجزاء. إذا ما ظهر أي شيئ مهم داخل أي جزء، سنقم بمييز هذا الجزء.

الخطوة 3: إحفظ النتائج داخل مصفوفة جديدة

ناتج معالجة كل جزء صغير داخل الصورة سيتم حفظة داخل مصفوفة جديدة تبدو كالتالي:

بمعني آخر، بدأنا بصورة كبيرة وإنتهينا بصورة صغيرة تحفظ فقط المعلومات المهمة داخل الصورة الكبيرة.

 

الخطوة 4: Downsampling

الصورة الأخيرة تعتبر أصغر من الصورة الأصلية لكنها مازالت كبيرة:

لتقليل حجم الصورة، سنستخدم خوارزمية max pooling وذلك لأخذ أهم العينات داخلها.

داخل كل مربع بحجم 2×2 داخل الصورة، سنحتفظ فقط بأكبر القيم بداخله:

الفكرة هو عدم الإحتفاظ إلا بأهم المعلومات التي ستفيدنا في معرفة إذا ما كانت الصورة تحتوي علي الـ object المطلوب. هذا سيقلل حجم المصفوفة.

 

الخطوة الأخيرة: عمل توقعات

قمنا بتقليل حجم الصورة إلي مصفوفة أصغر بكثير.

المصفوفة تعتبر مجموعة أرقام ونستطيع إستخدام تلك الأرقام كمدخلات إلي neural network أخري. آخر neural network ستقرر إذا ما كانت الصورة بها الـ object المطلوب أم لا. لجعلها مختلفة عن خطوة ال convolution، سيتم تسميتها fully connected network.

لذلك من البداية للنهاية،يوجد 5 خطوات:

 

إضافة خطوات أخري

الخطوات التي تم إتباعها في معالجة الصورة هي convolution وmax pooling وأخيراً folly connected network.

لحل المشاكل الواقعية، هذه الخطوات يمكن تكرارها أكثر من مرة كما تريد. يمكنك إستخدام طبقة، إثنان، أو ثلاث طبقات من الـ convolution. يمكنك عدم إستخدام عملية مثلاً مثل عملية الـ max pooling. هذا يرجع لك.

الفكرة أن تبدأ بصورة ضخطة وتستمر في تصغيرها خطوة بخطوة حتي تصل إلي الناتج المطلوب. كلما زادت عدد الـ convolution layers كلما تعقدت ال features التي يمكن للـ neural network أن نتعرف عليها.

علي سبيل المثال، أول خطوة convolution ستتعرف علي الـ edges، الخطوة الثانية تتعرف علي منقار الطائر بتوصيل الـ Edges مع بعض، الخطوة الثالثة يمكنها التعرف علي الطائر كاملاً، وهكذا.

هذا ما تبدو عليه deep convolutional network بشكل واقعي:

 

في هذه الحالة، بدأنا بصورة بحجم 224×224 وطبقنا كل سلسلة من عمليات الـ covolution والـ max pooling حتي نصل إلي الـ fully connected layer. الناتج النهائي هو أن الصورة تم تصنيفها لصنف من ضمن 1000 صنف.

 

بناء الشبكة الصحيحة

كيف لك أن تعرف الخطوات المطلوبة لعمل classifier للصور؟

يجب علك أن تُجيب بعمل العديد من التجارب والإختبارات. يمكن أن تقوم بتدريب 100 شبكة قبل أن تجد الهيكل المثالي للمشكلة. الـ machine learning يتضمن العديد من المحاولات.

 

بناء الـ Bird Classifier

الآن لديك معلومات كافية لكتابة برنامجاً لتصنيف صور الطيور.

كالمعتاد، نحتاج للبيانات كي نبدأ. قاهدة البيانات CIFAR10 تحتوي علي 6,000 صورة للطيور بالإضافة إلي 52,000 صورة أخري للطائرات، الكلاب، القطط، وغيرها. لكن للحصول علي المنزيد من البيانات، سنستخدم أيضاً بيانات من قاعدة Caltech-UCSD Birds-200-2011 والتي بها 12,000 صورة طائر.

ها هي بعض الصور من قاعدتي البيانات المستخدمة:

بعض الصور لغير الطيور:

البيانات المستخدة جيدة للمثال الذي نعمل عليه لكنها صغيرة جداً بالنسبة للتطبيقات الواقعية. إذا ما كنت تريد أن تصل لدقة جودل في التعامل مع الصور، تحتاج لملايين من الصور بدقة عالية. في الـ machine learning، كلما زادت كمية البيانات كلما أصبحت الكفاءة أعلي.

لبناء الـ classifier، سنستخدم الـ TFLearn الذي يعتبر طريقة سهلة للتعامل مع مكتبة TensorFlow من جوجل وبناء convolutional neural networks بعدد أقل من السطور.

ها هو الـكود المستخدم لتدريب الشبكة :

# -*- coding: utf-8 -*-

"""
Based on the tflearn example located here:
https://github.com/tflearn/tflearn/blob/master/examples/images/convnet_cifar10.py
"""
from __future__ import division, print_function, absolute_import

# Import tflearn and some helpers
import tflearn
from tflearn.data_utils import shuffle
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.estimator import regression
from tflearn.data_preprocessing import ImagePreprocessing
from tflearn.data_augmentation import ImageAugmentation
import pickle

# Load the data set
X, Y, X_test, Y_test = pickle.load(open("full_dataset.pkl", "rb"))

# Shuffle the data
X, Y = shuffle(X, Y)

# Make sure the data is normalized
img_prep = ImagePreprocessing()
img_prep.add_featurewise_zero_center()
img_prep.add_featurewise_stdnorm()

# Create extra synthetic training data by flipping, rotating and blurring the
# images on our data set.
img_aug = ImageAugmentation()
img_aug.add_random_flip_leftright()
img_aug.add_random_rotation(max_angle=25.)
img_aug.add_random_blur(sigma_max=3.)

# Define our network architecture:

# Input is a 32x32 image with 3 color channels (red, green and blue)
network = input_data(shape=[None, 32, 32, 3],
                     data_preprocessing=img_prep,
                     data_augmentation=img_aug)

# Step 1: Convolution
network = conv_2d(network, 32, 3, activation='relu')

# Step 2: Max pooling
network = max_pool_2d(network, 2)

# Step 3: Convolution again
network = conv_2d(network, 64, 3, activation='relu')

# Step 4: Convolution yet again
network = conv_2d(network, 64, 3, activation='relu')

# Step 5: Max pooling again
network = max_pool_2d(network, 2)

# Step 6: Fully-connected 512 node neural network
network = fully_connected(network, 512, activation='relu')

# Step 7: Dropout - throw away some data randomly during training to prevent over-fitting
network = dropout(network, 0.5)

# Step 8: Fully-connected neural network with two outputs (0=isn't a bird, 1=is a bird) to make the final prediction
network = fully_connected(network, 2, activation='softmax')

# Tell tflearn how we want to train the network
network = regression(network, optimizer='adam',
                     loss='categorical_crossentropy',
                     learning_rate=0.001)

# Wrap the network in a model object
model = tflearn.DNN(network, tensorboard_verbose=0, checkpoint_path='bird-classifier.tfl.ckpt')

# Train it! We'll do 100 training passes and monitor it as it goes.
model.fit(X, Y, n_epoch=100, shuffle=True, validation_set=(X_test, Y_test),
          show_metric=True, batch_size=96,
          snapshot_epoch=True,
          run_id='bird-classifier')

# Save model when training is complete to a file
model.save("bird-classifier.tfl")
print("Network trained and saved as bird-classifier.tfl!")

 

كلما دربت الشبكة، كلما زادت الدقة. بعد أول دورة، الدقة كانت 75.4%. بعد 10 دورات الدقة وصلت إلي 91.7%.  بعد 50 دورة الدقة وصلت إلي 95.5%. لأن المزيد من الدورات لم تُحسن الناتج، توقفنا عند 50 دورة.

في هذا الوقت، يستطيع البرنامج التعرف علي صور الطيور.

 

إختبار الشبكة

بعد تدريب الشبكة، يمكننا إستخدامها لتوقع حالات جديدة لم تراها الشبكة من قبل.

لكي نعرف كفائة الشبكة، نريد إختبارها علي العديد من الصور. يوجد 15,000 صورة لإختبار الصورة دقة الشبكة كانت 95% بناءً عليهم.

هل هذا يعني أن الدقة عالية؟ هذا يعتمد علي طبيعة المشكلة.

 

هل دقة 95% جيدة؟

الخوارزمية بعد إختبارها وصلت دقتها إلي 95%. لكن هذا لا يعني أنها دقة عالية. فبعض المشاكل تعتبر هذه الدقة فيها ضعيفة. هناك العديد من الحالات التي يُمكن أن يمكن أن تُغير في الدقة.

علي سبيل المثال، ماذا لو كانت نسبة صور الطيور في بيانات التدريب هي فقط 5% ونسبة صور غير الطيور هي 95%؟ البرنامج سيستطيع التعرف علي الصور التي ليس بها طيور بدقة 95% ولكنه بنسبة 100% ليس مهماً للمستخدمين.

لا نريد أن نكتفي فقط بالدقة. نريد أن نعرف عدد المرات التي فشل فيها البرنامج في التعرف علي الطيور.

بدلاً من التفكير في إن كانت التوقعات صحيحة أو خاطئة، يمكننا تقسيمهم إلي أربع أصناف.

أولاً، بعض الصور التي بها طيور ونجح البرنامج في التعرف أن فيهم طيور بالفعل. لنسمي ذلك True Positives:

الصنف الثاني، الصور التي ليس بها طيور ونجح البرنامج في التعرف أنها لا تحتوي علي طيور بالفعل. سنسمي ذلك True Negatives:

الصنف الثالث، الصور التي ليس بها طيور وأخطأ البرنامج في ذلك وتعرف أن بها طيور. هذا يُسمي False Positives:

الصنف الأخير، الصور التي بها طيور وتعرف البرنامج أن ليس بها طيور بشكل خاطئ. هذا يُسمي False Negatives:

بإختبار البرنامج بإستخدام 15,000 صورة، ها هو عدد مرات التوقعات في كل صنف:

لماذا تم تقسييم الناتج بالشكل الواضح أعلي؟ السبب أن ليس كل الأخطاء موجودة بنسب متساوية.

تخيل إن كنا نكتب برنامج لإكتشاف السرطان في الصور. إذا كان هدفنا إكتشاف أن هناك سرطان، يُمكن أن نحصل علي false positives أكثر من false negatives.

بدلاً من إستخدام الدقة، يمكننا حساب كل من Precision وRecall فهم يعطوا صورة أوضح عن كفاءة البرنامج:

 

هذا يُخبرنا أن 97% من المرات التي توقعنا أن الصور بها طيور كانت صحيحة. وأيضاً يُخبرنا أننا وجدنا 90% من الطيور في البيانات. بشكل آخر، لا يمكننا التعرف علي كل الطيور في البيانات لكننا إذا توقعنا أن هناك صورة بها طائير فإننا واثقين من ذلك.

 

ماذا بعد ذلك؟

الأى تعرف أساسيات ال deep convolutional networks، يمكنك إستخدام بعض الأمثلة الموجودة في TFLearn لتتمرن عليها.

يمكنك أيضاً البداية في فروع أخري من الـ machine learning. لما لا تختبر قدرة بعض الخوارزميات لتدريب الحاسب الآلي كي يلعب ألعاب Atari بنفسه.


تم ترجمة هذا المقال بواسطة أحمد جاد.

المقال الأصلي موجود في هذا الرابط لصاحبه (Adam Geitgey).

https://medium.com/@ageitgey/machine-learning-is-fun-part-3-deep-learning-and-convolutional-neural-networks-f40359318721

تعليقات