طبقة تطبيع الدُفعات في Keras مكسورة في ذكاء بيانات PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

تم كسر طبقة تطبيع دفعة Keras

تحديث: لسوء الحظ لم يتم قبول طلبي إلى Keras الذي غيّر سلوك طبقة تسوية الدفعة. يمكنك قراءة التفاصيل هنا. بالنسبة لأولئك منكم الذين لديهم الشجاعة الكافية للعبث مع التطبيقات المخصصة ، يمكنك العثور على الرمز في فرعي. يمكنني الاحتفاظ بها ودمجها مع أحدث إصدار ثابت من Keras (2.1.6, 2.2.2 و 2.2.4) لطالما استخدمته ولكن بدون وعود.

معظم الأشخاص الذين يعملون في Deep Learning إما استخدموا أو سمعوا بذلك Keras. بالنسبة لأولئك الذين لم يفعلوا ذلك ، فهي مكتبة رائعة تلخص أطر التعلم العميق الأساسية مثل TensorFlow و Theano و CNTK وتوفر API عالية المستوى لتدريب ANNs. إنه سهل الاستخدام ، ويمكّن من إنشاء نماذج أولية سريعة ولديه مجتمع نشط ودود. لقد استخدمته بكثافة وساهم في المشروع بشكل دوري لبعض الوقت وأوصي به بالتأكيد لأي شخص يريد العمل في Deep Learning.

على الرغم من أن Keras جعلت حياتي أسهل ، فقد تعرضت للعض من السلوك الغريب لطبقة Batch Normalization. لقد تغير سلوكه الافتراضي بمرور الوقت ، ومع ذلك فإنه لا يزال يسبب مشاكل لكثير من المستخدمين ونتيجة لذلك هناك العديد من المشاكل ذات الصلة القضايا المفتوحة على جيثب. في منشور المدونة هذا ، سأحاول إنشاء حالة توضح لماذا لا تعمل طبقة BatchNormalization الخاصة بشركة Keras بشكل جيد مع Transfer Learning ، وسأقدم الرمز الذي يعمل على إصلاح المشكلة وسأقدم أمثلة على نتائج التصحيح.

في الأقسام الفرعية أدناه ، أقدم مقدمة عن كيفية استخدام نقل التعلم في التعلم العميق ، وما هي طبقة التطبيع الدفعي ، وكيف يعمل التعلم_المرحلة وكيف غيّر Keras سلوك BN بمرور الوقت. إذا كنت تعرف هذه بالفعل ، يمكنك القفز بأمان مباشرة إلى القسم 2.

1.1 يعد استخدام نقل التعلم أمرًا بالغ الأهمية للتعلم العميق

أحد أسباب انتقاد Deep Learning في الماضي هو أنه يتطلب الكثير من البيانات. هذا ليس صحيحا دائما؛ هناك العديد من التقنيات لمعالجة هذا القيد ، أحدها نقل التعلم.

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

1.2 ما هي طبقة تسوية الدفعة؟

تم تقديم طبقة تطبيع دفعة في عام 2014 من قبل Ioffe و Szegedy. يعالج مشكلة التدرج المتلاشي من خلال توحيد ناتج الطبقة السابقة ، ويسرع التدريب من خلال تقليل عدد التكرارات المطلوبة ويمكّن من تدريب الشبكات العصبية الأعمق. شرح كيفية عملها بالضبط خارج نطاق هذا المنشور ولكني أشجعك بشدة على قراءة الورقة الأصلية. تفسير مبالغ فيه هو أنه يعيد إدخالها بطرح متوسطها والانقسام مع انحرافها المعياري ؛ يمكنه أيضًا تعلم التراجع عن التحويل إذا لزم الأمر.
طبقة تطبيع الدُفعات في Keras مكسورة في ذكاء بيانات PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

1.3 ما هي مرحلة التعلم في Keras؟

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

