إنشاء نموذج رؤية للكمبيوتر باستخدام TensorFlow

1. قبل البدء

في هذا الدرس التطبيقي حول الترميز، سيكون عليك إنشاء نموذج رؤية للكمبيوتر يمكنه التعرّف على عناصر الملابس باستخدام TensorFlow.

المتطلبات الأساسية

  • معرفة راسخة بلغة Python
  • مهارات البرمجة الأساسية

ما ستتعرّف عليه

في هذا الدرس التطبيقي حول الترميز:

  • تدريب شبكة عصبونية للتعرّف على مقالات الملابس
  • أكمِل سلسلة من التمارين لتوجيهك خلال تجربة طبقات مختلفة من الشبكة.

العناصر التي سيتم إنشاؤها

  • شبكة عصبونية تحدّد مقالات الملابس

المتطلبات اللازمة

إذا لم تنشئ شبكة عصبونية مطلقًا للرؤية الحاسوبية باستخدام TensorFlow، يمكنك استخدام Colaboratory، وهي بيئة مستندة إلى المتصفّح تحتوي على جميع الاعتماديات المطلوبة. يمكنك العثور على الرمز لبقية الدرس التطبيقي حول الترميز قيد التشغيل في Colab.

وإلا، فإن اللغة الرئيسية التي ستستخدمها لنماذج التدريب هي Python، لذا ستحتاج إلى تثبيتها. بالإضافة إلى ذلك، ستحتاج أيضًا إلى TensorFlow ومكتبة NumPy. ويمكنك التعرُّف على مزيد من المعلومات حول TensorFlow وتثبيتها هنا. ثبِّت تطبيق NumPy هنا.

2. بدء الترميز

أولاً، استكشف مفكرة Colab القابلة للتنفيذ.

يمكنك البدء باستيراد TensorFlow.

import tensorflow as tf
print(tf.__version__)

ستتمكّن من تدريب شبكة عصبونية للتعرّف على أغراض الملابس من مجموعة بيانات شائعة اسمها Fashion MNIST. ويحتوي هذا المتجر على 70 ألف قطعة من الملابس ضمن 10 فئات مختلفة. يظهر كل عنصر من الملابس في صورة بتدرج 28x28. يمكنك الاطّلاع على بعض الأمثلة هنا:

في ما يلي التصنيفات المرتبطة بمجموعة البيانات:

التصنيف

الوصف

0

قميص/قميص

1

سروال

2

بلوفر

3

فستان

4

معطف

5

صندل

6

قميص

7

حذاء رياضي

8

حقيبة

9

الكاحل

تتوفّر بيانات MNIST للأزياء في واجهة برمجة تطبيقات tf.keras.datasets. حمِّله على النحو التالي:

mnist = tf.keras.datasets.fashion_mnist

يستدعي استدعاء load_data على ذلك الكائن مجموعتين من قائمتين: قيم التدريب وقيم الاختبار التي تمثل رسومات تعرض عناصر الملابس وتصنيفاتها.

(training_images, training_labels), (test_images, test_labels) = mnist.load_data()

كيف تبدو تلك القيم؟ طباعة صورة تدريب وتصنيف تدريبي لعرضه ويمكنك إجراء تجربة باستخدام فهارس مختلفة في المصفوفة.

import matplotlib.pyplot as plt
plt.imshow(training_images[0])
print(training_labels[0])
print(training_images[0])

تبدو عملية طباعة بيانات العنصر 0 كما يلي:

ستلاحظ أن جميع القيم عبارة عن أعداد صحيحة بين 0 و255. عند تدريب شبكة عصبونية، يكون من الأسهل التعامل مع جميع القيم باعتبارها بين 0 و1، وهي عملية تُسمّى التسوية. لحسن الحظ، يوفر Python طريقة سهلة لتسوية قائمة مثل هذه بدون تكرار.

training_images  = training_images / 255.0
test_images = test_images / 255.0

قد تريد أيضًا إلقاء نظرة على 42، وهو تشغيل مختلف عن الفهرس في الفهرس 0.

قد تتساءل الآن عن سبب وجود مجموعتَي بيانات؛ هما التدريب والاختبار.

وتكمن الفكرة في وجود مجموعة واحدة من البيانات للتدريب ومجموعة أخرى من البيانات التي لم يتعرّف عليها النموذج حتى الآن لمعرفة مدى جودة تصنيف القيم. وأخيرًا، عند الانتهاء من ذلك، ترغب في استخدام النموذج مع البيانات التي لم يرها من قبل. علاوة على ذلك، بدون بيانات الاختبار المنفصلة، ستخاطر الشبكة بالشبكة من خلال حفظ بيانات التدريب فقط بدون تعميم معرفتها.

3- تصميم النموذج

والآن، صمِّم النموذج. سيكون لديك ثلاث طبقات. تنقّل بينها واحدًا تلو الآخر واستكشف الأنواع المختلفة من الطبقات والمعلّمات المُستخدَمة لكلّ منها.

