الشبكة العصبية المتكررة Recurrent Neural Network باسخدام Tensorflow – (الجزء الاول)

705

لماذا نحتاج إلى RNN؟

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

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

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

المشكلة مع هذا النوع من النماذج، انها ليست لديها أي ذاكرة. لا ينظر النموذج ورائه. بمعنى آخر، لا يهتم النموذج بما حدث من قبل. وهو يثير بعض التساؤلات عندما تحتاج إلى التنبؤ بسلسلة من النتائج معتمدة على بعضها البعض لابد أن يكون النموذج على دراية بكل ما حدث في التنبؤات السابقة.

للتغلب على هذه المشكلة، تم تطوير معمارية جديدة للشبكات العصبية: Recurrent Neural network (الشبكة العصبية المتكررة)

في هذا المقال، سوف تتعلم.

  • لماذا نحتاج إلى RNN؟.
  • ما هو RNN؟.
  • تطبيقات RNN.
  • حدود RNN.
  • التحسين LSMT.
  • RNN في سلسلة زمنية.
  • بناء RNN للتنبؤ بالسلسلة الزمنية في TensorFlow.

 

ما هو RNN؟

تبدو الشبكة العصبية المتكررة متشابهة إلى حد بعيد مع الشبكة العصبية التقليدية بإضافة الى الذاكرة التي تضاف إلى الخلايا العصبية.

تخيل نموذجًا بسيطًا يحتوي على خلية عصبية واحدة فقط تم اعطاؤه مجموعة من البيانات. في الشبكة العصبية التقليدية، ينتج النموذج المخرج عن طريق حاصل ضرب المدخلات بالأوزان ووظيفة التنشيط. مع RNN، يتم إرسال هذا المخرج إلى نفسه عدد من المرات. ندعو كل خطوة ب timestep (خطوة الوقت) أي مقدار الوقت حتى يصبح المخرج عبارة عن مدخل في العملية الحسابية القادمة.

على سبيل المثال، في الصورة أدناه، يمكنك رؤية الشبكة تتكون من خلية واحدة. تقوم الشبكة بحساب حاصل ضرب المدخلات والاوزان وتضيف عدم الخطية مع وظيفة التنشيط. يصبح المخرج في T-1 هو مدخل مرة خري.

أدناه، برنامج RNN بسيط في Tensorflow.

تتكون الشبكة من:

  • 4 مدخلات.
  • ستة خلايا.
  • 2 timestep.

تسمى الشبكة بال “المتكررة” لأنها تقوم بنفس العملية في كل نداء لوظيفة التنشيط. تحسب الشبكة أوزان المدخلات وتستعمل المخرجات السابقة من قبل لاستخدام وظيفة التنشيط مرة اخري.

import numpy as np
import tensorflow as tf
n_inputs = 4
n_neurons = 6
n_timesteps = 2
The data is a sequence of a number from 0 to 9 and divided into three batches of data.
## Data 
X_batch = np.array([
        [[0, 1, 2, 5], [9, 8, 7, 4]], # Batch 1
        [[3, 4, 5, 2], [0, 0, 0, 0]], # Batch 2
        [[6, 7, 8, 5], [6, 5, 4, 2]], # Batch 3
    ])

يمكننا البدء في بناء الشبكة مع ال placeholder ، ثم المرحلة المتكررة وفي النهاية المخرجات.

1- تحديد ال placeholder

ال placeholder هو ببساطة متغير سنقوم بتعيين البيانات إليه في وقت لاحق.
يتيح لنا ذلك إجراء العمليات وبناء الرسوم البيانية دون الحاجة إلى البيانات.

X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])
  • None: غير معروف الحجم وسيأخذ دفعة البيانات كلها.
  • n_timesteps: عدد الخطوات حيث ستقوم الشبكة بإرسال المخرجات إلى الخلية مرة اخري كمدخلات.
  • n_inputs: عدد المدخلات.

2- حدد الشبكة المتكررة

في الصورة أعلاه، تتكون الشبكة من 6 خلايا عصبية. ستحسب الشبكة حاصل ضرب المتجهات القياسية لكل من:

  • المدخلات بإضافة الى المجموعة الأولى من الأوزان (أي 6: تساوي عدد الخلايا العصبية).
  • المخرجات السابقة بإضافة الى مجموعة ثانية من الأوزان (أي 6: المقابلة لعدد المخرجات).

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

للبدء ببناء RNN سنقوم ب tf.contrib.rnn.BasicRNNCell مع تمرير num_units لتعريف عدد المدخلات.

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)

الآن بعد أن تم تعريف الشبكة، يمكنك حساب كل من المخرجات والحالات.

outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)	