يعرف Keras في أي وضع يتم تشغيله لأنه يحتوي على آلية مدمجة تسمى مرحلة التعلم. تتحكم مرحلة التعلم فيما إذا كانت الشبكة في وضع التدريب أو وضع الاختبار. إذا لم يتم تعيينها يدويًا من قبل المستخدم ، أثناء الملاءمة () تعمل الشبكة مع Learning_phase = 1 (وضع القطار). أثناء إنتاج التنبؤات (على سبيل المثال ، عندما نسمي طرق التنبؤ () والتقييم () أو عند خطوة التحقق من الصلاحية الملائمة ()) تعمل الشبكة مع Learning_phase = 0 (وضع الاختبار). على الرغم من أنه لا يوصى بذلك ، يمكن للمستخدم أيضًا تغيير مرحلة التعلم بشكل ثابت إلى قيمة محددة ولكن يجب أن يحدث هذا قبل إضافة أي نموذج أو موتر في الرسم البياني. إذا تم تعيين Learning_phase بشكل ثابت ، فسيتم قفل Keras في أي وضع يختاره المستخدم.

1.4 كيف طبقت Keras تطبيع الدفعات بمرور الوقت؟

لقد قامت Keras بتغيير سلوك Batch Normalization عدة مرات ولكن آخر تحديث هام حدث في Keras 2.1.3. قبل v2.1.3 عندما تم تجميد طبقة BN (قابل للتدريب = خطأ) ، استمرت في تحديث إحصائيات الدفعة ، وهو ما تسبب في صداع ملحمي لمستخدميها.

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

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

2.1 الوصف الفني للمشكلة

تكمن المشكلة في التنفيذ الحالي لـ Keras في أنه عندما يتم تجميد طبقة BN ، فإنها تستمر في استخدام إحصائيات الدفعة الصغيرة أثناء التدريب. أعتقد أن أفضل طريقة عندما يتم تجميد BN هو استخدام المتوسط ​​المتحرك والتباين الذي تعلمته أثناء التدريب. لماذا ا؟ لنفس الأسباب التي لا ينبغي أن يتم تحديث إحصائيات الدُفعة المصغرة بها عند تجميد الطبقة: يمكن أن تؤدي إلى نتائج سيئة لأن الطبقات التالية لم يتم تدريبها بشكل صحيح.

افترض أنك تقوم ببناء نموذج رؤية الكمبيوتر ولكن ليس لديك ما يكفي من البيانات ، لذلك قررت استخدام إحدى شبكات CNN المدربة مسبقًا من Keras وضبطها. لسوء الحظ ، من خلال القيام بذلك ، لن تحصل على أي ضمانات بأن متوسط ​​وتنوع مجموعة البيانات الجديدة الخاصة بك داخل طبقات BN ستكون مشابهة لتلك الموجودة في مجموعة البيانات الأصلية. تذكر أنه في الوقت الحالي ، أثناء التدريب ، ستستخدم شبكتك دائمًا إحصائيات الدُفعة المصغرة إما أن طبقة BN مجمدة أم لا ؛ أيضًا أثناء الاستدلال ، ستستخدم الإحصائيات المكتسبة مسبقًا لطبقات BN المجمدة. ونتيجة لذلك ، إذا قمت بضبط الطبقات العليا ، فسيتم تعديل أوزانها وفقًا لمتوسط ​​/ تباين جديد مجموعة البيانات. ومع ذلك ، سيحصلون أثناء الاستدلال على بيانات يتم تحجيمها بشكل مختلف لأن متوسط ​​/ تباين أصلي سيتم استخدام مجموعة البيانات.
طبقة تطبيع الدُفعات في Keras مكسورة في ذكاء بيانات PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.
أعلاه أقدم بنية مبسطة (وغير واقعية) لأغراض العرض التوضيحي. لنفترض أننا قمنا بضبط النموذج من Convolution k + 1 حتى الجزء العلوي من الشبكة (الجانب الأيمن) ونحتفظ بتجميد الجزء السفلي (الجانب الأيسر). أثناء التدريب ، ستستخدم جميع طبقات BN من 1 إلى k متوسط ​​/ اختلاف بيانات التدريب الخاصة بك. سيكون لهذا آثار سلبية على وحدات ReLU المجمدة إذا لم يكن المتوسط ​​والتباين في كل BN قريبًا من تلك التي تم تعلمها أثناء التدريب المسبق. وسيتسبب أيضًا في تدريب بقية الشبكة (من CONV k + 1 والإصدارات الأحدث) مع المدخلات التي لها مقاييس مختلفة مقارنة بما ستستقبله أثناء الاستدلال. أثناء التدريب ، يمكن لشبكتك التكيف مع هذه التغييرات ، ومع ذلك في اللحظة التي تحول فيها إلى وضع التنبؤ ، ستستخدم Keras إحصائيات التقييس المختلفة ، وهو أمر من شأنه أن يسرع توزيع مدخلات الطبقات التالية مما يؤدي إلى نتائج سيئة.