model = tf.keras.models.Sequential([tf.keras.layers.Flatten(), 
                                    tf.keras.layers.Dense(128, activation=tf.nn.relu), 
                                    tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
  • تحدّد Sequential تسلسلاً للطبقات في الشبكة العصبونية.
  • تأخذ Flatten مربّعًا وتحوّله إلى متّجه أحادي الأبعاد.
  • يضيف Dense طبقة عصبية.
  • توضّح وظائف Activation لكل طبقة من الخلايا العصبية ما يجب فعله. تتوفّر العديد من الخيارات، ولكن يمكنك استخدامها الآن:
  • وتعني القيمة Relu بشكل فعّال أنّه إذا كان قيمة X أكبر من 0، سيتم عرض 0. ولا تمرِّر سوى قيم 0 أو أكبر إلى الطبقة التالية في الشبكة.
  • يتخذ Softmax مجموعة من القيم ويختار الأعلى منها بفعالية. على سبيل المثال، إذا كان مخرجات الطبقة الأخيرة تبدو مثل [0.1، 0.1، 0.05، 0.1، 9.5، 0.1، 0.05، 0.05، 0.05]، فإنها تتيح لك ترتيب النتائج حسب أكبر قيمة، فإنها تعرض [0,0,0,0,1,0,0,0]،0].

4. تجميع النموذج وتدريبه

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

لاحِظ استخدام metrics= كمَعلمة، ما يسمح لنظام TensorFlow بالإبلاغ عن دقة التدريب عن طريق التحقُّق من النتائج المتوقَّعة مقابل الإجابات المعروفة (التصنيفات).

model.compile(optimizer = tf.keras.optimizers.Adam(),
              loss = 'sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(training_images, training_labels, epochs=5)

عندما يتم تنفيذ model.fit، سترى الفقدان ودقة:

Epoch 1/5
60000/60000 [=======] - 6s 101us/sample - loss: 0.4964 - acc: 0.8247
Epoch 2/5
60000/60000 [=======] - 5s 86us/sample - loss: 0.3720 - acc: 0.8656
Epoch 3/5
60000/60000 [=======] - 5s 85us/sample - loss: 0.3335 - acc: 0.8780
Epoch 4/5
60000/60000 [=======] - 6s 103us/sample - loss: 0.3134 - acc: 0.8844
Epoch 5/5
60000/60000 [=======] - 6s 94us/sample - loss: 0.2931 - acc: 0.8926

عند انتهاء النموذج من التدريب، ستظهر لك قيمة دقة في نهاية الحقبة النهائية. قد يبدو مثل 0.8926 كما هو موضح أعلاه. يُخبرك هذا بأن الشبكة العصبونية لديك حوالي 89% دقيقة في تصنيف بيانات التدريب. وبعبارة أخرى، تبيّن لنا أنّ هناك تطابقًا بين نمط الصورة والتصنيفات التي حقّقت نسبة 89% من الوقت. والأمر ليس رائعًا على الإطلاق، بل إنها كانت مُريحة لأنه تم تدريبها لخمس فترات قصيرة وتم إجراؤها بسرعة.

5. اختبار النموذج

ما مستوى أداء النموذج في البيانات التي لم يشاهدها؟ ولهذا السبب، تمّ إعداد مجموعة الاختبار الخاصة بك. يمكنك الاتصال بالرقم model.evaluate واجتياز المجموعتان، وسيتم الإبلاغ عن فقدان كل مجموعة. جرّب بنفسك:

model.evaluate(test_images, test_labels)

وإليك النتيجة:

10000/10000 [=====] - 1s 56us/sample - loss: 0.3365 - acc: 0.8789
[0.33648381242752073, 0.8789]

عرض هذا المثال دقة 0 .8789، ما يعني أنّ المعلومات كانت دقيقة بنسبة 88%. (قد تكون لديك قيم مختلفة قليلاً).

وكما هو متوقّع، لا يكون النموذج دقيقًا مع البيانات غير المعروفة كما هو الحال مع البيانات التي تم تدريبه عليها. ومن خلال الاطّلاع على مزيد من المعلومات حول TensorFlow، ستعثر على طرق لتحسين ذلك.

للاطّلاع على مزيد من التفاصيل، جرِّب التمارين في الخطوة التالية.

6- تمارين الاستكشاف

التمرين 1

بالنسبة إلى هذا التمرين الأول، شغِّل الرمز التالي:

classifications = model.predict(test_images)
print(classifications[0])

وتُنشئ مجموعة من التصنيفات لكل صورة من الصور الاختبارية، ثم تطبع الإدخال الأول في التصنيفات. النتائج بعد التشغيل هي قائمة بالأرقام. لماذا تعتقد أن هذا هو وما تمثّله هذه الأرقام؟

حاوِل تشغيل print(test_labels[0]) وستحصل على 9. هل يساعدك ذلك في فهم سبب ظهور القائمة كما تبدو؟

مخرجات النموذج هي قائمة من 10 أرقام. وهذه الأرقام هي احتمالية أن القيمة التي يتم تصنيفها هي التصنيف المقابل. على سبيل المثال، القيمة الأولى في القائمة هي احتمالية أن الملابس من الفئة 0 والقيمة التالية هي 1. لاحظ أن جميعها احتمالات منخفضة للغاية باستثناء حالة واحدة. بالإضافة إلى ذلك، تحصل على جميع الاحتمالات في القائمة على 1.0 بسبب Softmax.

القائمة والتصنيفات تستند إلى 0، لذا يعني مصطلح "حذاء الكاحل" أنّها الصف العاشر من الصفوف العشرة. وتشير القائمة العاشرة التي تمثّل أعلى قيمة إلى أنّ الشبكة العصبونية توقّعت أنّ العنصر الذي يصنّفه هو على الأرجح أحد الأحذية ذات الكعوب.

التمرين 2

انظر إلى الطبقات في النموذج. وعليك بتجربة قيم مختلفة للطبقة الكثيفة باستخدام 512 عصبون.

ما النتائج المختلفة التي تحصل عليها لوقت الخسارة والتدريب؟ لماذا تعتقد أن هذه هي الحالة؟

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

التمرين 3

ماذا سيحدث إذا أزلت طبقة Flatten(). لماذا تعتقد أن هذه هي الحالة؟

يظهر لك خطأ بشأن شكل البيانات. وقد تبدو تفاصيل الخطأ غامضة في الوقت الحالي، إلا أنها تعزّز القاعدة الأساسية التي مفادها أن الطبقة الأولى في شبكتك يجب أن تكون بنفس شكل بياناتك. في الوقت الحالي، تكون بياناتك بحجم 28x28، و28 طبقة من الخلايا العصبية التي تحتوي على 28 خلية، لن يكون ذلك ممكنًا، لذلك من الأسهل دمج 28.28 في 784x1.

وبدلاً من كتابة كل الرموز، أضِف طبقة Flatten() في البداية. عند تحميل المصفوفات إلى النموذج لاحقًا، سيتم دمجها تلقائيًا لك.

التمرين 4

ضع في اعتبارك الطبقات النهائية (الإخراج). لماذا يتضمّن الرقم 10 منها؟ ماذا سيحدث إذا كان لديك مبلغ مختلف عن 10؟

حاوِل تدريب الشبكة باستخدام الرقم 5. تحصل على خطأ فور العثور على قيمة غير متوقعة. قاعدة أساسية أخرى: يجب أن يتطابق عدد الخلايا العصبية في الطبقة الأخيرة مع عدد الفئات التي تصنّفها. في هذه الحالة، تكون الأرقام 0 إلى 9، وبالتالي هناك 10 منها، وبالتالي يجب أن يكون لديك 10 خلايا عصبية في الطبقة النهائية.

التمرين 5

وعليك مراعاة تأثيرات الطبقات الإضافية في الشبكة. ماذا سيحدث إذا أضفت طبقة أخرى بين الطبقة التي تحتوي على 512 والطبقة النهائية التي تحتوي على 10؟

ليس هناك تأثير كبير لأن هذه البيانات بسيطة نسبيًا. بالنسبة إلى البيانات الأكثر تعقيدًا، غالبًا ما تكون الطبقات الإضافية ضرورية.

التمرين 6

قبل التدريب، كنت قد عدّلت البيانات من القيم التي كانت 0 إلى 255 إلى القيم التي كانت 0 إلى 1. ما تأثير ذلك؟ في ما يلي الرمز الكامل لتجربته (لاحظ أن السطرين الذين يطابقان البيانات قد تم التعليق عليها).

لماذا تعتقد أنك تحصل على نتائج مختلفة؟ هناك إجابة رائعة هنا على Stack Overflow.

import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
#training_images=training_images/255.0
#test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
model.fit(training_images, training_labels, epochs=5)
model.evaluate(test_images, test_labels)
classifications = model.predict(test_images)
print(classifications[0])
print(test_labels[0])

7- استكشاف معاودة الاتصال

في وقت سابق، عندما تدرّبت على فترات إضافية، واجهت مشكلة قد تتغيّر فيها خسارتك. قد يستغرق الأمر بعض الوقت لانتظار التدريب لإجراء ذلك وقد تظن أنّه من المفيد أن توقف التدريب عند الوصول إلى القيمة المطلوبة، مثل الدقة بنسبة 95%. إذا وصلت إلى ذلك بعد 3 حقبات، فلمَ لا تنتظرها حتى تنتهي من المزيد من الفترات؟

مثل أي برنامج آخر، هناك معاودة اتصال. أمثلة واقعية:

import tensorflow as tf

class myCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs={}):
    if(logs.get('accuracy')>0.95):
      print("\nReached 95% accuracy so cancelling training!")
      self.model.stop_training = True

callbacks = myCallback()
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images/255.0
test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5, callbacks=[callbacks])

8- تهانينا

لقد أنشأت أول نموذج رؤية للكمبيوتر. للتعرّف على كيفية تحسين نماذج الرؤية على الكمبيوتر، انتقِل إلى إنشاء خلطات وإجراء التجميع.