تستخدم الشبكة حلقة داخلية للقيام بهذه العملية الحسابية لعدد مناسب من المرات.

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

## Define the shape of the tensor
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])
## Define the network
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
init = tf.global_variables_initializer()
init = tf.global_variables_initializer()
with tf.Session() as sess:
    init.run()
    outputs_val = outputs.eval(feed_dict={X: X_batch})
print(states.eval(feed_dict={X: X_batch}))

النتيجة.

[[ 0.38941205 -0.9980438   0.99750966  0.7892596   0.9978241   0.9999997 ]
 [ 0.61096436  0.7255889   0.82977575 -0.88226104  0.29261455 -0.15597084]
 [ 0.62091285 -0.87023467  0.99729395 -0.58261937  0.9811445   0.99969864]]

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

print(outputs_val)    
print(outputs_val.shape)  

النتيجة.

[[[-0.75934666 -0.99537754  0.9735819  -0.9722234  -0.14234993
   -0.9984044 ]
  [ 0.99975264 -0.9983206   0.9999993  -1.         -0.9997506
   -1.        ]]

 [[ 0.97486496 -0.98773265  0.9969686  -0.99950117 -0.7092863
   -0.99998885]
  [ 0.9326837   0.2673438   0.2808514  -0.7535883  -0.43337247
    0.5700631 ]]

 [[ 0.99628735 -0.9998728   0.99999213 -0.99999976 -0.9884324
   -1.        ]
  [ 0.99962527 -0.9467421   0.9997403  -0.99999714 -0.99929446
   -0.9999795 ]]]
(3, 2, 6)

تتشكل المخرجات ب (3، 2، 6):

  • 3: عدد دفعات البيانات
  • 2: عدد timestep
  • 6: عدد الخلايا العصبية

إن تحسين الشبكة العصبية المتكررة هو مماثل للشبكة العصبية التقليدية. سترى مزيد من التفاصيل لاحقا.

 

تطبيقات RNN

RNN لها استخدامات متعددة ، خاصة عندما يتعلق الأمر بالتنبؤ بالمستقبل. في اسواق المال مثلا، يمكن أن تكون RNN مفيدة في التنبؤ بأسعار الأسهم أو وجهتها (أي إيجابية أو سلبية). RNN مفيدة للسيارة ذاتية القيادة لأنها يمكن أن تتجنب حادث اصطام من خلال توقع مسار السيارة.

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

 

حدود RNN

من الناحية النظرية، من المفترض ل RNN أن تحمل هذه المعلومات مع مرور الوقت. ومع ذلك، من الصعب جدًا نشر كل هذه المعلومات عندما تكون time step (الخطوة الزمنية) طويلة جدًا. عندما تحتوي الشبكة على عدد كبير جدًا من الطبقات العميقة، تصبح مهمة التدريب امرا صعباً جدا. تسمى هذه المشكلة: vanishing gradient (اختفاء التدرج). تقوم الشبكة العصبية بتحديث الوزن باستخدام خوارزمية النزول المتدرج. تصبح التدرجات أصغر شيئا فشيئا عندما تتقدم الشبكة إلى طبقات أعمق.

في الختام، يعلن اختفاء التدرج “أي التدرجات ثابتة” أنه لا توجد مجال لتحسين أداء الشبكة. وكما نعرف يعتمد النموذج في الأساس على هذا التغير في التدرج ليتعلم. ويؤثر هذا التغيير على أداء الشبكة. ومع ذلك، إذا كان التغير في التدرج صغيرًا جدًا (على سبيل المثال، تتغير في الأوزان قليلاً)، فلن تتمكن الشبكة من تعلم أي جديد.

 

التحسين LSMT

في منتصف التسعينيات، اقترح الباحثون الألمان سيب هوشاريتر ويورجن شميدهوبر استخدام شكل مختلف للشبكة العصبية المتكررة يسمى Long Short-Term Memory، أو LSTM، كحل لمشكلة اختفاء التغير في التدرج.

تساعد LSTMs في الحفاظ على معدل الخطأ الذي يمكن إعادة نشره عبر الطبقات على مدار الوقت. من خلال الحفاظ على معدل خطأ أكثر ثباتا، فإنها تسمح للشبكة المتكررة بالاستمرار في التعلم عبر العديد من الخطوات الزمنية (أكثر من 1000 مثلا).

هذا هو أحد التحديات الرئيسية للتعلم الآلي والذكاء الاصطناعي، لمزيد من المعلومات من هنا.

الى اللقاء في الجزء الثاني ان شاء الله.

المصدر:(RNN(Recurrent Neural Network) Tutorial: TensorFlow Example)

 

تعليقات