2.2 كيف يمكنك اكتشاف ما إذا كنت متأثرًا؟

تتمثل إحدى طرق اكتشاف ذلك في تعيين مرحلة التعلم لـ Keras بشكل ثابت إلى 1 (وضع القطار) وإلى 0 (وضع الاختبار) وتقييم نموذجك في كل حالة. إذا كان هناك اختلاف كبير في الدقة على نفس مجموعة البيانات ، فأنت تتأثر بالمشكلة. تجدر الإشارة إلى أنه نظرًا للطريقة التي يتم بها تنفيذ آلية مرحلة التعلم في Keras ، لا يُنصح عادةً بالعبث بها. لن يكون للتغييرات في مرحلة التعلم أي تأثير على النماذج التي تم تجميعها واستخدامها بالفعل ؛ كما ترى في الأمثلة الواردة في الأقسام الفرعية التالية ، فإن أفضل طريقة للقيام بذلك هي البدء بجلسة نظيفة وتغيير مرحلة التعلم قبل تحديد أي موتر في الرسم البياني.

طريقة أخرى لاكتشاف المشكلة أثناء العمل مع المصنفات الثنائية هي التحقق من الدقة والجامعة الأمريكية. إذا كانت الدقة قريبة من 50٪ ولكن الجامعة الأمريكية بالقاهرة قريبة من 1 (وتلاحظ أيضًا الاختلافات بين وضع القطار / الاختبار على نفس مجموعة البيانات) ، فقد يكون ذلك الاحتمالات خارج النطاق بسبب إحصاءات BN. وبالمثل ، بالنسبة للانحدار ، يمكنك استخدام ارتباط MSE و Spearman لاكتشافه.

2.3 كيف يمكننا إصلاحه؟

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

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

2.4 تقييم آثار التصحيح

على الرغم من أنني كتبت التنفيذ أعلاه مؤخرًا ، إلا أن الفكرة الكامنة وراءه تم اختبارها بشكل كبير على مشكلات العالم الحقيقي باستخدام حلول مختلفة لها نفس التأثير. على سبيل المثال ، يمكن تفادي التباين بين أوضاع التدريب والاختبار ويمكن تجنُّبه عن طريق تقسيم الشبكة إلى قسمين (مجمد وغير مجمد) وإجراء تدريب مؤقت (تمرير البيانات عبر النموذج المجمد مرة واحدة ثم استخدامها لتدريب الشبكة غير المجمدة). ومع ذلك ، نظرًا لأن "ثق بي لقد فعلت ذلك من قبل" ليس لها أي وزن عادةً ، فإنني أقدم أدناه بعض الأمثلة التي تظهر آثار التنفيذ الجديد في الممارسة.

فيما يلي بعض النقاط المهمة حول التجربة:

  1. سأستخدم قدرًا ضئيلاً من البيانات لتزويد النموذج عن قصد وسأقوم بتدريب النموذج والتحقق منه على نفس مجموعة البيانات. من خلال القيام بذلك ، أتوقع دقة شبه كاملة وأداء متطابق في مجموعة بيانات القطار / التحقق من الصحة.
  2. إذا حصلت أثناء التحقق على دقة أقل بكثير على نفس مجموعة البيانات ، سيكون لدي إشارة واضحة إلى أن سياسة BN الحالية تؤثر سلبًا على أداء النموذج أثناء الاستدلال.
  3. سيتم إجراء أي معالجة مسبقة خارج المولدات. يتم ذلك لحل الخلل الذي تم تقديمه في الإصدار 2.1.5 (تم إصلاحه حاليًا على الإصدار 2.1.6 القادم وأحدث سيد).
  4. سوف نجبر Keras على استخدام مراحل التعلم المختلفة أثناء التقييم. إذا اكتشفنا الاختلافات بين الدقة المبلغ عنها ، فسنعلم أننا متأثرون بسياسة BN الحالية.

يظهر رمز التجربة أدناه:

