اذهب إلى المحتوى

السؤال

نشر

أقوم ببناء نموذج للتوقع لكن الدقة تكون سيئة جداً عندما استخدم أحد توابع التنشيط مثل sigmoid أو tanh، لكن عندما استخدم تابع التنشيط relu يعطي نتيجة جيدة؟ أريد تفسير؟

 

Recommended Posts

  • 2
نشر

هذا خطأ شائع يقع فيه المبتدئين، وهو استخدام توابع التنشيط في آخر طبقة من طبقات نماذج التوقع، يجب أن تتذكر دوماً أن مسائل التوقع Regression تكون فيها قيم الخرج قيم مستمرة أي قيم غير محدودة بمجال معين أي ليست كما في ال classifications حيث يكون فيها الخرج قيم متقطعة أي قيم معينة. لذلك لايجب استخدام أحد توابع التنشيط معها ولاسيما توابع التنشيط اللوجستية مثل التابع السيني sigmoid أو حتى tanh. لأن هذين التابعين خرجهما يكون بين ال 0 وال 1 (بالنسبة للسيني) و من 1 لل -1 (بالنسبة لل tanh). وبالتالي إذا استخدمت أحدهما في آخر طبقة سيكون خرج نموذجك قيماً محصورة بمجال محدد وهذا خاطئ لأنه في أي مهمة توقع ولتكن مهمة توقع أسعار المنازل مثلاً، يجب أن يكون الخرج قيماً تنتمي إلى مجال غير محدود (قيم مستمرة) أما إذا استخدمت التابع السيني مثلاً سيكون خرج النموذج من أجل أي عينة قيمة محصورة بالمجال من 0 ل 1 والقيمة الحقيقية قد تكون 100 أو 50 أو 77 أو أو.. وبالتالي سيكون مقدار الخطأ في التوقع كبير جداً. لذا يجب ضبط تابع التنشيط في آخر طبقة على None دوماً.
حسناً أنت تتساءل لماذا تابع ال relu يعطيك نتائج جيدة، وهذا صحيح فبالفعل قد يعطيك نتائج جيدة وفي بعض الأحيان قد يعطيك نتائج أفضل من عدم استخدام تابع تنشيط أي None كالمثال التالي، حيث سنستخدم relu  والخطأ المطلق mae=2.2152:

from keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) =boston_housing.load_data()
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(64, activation='relu',
input_shape=(train_data.shape[1],)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(1, activation='relu'))
model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
history = model.fit(train_data, train_targets,epochs=7, batch_size=1, verbose=1)
-------------------------------------------------
Epoch 1/7
404/404 [==============================] - 1s 967us/step - loss: 338.1444 - mae: 15.1877
Epoch 2/7
404/404 [==============================] - 0s 1ms/step - loss: 21.6941 - mae: 3.1332
Epoch 3/7
404/404 [==============================] - 0s 1ms/step - loss: 17.6999 - mae: 2.8479
Epoch 4/7
404/404 [==============================] - 0s 947us/step - loss: 13.1258 - mae: 2.4018
Epoch 5/7
404/404 [==============================] - 0s 970us/step - loss: 15.7603 - mae: 2.6360
Epoch 6/7
404/404 [==============================] - 0s 1ms/step - loss: 12.1877 - mae: 2.3640
Epoch 7/7
404/404 [==============================] - 0s 965us/step - loss: 9.7259 - mae: 2.2152

أما بدونه mae: 2.3221:

from keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) =boston_housing.load_data()
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(64, activation='relu',
input_shape=(train_data.shape[1],)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(1, activation=None))
model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
history = model.fit(train_data, train_targets,epochs=7, batch_size=1, verbose=1)
-----------------------------------------------
Epoch 1/7
404/404 [==============================] - 1s 1ms/step - loss: 280.0789 - mae: 13.5154
Epoch 2/7
404/404 [==============================] - 0s 1ms/step - loss: 19.4468 - mae: 3.0621
Epoch 3/7
404/404 [==============================] - 0s 1ms/step - loss: 17.4921 - mae: 2.9243
Epoch 4/7
404/404 [==============================] - 0s 1ms/step - loss: 14.3356 - mae: 2.6068
Epoch 5/7
404/404 [==============================] - 0s 1ms/step - loss: 12.1125 - mae: 2.4581
Epoch 6/7
404/404 [==============================] - 0s 952us/step - loss: 16.5646 - mae: 2.5852
Epoch 7/7
404/404 [==============================] - 0s 1ms/step - loss: 12.4237 - mae: 2.3221

حسناً كما تلاحظ فإن النتيجة أفضل مع relu، والسبب في أن التابع relu هو تابع خطي خرجه من الشكل:

max(x, 0)

بحيث من أجل دخل x>0 سيكون خرجه هو x نفسها  (أي لاتغيير أي كأننا لم نستخدم تابع تنشيط أي None ) ومن أجل دخل أصغر من الصفر يكون الخرج 0، هذا يعني أنه يسلك سلوك None من أجل الجزء الموجب وكما نعلم فإن أسعار المنازل هي دوماً موجبة وبالتالي استخدام relu سيكون مكافئاً ل None ولكن أفضل لأنه في حالة توقع النموذج قيمة سالبة للنموذج سوف يقصرها على 0 أي إذا توقع -5 سوف يجعلها 0 بسبب تابع ال relu ولهذا السبب كان استخدامه يعطي نتيجة أفضل، لكن هذا لايعني أن استخدامه صحيح وخصوصاً إذا كانت القيم السالبة ضمن مجال التوقع، وأيضاً استخدامه قد يضلل نموذجك قليلاً في الوصول للقيم الصغرى الشاملة لذا أنا أفضل عدم استخدامه.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...