import numpy as np
from keras.datasets import cifar10
from scipy.misc import imresize

from keras.preprocessing.image import ImageDataGenerator
from keras.applications.resnet50 import ResNet50, preprocess_input
from keras.models import Model, load_model
from keras.layers import Dense, Flatten
from keras import backend as K


seed = 42
epochs = 10
records_per_class = 100

# We take only 2 classes from CIFAR10 and a very small sample to intentionally overfit the model.
# We will also use the same data for train/test and expect that Keras will give the same accuracy.
(x, y), _ = cifar10.load_data()

def filter_resize(category):
   # We do the preprocessing here instead in the Generator to get around a bug on Keras 2.1.5.
   return [preprocess_input(imresize(img, (224,224)).astype('float')) for img in x[y.flatten()==category][:records_per_class]]

x = np.stack(filter_resize(3)+filter_resize(5))
records_per_class = x.shape[0] // 2
y = np.array([[1,0]]*records_per_class + [[0,1]]*records_per_class)


# We will use a pre-trained model and finetune the top layers.
np.random.seed(seed)
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
l = Flatten()(base_model.output)
predictions = Dense(2, activation='softmax')(l)
model = Model(inputs=base_model.input, outputs=predictions)

for layer in model.layers[:140]:
   layer.trainable = False

for layer in model.layers[140:]:
   layer.trainable = True

model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(ImageDataGenerator().flow(x, y, seed=42), epochs=epochs, validation_data=ImageDataGenerator().flow(x, y, seed=42))

# Store the model on disk
model.save('tmp.h5')


# In every test we will clear the session and reload the model to force Learning_Phase values to change.
print('DYNAMIC LEARNING_PHASE')
K.clear_session()
model = load_model('tmp.h5')
# This accuracy should match exactly the one of the validation set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 0')
K.clear_session()
K.set_learning_phase(0)
model = load_model('tmp.h5')
# Again the accuracy should match the above.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 1')
K.clear_session()
K.set_learning_phase(1)
model = load_model('tmp.h5')
# The accuracy will be close to the one of the training set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))

دعونا نتحقق من النتائج على Keras v2.1.5:

Epoch 1/10
1/7 [===>..........................] - ETA: 25s - loss: 0.8751 - acc: 0.5312
2/7 [=======>......................] - ETA: 11s - loss: 0.8594 - acc: 0.4531
3/7 [===========>..................] - ETA: 7s - loss: 0.8398 - acc: 0.4688 
4/7 [================>.............] - ETA: 4s - loss: 0.8467 - acc: 0.4844
5/7 [====================>.........] - ETA: 2s - loss: 0.7904 - acc: 0.5437
6/7 [========================>.....] - ETA: 1s - loss: 0.7593 - acc: 0.5625
7/7 [==============================] - 12s 2s/step - loss: 0.7536 - acc: 0.5744 - val_loss: 0.6526 - val_acc: 0.6650

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.3881 - acc: 0.8125
2/7 [=======>......................] - ETA: 3s - loss: 0.3945 - acc: 0.7812
3/7 [===========>..................] - ETA: 2s - loss: 0.3956 - acc: 0.8229
4/7 [================>.............] - ETA: 1s - loss: 0.4223 - acc: 0.8047
5/7 [====================>.........] - ETA: 1s - loss: 0.4483 - acc: 0.7812
6/7 [========================>.....] - ETA: 0s - loss: 0.4325 - acc: 0.7917
7/7 [==============================] - 8s 1s/step - loss: 0.4095 - acc: 0.8089 - val_loss: 0.4722 - val_acc: 0.7700

Epoch 3/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2246 - acc: 0.9375
2/7 [=======>......................] - ETA: 3s - loss: 0.2167 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.2260 - acc: 0.9479
4/7 [================>.............] - ETA: 2s - loss: 0.2179 - acc: 0.9375
5/7 [====================>.........] - ETA: 1s - loss: 0.2356 - acc: 0.9313
6/7 [========================>.....] - ETA: 0s - loss: 0.2392 - acc: 0.9427
7/7 [==============================] - 8s 1s/step - loss: 0.2288 - acc: 0.9456 - val_loss: 0.4282 - val_acc: 0.7800

Epoch 4/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2183 - acc: 0.9688
2/7 [=======>......................] - ETA: 3s - loss: 0.1899 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1887 - acc: 0.9792
4/7 [================>.............] - ETA: 1s - loss: 0.1995 - acc: 0.9531
5/7 [====================>.........] - ETA: 1s - loss: 0.1932 - acc: 0.9625
6/7 [========================>.....] - ETA: 0s - loss: 0.1819 - acc: 0.9688
7/7 [==============================] - 8s 1s/step - loss: 0.1743 - acc: 0.9747 - val_loss: 0.3778 - val_acc: 0.8400

Epoch 5/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0973 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0828 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0851 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0897 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0928 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0936 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.1337 - acc: 0.9838 - val_loss: 0.3916 - val_acc: 0.8100

Epoch 6/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0747 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0852 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0812 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0831 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0779 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0766 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0813 - acc: 1.0000 - val_loss: 0.3637 - val_acc: 0.8550

Epoch 7/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2478 - acc: 0.8750
2/7 [=======>......................] - ETA: 2s - loss: 0.1966 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.1528 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.1300 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.1193 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.1196 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.1084 - acc: 0.9838 - val_loss: 0.3546 - val_acc: 0.8600

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0539 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0900 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0815 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0740 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0700 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0701 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0695 - acc: 1.0000 - val_loss: 0.3269 - val_acc: 0.8600

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0306 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0377 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0898 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.0773 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0742 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0708 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0659 - acc: 0.9838 - val_loss: 0.3604 - val_acc: 0.8600

Epoch 10/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0354 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0381 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0354 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0828 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0791 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0794 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0704 - acc: 0.9838 - val_loss: 0.3615 - val_acc: 0.8600

DYNAMIC LEARNING_PHASE
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 0
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 1
[0.025861846953630446, 1.0]

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

بعد الانتهاء من التدريب ، نقوم بتقييم النموذج باستخدام 3 تكوينات مختلفة لمراحل التعلم: ديناميكي ، ثابت = 0 (وضع الاختبار) وثابت = 1 (وضع التدريب). كما يمكننا أن نرى أول تكوينين سيقدمان نتائج متطابقة من حيث الخسارة والدقة وتتطابق قيمتها مع الدقة المبلغ عنها للنموذج في مجموعة التحقق من الصحة في التكرار الأخير. ومع ذلك ، بمجرد أن ننتقل إلى وضع التدريب ، نلاحظ وجود تباين كبير (تحسين). لماذا هذا؟ كما قلنا سابقًا ، يتم ضبط أوزان الشبكة لتتوقع تلقي بيانات مقاسة بمتوسط ​​/ تباين بيانات التدريب. لسوء الحظ ، تختلف هذه الإحصائيات عن تلك المخزنة في طبقات BN. منذ أن تم تجميد طبقات BN ، لم يتم تحديث هذه الإحصائيات. يؤدي هذا التناقض بين قيم إحصائيات BN إلى تدهور الدقة أثناء الاستدلال.

دعونا نرى ما يحدث بمجرد تطبيق التصحيح:

Epoch 1/10
1/7 [===>..........................] - ETA: 26s - loss: 0.9992 - acc: 0.4375
2/7 [=======>......................] - ETA: 12s - loss: 1.0534 - acc: 0.4375
3/7 [===========>..................] - ETA: 7s - loss: 1.0592 - acc: 0.4479 
4/7 [================>.............] - ETA: 4s - loss: 0.9618 - acc: 0.5000
5/7 [====================>.........] - ETA: 2s - loss: 0.8933 - acc: 0.5250
6/7 [========================>.....] - ETA: 1s - loss: 0.8638 - acc: 0.5417
7/7 [==============================] - 13s 2s/step - loss: 0.8357 - acc: 0.5570 - val_loss: 0.2414 - val_acc: 0.9450

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2331 - acc: 0.9688
2/7 [=======>......................] - ETA: 2s - loss: 0.3308 - acc: 0.8594
3/7 [===========>..................] - ETA: 2s - loss: 0.3986 - acc: 0.8125
4/7 [================>.............] - ETA: 1s - loss: 0.3721 - acc: 0.8281
5/7 [====================>.........] - ETA: 1s - loss: 0.3449 - acc: 0.8438
6/7 [========================>.....] - ETA: 0s - loss: 0.3168 - acc: 0.8646
7/7 [==============================] - 9s 1s/step - loss: 0.3165 - acc: 0.8633 - val_loss: 0.1167 - val_acc: 0.9950

Epoch 3/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2457 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.2592 - acc: 0.9688
3/7 [===========>..................] - ETA: 2s - loss: 0.2173 - acc: 0.9688
4/7 [================>.............] - ETA: 1s - loss: 0.2122 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.2003 - acc: 0.9688
6/7 [========================>.....] - ETA: 0s - loss: 0.1896 - acc: 0.9740
7/7 [==============================] - 9s 1s/step - loss: 0.1835 - acc: 0.9773 - val_loss: 0.0678 - val_acc: 1.0000

Epoch 4/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2051 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1652 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1423 - acc: 0.9896
4/7 [================>.............] - ETA: 1s - loss: 0.1289 - acc: 0.9922
5/7 [====================>.........] - ETA: 1s - loss: 0.1225 - acc: 0.9938
6/7 [========================>.....] - ETA: 0s - loss: 0.1149 - acc: 0.9948
7/7 [==============================] - 9s 1s/step - loss: 0.1060 - acc: 0.9955 - val_loss: 0.0455 - val_acc: 1.0000

Epoch 5/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0769 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0846 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0797 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0736 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0914 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0858 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0808 - acc: 1.0000 - val_loss: 0.0346 - val_acc: 1.0000

Epoch 6/10
1/7 [===>..........................] - ETA: 1s - loss: 0.1267 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1039 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0893 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0780 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0758 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0789 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0738 - acc: 1.0000 - val_loss: 0.0248 - val_acc: 1.0000

Epoch 7/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0344 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0385 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0467 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0445 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0446 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0429 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0421 - acc: 1.0000 - val_loss: 0.0202 - val_acc: 1.0000

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0319 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0300 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0320 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0307 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0303 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0291 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0358 - acc: 1.0000 - val_loss: 0.0167 - val_acc: 1.0000

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0246 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0255 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0258 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0250 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0252 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0260 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0327 - acc: 1.0000 - val_loss: 0.0143 - val_acc: 1.0000

Epoch 10/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0251 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0228 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0217 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0249 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0244 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0239 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0290 - acc: 1.0000 - val_loss: 0.0127 - val_acc: 1.0000

DYNAMIC LEARNING_PHASE
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 0
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 1
[0.01744014158844948, 1.0]

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

2.5 كيف يعمل التصحيح على مجموعة بيانات حقيقية؟

فكيف يعمل التصحيح في تجربة أكثر واقعية؟ دعنا نستخدم ResNet50 الذي تم تدريبه مسبقًا من Keras (الذي كان مناسبًا في الأصل على imagenet) ، وقم بإزالة طبقة التصنيف الأعلى وضبطها باستخدام التصحيح أو بدونه ومقارنة النتائج. بالنسبة للبيانات ، سنستخدم CIFAR10 (تقسيم القطار / الاختبار القياسي المقدم من Keras) وسنقوم بتغيير حجم الصور إلى 224 × 224 لجعلها متوافقة مع حجم إدخال ResNet50.

سنفعل 10 حقب لتدريب طبقة التصنيف الأعلى باستخدام RSMprop ثم سنقوم بعمل 5 أخرى لضبط كل شيء بعد الطبقة 139 باستخدام SGD (lr = 1e-4 ، الزخم = 0.9). بدون التصحيح ، حقق نموذجنا دقة 87.44٪. باستخدام التصحيح ، نحصل على دقة تبلغ 92.36٪ ، أعلى بنحو 5 نقاط.

2.6 هل يجب تطبيق نفس الإصلاح على طبقات أخرى مثل Dropout؟

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

أعتقد بقوة أنه يجب حل هذا التناقض في Keras. لقد رأيت تأثيرات أكثر عمقًا (من 100٪ إلى 50٪ دقة) في التطبيقات الواقعية الناجمة عن هذه المشكلة. أنا تخطط لإرسالها أرسلت بالفعل PR إلى Keras مع الإصلاح ونأمل أن يتم قبوله.

إذا كنت تحب هذه المدونة ، يرجى تخصيص بعض الوقت لمشاركتها على Facebook أو Twitter. 🙂

الطابع الزمني:

اكثر من داتومبوكس