يستخدم العديد من غير الخبراء الكود التالي http://stackoverflow.com/questions/33949786/how-could-i-use-batch-normalization-in-tensorflow؟answertab=votes#tab -top.
سيكون من الجيد أن يكون لديك طبقة معيار مجموعة رسمية نظرًا لأهميتها في تدريب DNNs.
أنا أعمل على بعض أجزاء ذلك.
أعتقد أن هناك خطأ ما في هذه الطبقة. في التدريب كل شيء على ما يرام والخسارة تنخفض بشكل جيد للغاية. لكن في الاختبار لا أحصل على دقة.
بالمناسبة في الاختبار عندما أستخدم is_training = False ، أحصل على صفر acc.
أعرف أن تطبيع الدفعات يتصرف بشكل مختلف في القطار ومرحلة الاختبار ، كما هو موضح في كيف يتصرف تطبيع الدُفعات بشكل مختلف في وقت التدريب ووقت الاختبار؟
نفس الشيء هنا ، لقد واجهت بعض السلوك غير المتوقع مع is_training = False. ما هي الطريقة الصحيحة لتغيير هذا العلم؟ أستخدم حاليًا tf.cond
لأنه لا يأخذ tf.placeholders
بمفرده.
pawni عليك استخدام بايثون منطقية مقابل is_training
. لا يمكن أن يكون tf.cond
.
ppwwyyxx حسنًا ، أقوم بعمل tf.cond(placeholder, batch_norm(.., is_training = True), batch_norm(.., is_training = False))
أم أنه من المفترض أن يقوم أحدهم بعمل batch_norm(.., is_training=variable)
وتغيير ذلك خارج الرسم البياني عند الحاجة؟
أوه اعتقدت أنك كنت تفعل batch_norm(.., is_training=tf.cond(placeholder))
، وهذا غير صحيح.
طريقتك الحالية قد تواجه مشاكل أيضًا. ستحتاج إلى التحقق مرة أخرى من أن عمليتي batch_norm
op اللتين أنشأتهما تشتركان في نفس النطاق ، وإلا فلن يشاركا إحصائيات المتوسط / التباين الأساسية.
للقيام بذلك ، قد تساعد الوسيطة reuse
، لكنني لست متأكدًا لأنني أستخدم إصداري الخاص من طبقة bn.
أنا أستخدم نفس النطاق و reuse=True
. يبدو أنه يعمل في بعض الأحيان ولكني لست متأكدًا تمامًا. سيكون من الرائع أن تتم إضافة الطبقة إلى الوثائق مع شرح موجز لكيفية التعامل بشكل أفضل مع التغيير من التدريب إلى الاختبار.
sguada لمعلوماتك
في الوقت الحالي ، تتطلب batch_norm وجود لغة python boolean ، لكننا نعمل على إضافة خيار تمرير Tensor.
pawni إذا كنت لا تريد أن تقلق بشأن تحديث move_mean و move_variance set updates_collections = لا شيء للتأكد من تحديثها في مكانها ، وإلا فإنك تحتاج إلى التأكد من أن update_ops المضاف إلى tf.GraphKeys.UPDATE_OPS يتم تشغيله أثناء التدريب.
أعتقد أن tensorflow يحتاج إلى طريقتين مفرطتين لتغيير حالة النموذج ، شيء مثل الشعلة. تغيير حالة النموذج . أعتقد أنه واضح جدا.
هل يوجد نص صغير يحتوي على NN بسيط للغاية يوضح الطريقة الصحيحة لاستخدام طبقة BN "الرسمية"؟ أنا حقا أقدر ذلك.
آسف إذا كان هذا متكررًا بعض الشيء ، لكن يبدو أن واجهة برمجة التطبيقات تتحدث عن BN في واجهة مختلفة: https://www.tensorflow.org/versions/r0.9/api_docs/python/nn.html#batch_normalization
أليست هذه هي الطريقة الرسمية لاستخدام BN؟ أنا في حيرة من أمري حول كيفية استخدامها ويبدو أن SO قديم ، ثم هناك طبقة في رابط مختلف عن واجهة برمجة التطبيقات ، فكيف يفعل المرء ذلك بالضبط؟ ليس من الواضح ما إذا كنت سأذهب إلى SO أو أسأل هنا.
آسف على إرسال الرسائل غير المرغوب فيها ، ولكن ما الخطأ في مجرد استخدام شيء مثل هذا:
def standard_batch_norm(l, x, n_out, phase_train, scope='BN'):
"""
Batch normalization on feedforward maps.
Args:
x: Vector
n_out: integer, depth of input maps
phase_train: boolean tf.Varialbe, true indicates training phase
scope: string, variable scope
Return:
normed: batch-normalized maps
"""
with tf.variable_scope(scope+l):
#beta = tf.Variable(tf.constant(0.0, shape=[n_out], dtype=tf.float64 ), name='beta', trainable=True, dtype=tf.float64 )
#gamma = tf.Variable(tf.constant(1.0, shape=[n_out],dtype=tf.float64 ), name='gamma', trainable=True, dtype=tf.float64 )
init_beta = tf.constant(0.0, shape=[n_out], dtype=tf.float64)
init_gamma = tf.constant(1.0, shape=[n_out],dtype=tf.float64)
beta = tf.get_variable(name='beta'+l, dtype=tf.float64, initializer=init_beta, regularizer=None, trainable=True)
gamma = tf.get_variable(name='gamma'+l, dtype=tf.float64, initializer=init_gamma, regularizer=None, trainable=True)
batch_mean, batch_var = tf.nn.moments(x, [0], name='moments')
ema = tf.train.ExponentialMovingAverage(decay=0.5)
def mean_var_with_update():
ema_apply_op = ema.apply([batch_mean, batch_var])
with tf.control_dependencies([ema_apply_op]):
return tf.identity(batch_mean), tf.identity(batch_var)
mean, var = tf.cond(phase_train, mean_var_with_update, lambda: (ema.average(batch_mean), ema.average(batch_var)))
normed = tf.nn.batch_normalization(x, mean, var, beta, gamma, 1e-3)
return normed
ثم من السهل إخبار tensorflow أي واحد يستخدم مع قاموس موجز كما في:
feed_dict = {x: Xminibatch, y_: Yminibatch, phase_train: True}
sess.run(fetches=[merged,train_step], feed_dict=feed_dict)
نظرًا لأنه من غير الواضح ما إذا كان التنفيذ سيتغير ، فقد أردت تقديم اقتراح (لاحظ أنه من السهل توسيعه ليشمل التلافيف والأشياء التي لم ألصقها للتو).
لمppwwyyxxpawni يا رفاق تقرر ما إذا كان لديك لاستخدام إعادة استخدامها إلى true لحل القضية الاستطلاعية؟
@ brando90 حاليًا أفعل شيئًا مثل:
def BatchNorm(inputT, is_training=True, scope=None):
return tf.cond(isTraining,
lambda: batch_norm(inputT, is_training=True,
center=False, updates_collections=None, scope=scope),
lambda: batch_norm(inputT, is_training=False,
updates_collections=None, center=False, scope=scope, reuse = True))
ومع ذلك ، أعتقد أن # 3265 سيرغب بشكل أساسي في تنفيذه على هذا النحو. يمكن الإشارة إلى تطبيق التسرب هنا: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/layers/python/layers/layers.py#L433 -L435
عندما تكون updates_collections = لا شيء ، فإن التحديثات تحدث في مكانها ومن الأسهل استخدام tf.cond () للسماح بكون is_training أكثر تعقيدًا عندما تتأخر التحديثات ويتم تشغيل update_ops لاحقًا.
سأحاول الحصول على الجزء الأول قريبًا.
@ brando90pawni كود انه يعمل بشكل جيد، ولكن يجب أن تغير مثل أدناه
def BatchNorm(inputT, is_training=True, scope=None):
# Note: is_training is tf.placeholder(tf.bool) type
return tf.cond(is_training,
lambda: batch_norm(inputT, is_training=True,
center=False, updates_collections=None, scope=scope),
lambda: batch_norm(inputT, is_training=False,
updates_collections=None, center=False, scope=scope, reuse = True))
وعند الجري في وقت التدريب أو الاختبار ،
# when training
sess.run([opt, loss], feed_dict={x: bx, y: by, is_training=True})
# when test
sess.run([opt, loss], feed_dict={x: bx, y: by, is_training=False})
يعمل هذا الرمز ، ولكن مثل # 3265 يقول إنه سيكون رائعًا إذا حصل المتغير tf.contrib.layers.batch_norm
على is_training
أنه tf.plcaeholer
nmhkahn بفضلpawni لمقتطفات الشفرة. لقد كانت مفيدة جدًا في إضافة تطبيع الدفعات إلى شبكة الالتفاف الخاصة بي. يبدو أن التدريب يعمل بشكل جيد للغاية. الاختبار ليس كذلك. في بعض إصدارات الكود ، تكون دقة التدريب أعلى بكثير من دقة الاختبار ، مما يعني على الأرجح أنني لا أشارك معلمات تطبيع الدُفعات. في الإصدارات الأخرى من الكود ، أحصل على "ValueError: Variable conv1 / beta موجود بالفعل ، غير مسموح به. هل تقصد تعيين reuse = True في VarScope؟" والتي يبدو أنها تشير إلى أنني أحاول إعادة تعلم المعلمة ... عندما كنت أحاول إعادة استخدامها.
هل يمكن لشخص أن يقدم مثالاً على كيفية استدعاء وظيفة "def BatchNorm" أثناء التدريب والاختبار بحيث تحدث مشاركة المتغير بشكل صحيح.
شكرا على اي مساعدة.
تحديث 25 يوليو 2016:
nmhkahn بفضلpawni لتعليقاتكم. بعد إلقاء نظرة فاحصة على الكود في المساهمة أدركت ما هي مشكلتي. أثناء التدريب والاختبار ، نقوم إما بتحديث أو إعادة استخدام أربعة متغيرات (بيتا ، جاما ، متوسط الحركة ، تباين الحركة). لجعل هذه فريدة من نوعها ، كان علي تعيين نطاق لكل طبقة. لقد فعلت ذلك مثل هذا:
conv1 = tf.nn.relu (batch_norm_layer (conv2d_stride2_valid (data، W_conv1) + b_conv1، train_phase، range = "conv1"))
حيث batch_norm_layer مشابهة للأمثلة منpawninmhkahn، conv2d_stride2_valid هو مجرد مواطنه لتحديد طبقة التلافيف، وW_conv1 وb_conv1 متغيرات عقد الأوزان والانحيازات. ربما يمكنني إزالة مصطلح التحيز لأننا نستخدم تطبيع الدفعات.
الشبكة تعمل بشكل جيد الآن. لاحظت بعد دقة الرسم في وضعي التدريب والاختبار أن دقة الاختبار تبدأ في الارتفاع بعد دقة التدريب. عند الرجوع إلى الماضي ، يكون هذا منطقيًا لأننا نجمع إحصاءات مجموعة البيانات للاختبار. لكن بدا الأمر كما لو كنت أفعل شيئًا خاطئًا أثناء اختباراتي الأولية. نشكرك على تعليقاتك وإتاحة التطبيع الجماعي للمجتمع.
nmhkahn كيف تختلف عن اقتراح pawni؟
@ brando90 كان لدي خطأ بسيط في إصداري والذي تم إصلاحه بواسطة nmhkahn (تغيير isTraining
إلى is_training
)
diegoAtAlpine لقد وجدت نفس المشاكل - لست متأكدًا من سبب ذلك. ومع ذلك ، يجب حل ValueError بواسطة مقتطف التعليمات البرمجية. لست متأكدًا مما تريد رؤيته في كيفية تسميته حيث يبدو أن أمثلة nmhkahn تؤدي المهمة؟
nmhkahnpawni @ عندما تفعل:
sess.run([opt, loss], feed_dict={x: bx, y: by, is_training=True})
ألا يعني ذلك أن استخدامك is_training
كعنصر نائب؟ لقد علق الأشخاص بأنهم يريدون is_training
ليكون حامل الغشاء ولكن هذا ما كان لدي لنسختي منه:
def batch_norm_layer(x,train_phase,scope_bn):
bn_train = batch_norm(x, decay=0.999, center=True, scale=True,
is_training=True,
reuse=None, # is this right?
trainable=True,
scope=scope_bn)
bn_inference = batch_norm(x, decay=0.999, center=True, scale=True,
is_training=False,
reuse=True, # is this right?
trainable=True,
scope=scope_bn)
z = tf.cond(train_phase, lambda: bn_train, lambda: bn_inference)
return z
أليس هذا صحيحا؟
لقد قمت بالفعل بتمديد tf.contrib.layers.batch_norm للسماح بتمرير Tensor أو عنصر نائب لـ is_training. سيتم دمجها في TF المساهمة قريبًا.
متوفر الآن بتنسيق
https://github.com/tensorflow/tensorflow/commit/9da5fc8e6425cabd61fc36f0dcc1823a093d5c1d#diff -94bbcef0ec8a5cdef55f705e99c2b2ed
هل أنا فقط أم أن إضافة طبقة BN هذه تبطئ بشكل ملحوظ تدريب فترة واحدة؟
@ brando90 إنه يبطئ التدريب بالنسبة لي أيضًا ولكن أعتقد أن هذا متوقع لأنه يحتاج إلى حساب بعض الإحصائيات. ونسختك تبدو جيدة بالنسبة لي.
BatchNorm حاليًا بطيء جدًا (بسبب جميع الإحصائيات المحسوبة) ، لكنهم يعملون على إضافة عملية تشغيل دفعة cudnn كما قيل هنا .
nmhkahn سؤال سريع. عندما كتبت (للاختبار):
sess.run([opt, loss], feed_dict={x: bx, y: by, is_training=False})
من الناحية النظرية ، هل يمكن أن تكون bx وأي مجموعة بيانات؟ على سبيل المثال ، يمكن أن تظل مجموعة التدريب على الرغم من أننا لا نتدرب؟ (أي فقط لتتبع خطأ القطار)
@ brando90 أنت على حق.
أنا أيضًا مرتبك فيما يتعلق بـ is_training وإعادة استخدام الأعلام. لقد أنشأت برنامجًا يتبع مثال CIFAR ، حيث تم تنظيم الكود الخاص بي كما في CIFAR:
وأنا أقوم بتشغيله بأسلوب متعدد الجرافيكس (للتدريب).
لذلك لدي برنامج نصي واحد للتدريب (مشابه لـ cifar10_multigpu.py) وآخر للاختبار (مشابه لـ cifar10_eval.py).
وبالتالي
for ii in xrange(2): # Num of GPU
with tf.device('/gpu:%d' % ii):
with tf.name_scope('device_%d' % ii) as scope:
data_batch, label_batch = factory.GetShuffleBatch(batch_size)
unnormalized_logits = factory.MyModel(dataBatch=data_batch, numClasses=numClasses,
isTraining=True)
More stuff happening
tf.get_variable_scope().reuse_variables()
يحدث الاستدلال مع الوظيفة MyModel. (فيما يلي مثال على الوظيفة ، في الواقع أستخدم المزيد من الطبقات والخلايا العصبية).
def MyModel(data_batch, num_classes, feature_dim):
# Hidden Layer 1
with tf.variable_scope('hidden1') as scope:
weights = variable_on_cpu('weights',[feature_dim, 256], tf.truncated_normal_initializer(stddev=0.04))
biases = variable_on_cpu('biases', [256], tf.constant_initializer(0.001))
hidden1 = tf.nn.relu(tf.matmul(data_batch, weights) + biases, name=scope.name)
# Hidden Layer 2
with tf.variable_scope('hidden2') as scope:
weights = variable_on_cpu('weights',[256, 256], tf.truncated_normal_initializer(stddev=0.04))
biases = variable_on_cpu('biases', [256], tf.constant_initializer(0.001))
hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases, name=scope.name)
# output, unnormalized softmax
with tf.variable_scope('softmax_unnorm') as scope:
weights = variable_on_cpu('weights', [256, num_classes], tf.truncated_normal_initializer(stddev=1/num_classes))
biases = variable_on_cpu('biases', [num_classes], tf.constant_initializer(0.0))
softmax_un = tf.add(tf.matmul(hidden2, weights), biases, name=scope.name)
return softmax_un
أريد إجراء ترشيح دفعة. لذلك عندما فعلت:
def MyModel(data_batch, num_classes, feature_dim, isTraining):
with tf.variable_scope('bnormalization') as scope:
norm_data_batch = tcl.batch_norm(inputs=dataBatch, epsilon=0.0001, is_training=isTraining,
reuse=True, scope=scope)
# Hidden Layer 1
with tf.variable_scope('hidden1') as scope:
weights = variable_on_cpu('weights',[feature_dim, 256], tf.truncated_normal_initializer(stddev=0.04))
biases = variable_on_cpu('biases', [256], tf.constant_initializer(0.001))
hidden1 = tf.nn.relu(tf.matmul(data_batch, weights) + biases, name=scope.name)
حصلت على الخطأ التالي في مرحلة التدريب:
عدم وجود شذوذ متغير / بيتا غير موجود ، غير مسموح به. هل تقصد تعيين إعادة الاستخدام = لا شيء في VarScope؟
من خلال ما كنت أقرأه في هذا الموضوع في مرحلة التدريب ، يجب أن أستخدم إعادة الاستخدام = لا شيء. هل حصلت على هذا الجزء الصحيح؟ إذا كان هذا صحيحًا ، فبما أني أستخدم جهازي GPUS ، فهل يجب إعادة استخدام = لا شيء في وحدة معالجة الرسومات الأولى وإعادة استخدام = صحيح في الثانية؟ أو بما أنني أقوم بعمل tf.get_variable_scope (). reuse_variables () فإنه يعتني بنفسه؟
أخيرًا ، في مرحلة الاختبار ، هل يجب أن يكون لدي is_training = False and reuse = True؟
أي مساعدة يحظى بتقدير كبير.
الآن يقبل tf.contrib.layers.batch_norm Tensor أو Variable أو Placeholder كـ is_training
https://github.com/tensorflow/tensorflow/commit/9da5fc8e6425cabd61fc36f0dcc1823a093d5c1d#diff -94bbcef0ec8a5cdef55f705e99c2b2ed
هل من الطبيعي أن تجعل ميزة "تسوية الدفعات" تجاربي أسوأ ؟ لقد جربتها على شبكة NN ذات الطبقتين استنادًا إلى البرنامج التعليمي للمبتدئين MNIST وأحصل دائمًا على نتائج أسوأ عندما يكون BN موجودًا: مع BN (أحدهما مع مقياس ومركز مدرب والآخر ليس) دقة 0.8423 ، 0.8221 وبدون دقة BN 0.9477.
البرنامج النصي الخاص بي موجود هنا https://github.com/brando90/tensor_flow_experiments/blob/master/tf_tutorials/beginner_tutorial_MNIST_BN.py
لقد عانى أي شخص من هذه المشكلات أو هل BN مثل هذا وأحتاج إلى فعل شيء آخر لإنجاحه؟
يقبل أحدث إصدار من tf.contrib.layers.batch_norm عنصرًا نائبًا لـ is_training ، لذا لا داعي للقيام بذلك بنفسك.
ولكن المهم هو إما أن تقوم بتمرير updates_collections = لا شيء حتى يتم تحديث الفارق المتحرك والمتغير في المكان ، وإلا فستحتاج إلى جمع update_ops والتأكد من تشغيلهما.
أود أن أشجعك على استخدام tf.contrib.layers
أو tf.contrib.slim
لبناء نموذجك.
slim = tf.contrib.slim
def build_NN_two_hidden_layers(x, is_training):
batch_norm_params = {'is_training': is_training, 'decay': 0.9, 'updates_collections': None}
with slim.arg_scope([slim.fully_connected],
activation_fn=tf.nn.relu,
weigths_initializer=tf.contrib.layers.xavier_initializer(),
biases_initializer=tf.constant_initializer(0.1),
normalizer_fn=slim.batch_norm,
normalizer_params=batch_norm_params):
net = slim.fully_connected(x, 50, scope='A1')
net = slim.fully_connected(net, 49, scope='A2')
y = slim.fully_connected(net, 10, activation_fn=tf.nn.softmax, normalizer_fn=None, scope='A3')
return y
sguada لقد غيرت بلدي القديم حيث
أيضًا ، لاحظت أنك قلت إنه عنصر نائب ولم أكن بحاجة إلى القيام بذلك يدويًا. ومع ذلك ، عندما مررت عنصرًا نائبًا لـ is_training ، قالت
TypeError: Using a
tf.Tensor as a Python
bool is not allowed. Use
إذا لم يكن t بلا: instead of
إذا كان t: to test if a tensor is defined, and use the logical TensorFlow ops to test the value of a tensor.
وأشار إلى رمز batch_norm. ربما يكون من الجيد إظهار كيفية استخدام هذا العنصر النائب لأنه يبدو أنني لا أفهم كيف يُفترض استخدامه. شكر! :)
@ brando90
الجزء ذي الصلة من الكود موجود هنا L227-256 .
كما ستلاحظ أن هناك عبارة with ops.control_dependencies
تفرض التحديثات. أعتقد أنه لكي يتم استخدام الشفرة "مباشرة خارج الصندوق" ، يجب أن يكون الإعداد الافتراضي بلا.
بالنسبة لتعليقي أعلاه 1122 ، فقد اكتشفت أن tf.get_variable_scope (). reuse_variables () يعتني بالمسألة ، لذلك في مرحلة التدريب ، يجب أن تكون إعادة استخدام الدفعة رقم دفعة واحدة. يتعلق الأمر بعبارة Variable_op_scope (اقرأ وثائقها في Tensorflow)
استخدام batch_norm مع tf.placeholder
x = tf.placeholder(tf.float32, [None, 784])
is_training = tf.placeholder(tf.bool, [], name='is_training')
y = build_NN_two_hidden_layers(x, is_training)
# For training
sess.run(y, {is_training: True, x: train_data})
# For eval
sess.run(y, {is_training: False, x: eval_data})
كانت المشكلة من قبل هي أنك لم تقم بتحديث moving_mean
و moving_variance
بعد كل خطوة ، عندما تكون updates_collections بلا شيء ، فإنها تفرض التحديثات كجزء من الحساب.
ومع ذلك ، عندما تحتوي الشبكة على العديد من طبقات الدُفعات ، يكون من الأكثر كفاءة جمع كل عمليات التحديث وتشغيلها معًا ، لذلك لا تحتاج كل طبقة إلى انتظار انتهاء التحديث.
y = build_model_with_batch_norm(x, is_training)
update_ops = tf.group(tf.get_collection(tf.GraphKeys.UPDATE_OPS))
sess.run([y, update_ops])
هل تم إحراز أي تقدم في تسريع معيار الدُفعات؟
كنت أحاول استخدام معيار الدُفعات مع NN ثنائي الطبقات متصل بكثافة مع مجموعة بيانات (مسطحة) MNIST (ووحدات relu) لمهمة التشفير التلقائي وأظل أتلقى خطأ NaN. أي شخص يعرف لماذا قد يكون هذا؟ هل هذا ممكن مع BN؟ يبدو مريبًا ، لكن لا يمكن أن يكون إعداد تعليمي ، ومعدل ، وما إلى ذلك (لكنني أفترض أنه لا ينبغي أن يكون ذلك لأن BN يجب أن يكون نوعًا من الفهم لهذا)
sguada لا أفهم الطريقة الصحيحة لاستخدام batch_norm
خاصة فيما يتعلق بالعلم updates_collections
. إذا فهمت بشكل صحيح ما إذا كانت العلامة None
فإن الشبكة ليست فعالة ، لذلك يجب أن أترك updates_collections=tf.GraphKeys.UPDATE_OPS
وبعد ذلك يجب أن أجمع كل تحديثات الدُفعات وتشغيلها معًا.
تقوم بتجميع تحديثات batch_norms عن طريق القيام بما يلي: update_ops = tf.group(tf.get_collection(tf.GraphKeys.UPDATE_OPS))
.
لدي العديد من النماذج المختلفة التي تستخدم طبقات مختلفة من الدفعة ، فلن يعمل هذا بشكل صحيح ؟:
#model 1
y1 = build_model_with_batch_norm(x, is_training)
update_ops1 = tf.group(tf.get_collection(tf.GraphKeys.UPDATE_OPS))
sess.run([y1, update_ops1])
#model 2
y2 = build_model_with_batch_norm(x, is_training)
update_ops2 = tf.group(tf.get_collection(tf.GraphKeys.UPDATE_OPS))
sess.run([y2, update_ops2])
هل يمكن أن تشرح هذا الجزء بمزيد من التفاصيل؟ شكرا جزيلا.
فقط ضعه في مجموعة مفاتيح منفصلة:
# While building your 1st model...
tf.contrib.layers.batch_norm(..., updates_collection="updates-model1")
# same for 2nd model with key "updates-model2"
#model 1
y1 = build_model_with_batch_norm(x, is_training)
update_ops1 = tf.group(tf.get_collection("updates-model1"))
sess.run([y1, update_ops1])
#model 2
y2 = build_model_with_batch_norm(x, is_training)
update_ops2 = tf.group(tf.get_collection("updates-model1"))
sess.run([y2, update_ops2])
ومع ذلك ، يجب أن تكون طبقات الوثائق قديمة. تخبر أن تفعل ما يلي:
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
if update_ops:
updates = tf.group(update_ops)
total_loss = control_flow_ops.with_dependencies([updates], total_loss)
لكن:
تعديل:
يجب تحديث الوثائق إلى s.th. مثله:
from tensorflow.python import control_flow_ops
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
if update_ops:
updates = tf.tuple(update_ops)
total_loss = control_flow_ops.with_dependencies(updates, total_loss)
تحرير 2:
بعد القيام ببعض عمليات التشغيل على شبكتي ، يجب أن أقول
تحرير: من الصعب القول ، إذا كانت نتائجي صحيحة ، لكن الشبكة بأكملها تصل بالفعل إلى 1.5x أسرع. بقدر ما أعرف ، يتم حساب إحصائيات BN على وحدة المعالجة المركزية ، وليس على وحدة معالجة الرسومات حتى الآن.
هل يمكن لأي شخص منكم رؤية أي فوائد للأداء أيضًا؟ يرجى مشاركة النتائج الخاصة بك :)
بالعودة إلى مشكلة الأداء ، هل طبقة المعيار الحالية للدفعة مناسبة على الإطلاق من استخدام وحدة معالجة الرسومات؟ هل حصل أي شخص على فوائد من وحدات معالجة الرسومات مع تطبيق هذه المجموعة المعيارية؟
آسف على البريد العشوائي ، لكن الوثائق لا تشرح حقًا كيفية استخدام BN هذا مع الالتفاف (ربما ينبغي توفيره في مكان ما؟). باختصار ، كيف يكتشف أنه يجب تطبيقه وتعلم نفس المعلمات لكل ميزة (بدلاً من كل تنشيط)؟
(هل هناك مقتطف رمز على الأقل للقيام بذلك؟)
يتم تطبيع غلاف الدُفعة النحيف على البعد الأخير لموتّر الإدخال. لذلك إذا كان موتر إدخال ثنائي الأبعاد قادمًا من طبقة متصلة بالكامل ، فإنه يتم تطبيعه على الدُفعة ، وبالتالي يقوم بإجراء تسوية لكل تنشيط. إذا كان موترًا رباعي الأبعاد قادمًا من التفاف ، فسيتم تطبيعه على الأبعاد الثلاثة الأولى (الدُفعة ، العرض ، العمق) ، وبالتالي إجراء تسوية لكل ميزة. sguada ربما يكون أكثر وصفيًا حول هذا الأمر.
nmhkahn بخصوص مقتطف الشفرة ، هل لي أن أسأل لماذا تم تعيين reuse
ليكون None
عندما is_training=True
؟ ألن يؤدي ذلك إلى تشغيل معلمة القياس gamma
ومعامل الإزاحة beta
في كل خطوة تدريب؟ اعتقدت في الورقة الأصلية أن beta
و gamma
"تعلمت مع معلمات النموذج الأصلي". للقيام بذلك ، ألا يجب أن تتم تهيئتهم مرة واحدة فقط ثم إعادة استخدامها في جميع خطوات التدريب؟
tf.cond(is_training,
lambda: batch_norm(inputT, is_training=True, updates_collections=None, scope=scope),
lambda: batch_norm(inputT, is_training=False, updates_collections=None, scope=scope, reuse = True))
إنني أقدر بشدة العمل الذي قام به فريق فريق العمل هنا لجعل الدُفعة متوفرة وفعالة. من خلال بحثي ، هذا الموضوع هو أفضل مورد لكيفية استخدامه. هناك العديد من المشكلات والأفكار المختلفة التي تطير هنا ، ومن الصعب معرفة نصيحة الإجماع لأبسط حالة قياسية لكيفية استخدام طبقة batch_norm. أعتقد أنه سيكون هناك الكثير من القيمة في توسيع الوثائق لتحديد الاستخدام الموصى به بدقة.
لقد أوصلتني أفضل محاولاتي لمعرفة ذلك إلى الكود التالي:
is_training_ph = tf.placeholder(tf.bool)
...
with tf.variable_scope('bn_test_layer') as vs:
layer_output = tf.cond(is_training_ph,
lambda: tf.contrib.layers.batch_norm(layer_input, is_training=True, center=True, scale=True, activation_fn=tf.nn.relu, updates_collections=None, scope=vs),
lambda: tf.contrib.layers.batch_norm(layer_input, is_training=False, center=True, scale=True, activation_fn=tf.nn.relu, updates_collections=None, scope=vs, reuse=True))
ثم قمت بتعيين is_training_ph على True للتدريب و False للاختبار. هذا لا يعمل بالنسبة لي. يتدرب النموذج بشكل جيد ، لكن أداء الاختبار سيء. في المقابل ، إذا حافظت على is_training_ph = True لوقت الاختبار ، فإنها تعمل بشكل رائع. وبالتالي ، أعتقد أنه لا يزال لدي مشكلة في النطاق بحيث لا يتم العثور على المتغيرات الحالية المناسبة.
@ davek44 أستخدم نفس إطار عمل الكود الذي تستخدمه ولاحظت نفس الشيء: عند تشغيل is_training=True
أثناء مرحلة التدريب وإيقاف is_training=False
للتحقق و / أو مرحلة الاختبار ، يتدرب النموذج جيدًا مثل الورقة الموصوفة (يتقارب النموذج بشكل أسرع وتمكنت من استخدام معدل تعلم أكبر) ، ومع ذلك فإن أداء الاختبار سيء. إذا قمت بتشغيل is_training=True
طوال الوقت ، فإن النموذج يتدرب بنفس الطريقة بدون إدخال طبقة القاعدة الدفعية. لم أكتشف الخطأ الذي فعلته ، فأنا أخطط لاستخدام TensorBoard لمراقبة المعلمات. هل يمكنك التحديث إذا قمت بتشخيص سبب هذا السلوك؟
يمكن أن يأخذ tf.contrib.layers.batch_norm الموتر على أنه تدريب ، لذلك لا داعي لعمل أي شيء خاص.
is_training_ph = tf.placeholder(tf.bool)
outputs = tf.contrib.layers.batch_norm(layer_input, is_training=is_training_ph, center=True, scale=True, activation_fn=tf.nn.relu, updates_collections=None, scope='batch_norm'),
أرى نفس أداء الاختبار الضعيف مع هذا الرمز.
بدون مزيد من التفاصيل من المستحيل معرفتها ، تخميناتي هي أنك تتدرب فقط لعدد قليل من التكرارات ، لذلك لم يتقارب متوسط الحركة والمتوسط المتحرك بعد.
يمكنك تغيير حجم الدفعة أثناء الاختبار لترى كيف يتدهور الأداء عندما تجعل الدفعة أصغر.
أرى نفس أداء الاختبار الضعيف مع هذا الرمز.
واجهت نفس المشكلة تمامًا إما مع tf.slim batchnorm أو مع tf.cond والإدخال is_training كعنصر نائب.
في الحالة الأولى ، عند التحقق من النموذج المدرب ، اكتشفت أن متوسط الحركة والتباين المتحرك يتكونان من جميع الأصفار.
في الحالة الأخيرة ، يبدو المتوسط المتحرك والتباين أكثر منطقية (بقيم مختلفة) ، ولكن إذا استخدمت is_training = False في وقت الاختبار ، فإن الأداء سيء حقًا أيضًا. باستخدام is_training = True ، يعمل بشكل أفضل ولكني أعتقد أنه يستخدم فقط المتوسط المتحرك والتباين داخل مجموعة الاختبار.
nmduc @ davek44 لقد كتبت بعض التعليمات البرمجية لتتبع المتوسط المتحرك والتباين المتحرك المحسوب بـ tf.contrib.layers.batch_norm
أثناء التدريب والاختبار. اكتشفت أن قيمة decay
مهمة كثيرًا (يستخدمون الانحطاط الأسي لحساب المتوسط المتحرك والتباين المتحرك) ، مع إعداد decay
أقرب إلى 1.0 (أي decay=.999
) ، نقل القطرات المتوسطة إلى قيمة أقرب إلى 0. لقد أجريت تشغيلين اختباريين بنفس الكود بالضبط ولكن إعدادات مختلفة decay
في tf.contrib.layers.batch_norm
، وبدت دقة التحقق / الاختبار أكثر منطقية.
نتائج التشغيل التجريبي بـ decay=0.9
نتائج التشغيل التجريبي مع decay=0.999
( decay=0.999
هو الإعداد الافتراضي في tf.contrib.layers.batch_norm
)
(يبدو أيضًا أن قيمة الانحلال الأكبر تتطلب تدريب النموذج لفترة أطول لرؤية تغيير دقة التحقق)
نعم هذا أصلحها. شكرا لتقاسم تحليلك zhongyuk!
أنا أشجع المطورين على التفكير في جعل الانحلال = 0.9 هو الخيار الافتراضي. حتى 0.99 لا يعمل بشكل جيد بالنسبة لي. هذه هي القيمة الافتراضية في تنفيذ Torch أيضًا ؛ انظر معامل الزخم في https://github.com/torch/nn/blob/master/BatchNormalization.lua
zhongyuk شكرا جزيلا للمشاركة. بالنسبة لي كان يعمل الآن.
يبدو هذا مهمًا. sguada ، يجب أن نفكر في المسار الصحيح للعمل هنا قبل الإصدار 1.0. على المدى القصير ، هل يمكن لأحد الأطراف المهتمة أن يرسل لي مستند علاقات عامة يوثق حقيقة أن decay
قد يتم تخفيضه بشكل كبير عند مواجهة أداء تقييم ضعيف؟ أنا متأكد من أنني لم أضطر أبدًا إلى تعديل هذه المعلمة ، ولكن قد يكون ذلك أحد الآثار الجانبية للإعداد الموزع.
يمكننا تغيير الإعداد الافتراضي إلى 0.9 أو توثيق تأثيره بشكل أفضل في مجموعات بيانات أصغر أو تحديثات قليلة.
vincentvanhoucke في
على سبيل المثال ، عند استخدام decay = 0.999 انحياز 0.36 بعد 1000 تحديث ، ولكن هذا التحيز ينخفض إلى 0.000045 بعد 10000 تحديث وإلى 0.0 بعد 50000 تحديث.
أردت فقط أن أشير إلى أن لدي أيضًا مشكلة الأداء الضعيف للاختبار ، وتحديدًا باستخدام أحجام دفعات صغيرة (أي شيء أصغر من 10 بدلاً من 200 الذي استخدمته للتدريب يقلل من دقة الاختبار). لقد استخدمت tf.placeholder للتبديل بين وضع الاختبار / التدريب.
من الرائع أن تعمل طبقة تسوية الدُفعات هذه من أجل تقارب تدريب أفضل ، ولكن إذا لم تتمكن من تطبيق النموذج في الإنتاج ، فلا فائدة من استخدامه. هل يمكن لأي شخص تأكيد أداء الاختبار الجيد باستخدام عينات بيانات صغيرة أو مفردة باستخدام طبقة المعيار الدفعية هذه؟
أستطيع أن أؤكد أن أداء الاختبار جيد عند استخدام is_training = False مع دفعات صغيرة وحتى مع batch_size = 1 ، نظرًا لأنه لا يستخدم الإحصاء من الدُفعة ، ولكن الإحصاء الذي تم تعلمه أثناء التدريب. كل ما تحتاجه هو التأكد من أن الإحصائيات قد تقاربت مع الانحلال الافتراضي = 0.999 الذي يشير إلى 50 ألف تحديث على الأقل.
لمتابعة تأكيد مطور TF ، أقوم بتتبع تقارب الإحصائيات مع إعدادين مختلفين decay
(والتدريب batch_size = 1). مع decay=0.99
، تتقارب الإحصائيات (انحياز <0.001) بعد 550 ~ 600 خطوة من التعلم / التحديث. مع decay=0.9
، تتقارب الإحصائيات (الانحياز <0.001) في غضون 100 خطوة من التعلم / التحديث.
شكرًا sguada ، هل هذا يعني أيضًا أن الإخراج مستقل بالفعل عن حجم الدفعة؟ لأنني ألاحظ تغييرات طفيفة جدًا ذات تأثير كبير على دقتي (ربما يتأثر تعريفي للأداء بسهولة أكبر بهذا التغيير الطفيف). لكي أكون دقيقًا ، تزداد جميع القيم الموجودة في موتر الإخراج ذي الأبعاد 128 بحيث يتناسب إجمالي طول المتجه بشكل خطي تقريبًا مع حجم الدُفعة. بالنسبة للقيمة ، هذا ليس فرقًا كبيرًا ، لكن له تأثير كبير عند حساب مسافات المتجهات في المساحات الكامنة.
zhongyuk شكرًا ، لقد قمت بتشغيل حوالي 5 decay=0.9
، لذلك كان يجب أن تكون متقاربة واختبار الأداء باستخدام أحجام دفعات كبيرة أمر جيد. ولكن حتى لو لم يحدث ذلك ، فهل سيؤدي ذلك إلى اختلاف بين التدريب على الاختبار؟ سأكون رؤية سوء الأداء خلال التدريب واختبار إذا لم المتقاربة، أليس كذلك؟
سأحقق في المزيد وأرى ما إذا كان بإمكاني إعادة إظهار المشكلة في مهمة أخرى. شكرا للتغذية السريعة حتى الآن!
dominikandreas إذا كان أداء الاختبار السيئ ناتجًا عن عدم تقارب الإحصائيات ، فسترى أداء تدريبيًا جيدًا بشكل معقول ولكن أداء اختبار سيئ. لأنه أثناء التدريب ، يتم تطبيع الدُفعات باستخدام إحصائيات مجموعة التدريب فقط. ومع ذلك ، أثناء وقت الاختبار ، فإنه يستخدم إحصائيات المتوسط المتحرك لجميع مجموعات التدريب لتطبيع موتر الإدخال.
لقد وجدت وخطأ في الكود ، تطبيع الدفعات يعمل بشكل جيد الآن :-) شكرًا لدعمكم
مرحبًا zhongyuk ، كيف
شكر!
rogertrullo بشكل عام ، أقوم بإعداد TensorBoard لتتبع المتوسط المتحرك والتباين. بخلاف ذلك ، حاولت أيضًا جلب الإحصائيات من خلال tf.get_variable("moving_mean")
داخل النطاق أثناء التدريب والمرجع لمراقبة التحيز.
مرحبا،
لدي نفس المشكلة كما هو موصوف أن لدي نتائج تدريب جيدة ولكن التحقق من الصحة / الاختبار سيء بعد استخدام الدفعة.
أستخدم الوظيفة مثل هذا:
conv_normed1 = tf.contrib.layers.batch_norm (conv1 + block1_layer3_1_biases، updates_collections = None ، scale = True ، decay = batch_norm_decay، center = True، is_training = is_training)
قيمة الاضمحلال 0.9
هل أحتاج إلى تعيين علامة إعادة الاستخدام؟
سأكون سعيدا لأي مساعدة.
لقد كنت أستخدم batch_norm كما هو موضح في هذا الموضوع (مع tf.bool للتدريب ؛ و ops.GraphKeys.UPDATE_OPS) وكل شيء يعمل.
عند الحفظ والاستعادة باستخدام:
التوقف = tf.train.Saver ()
إنها تعمل،
ولكن عند الحفظ باستخدام:
saver = tf.train.Saver (tf.trainable_variables () + [global_step])
حتى أتمكن من توفير مساحة التخزين (بعدم حفظ التدرجات وما إلى ذلك)
عند الاستعادة يوجد خطأ:
"قيمة غير مهيأة unpool4 / convc / bn / move_mean"
من الواضح أن هذا يرجع إلى أن move_mean (وأفترض Moving_variance) لم يتم حفظها لأي من الطبقات. نظرًا لأن لدي الكثير منها (متداخلة في طبقات عديدة) - ما هي الطريقة الأكثر فعالية لإضافتها إلى قائمة القيم المراد حفظها؟ أيضًا ، نظرًا لأن هذه متغيرات قابلة للتدريب ، فلماذا لا يتم إضافتها إلى مجموعة المتغيرات القابلة للتدريب؟
mshunshin المتوسط المتحرك
لحفظها / استعادتها ، يمكنك استخدام tf.global_variables ()
بالنسبة لي ، بدأت الأمور تعمل عندما استخدمت هذا الغلاف:
def batch_norm_wrapper(x, phase, decay, scope, reuse):
with tf.variable_scope(scope, reuse=reuse):
normed = tf.contrib.layers.batch_norm(x, center=True, scale=True, decay=decay, is_training=phase, scope='bn',updates_collections=None, reuse=reuse)
return normed
استخدام النطاقات وإعادة الاستخدام بالكامل غير واضح في هذا الموضوع من وجهة نظري.
شكرا جزيلا. مع tf.global_variables () تكون ملفات الحفظ أكبر بكثير حيث أعتقد أنها تتضمن التدرجات ؛ في النهاية استخدمت:
saver = tf.train.Saver ([x for x في tf.global_variables () إذا لم يكن "Adam" في x.name])
ولأن مدير الجلسة init لم يهيئها بشكل صحيح:
sess.run (tf.variables_initializer ([x for x in tf.global_variables () if 'Adam' in x.name]))
(باستخدام tf.train.AdamOptimizer)
يمكنك أيضًا استخدام tf.model_variables () الذي يحتوي على متغيرات النموذج ، مثل move_mean
sguada آسف على المتاعب ، ولكن هل من الممكن تقديم مثال على كيفية استخدام slim.batch_norm عند دمجه مع slim.conv2d / slim.fully_connect في readme.md؟
أنا أستخدم slim.batch_norm ، لكني أحصل على أداء تدريبي جيد وأداء اختبار / تحقق ضعيف. أعتقد أنه يجب أن يكون بسبب الاستخدام غير السليم لـ reuse
أو scope
أو بعض المعلمات الأخرى. على الرغم من وجود العديد من المشكلات المتعلقة بتسوية الدفعات ، إلا أنه من الصعب العثور على مقتطف رمز كامل حول كيفية استخدامه ، خاصةً. لكيفية تمرير المعلمات المختلفة في مراحل مختلفة.
لنفترض ، في كود mnist_bn الخاص بي ، أنني قمت بالتحكم في التبعيات باستخدام tf.GraphKeys.UPDATE_OPS
وقمت بإعداد is_training
كعنصر نائب. لكن أداء التحقق لا يزال ضعيفًا إذا أطعمت {is_training: False}.
سأكون ممتنًا للغاية إذا كان هناك مثال رسمي وكامل (مما يعني التدريب والتحقق من الصحة والاختبار) مثال على تطبيع الدفعات.
شكرا لكم مقدما!
مرحبا،
تحتاج إلى تعيين نطاق مختلف لكل مرة تستخدم فيها معيار الدُفعات ومنحها إدخال إعادة الاستخدام وفقًا لمرحلة التدريب / الاختبار (صحيح عند اختبار FALSE عند التدريب) التي تناسبني.
ishaybee شكرا لمساعدتك. لقد وجدت مشكلتي = = إنها بسبب البداية الباردة لـ move_mean / move_variance.
نظرًا لأنني لم أقم بتدريب خطوات كافية ، فإن متوسط / تباين الحركة المقدر ليس مستقرًا. تبين أن النتيجة هي: أداء النموذج جيدًا في تدريب الدُفعات الصغيرة (تعلم أن الخسارة في البداية تنخفض بسرعة) ، لكن أداء التحقق غير منتظم (لأن متوسط / تباين المحتوى المقدر غير مستقر بدرجة كافية).
عندما دربت النموذج لفترة أطول ، تصبح دقة التحقق أجمل أيضًا.
شيء آخر مهم ، تأكد من استخدام slim.learning.create_train_op
لإنشاء عملية تدريب . لا تستخدم tf الأصلي tf.train.GradientDescentOptimizer(0.1).minimize(loss)
.
إذن الإجابة هي ، أنا أستخدم تطبيع الدُفعات بشكل صحيح ، لكنني لم أفهم تمامًا دينامياتها أثناء التدريب.
================
ما هو أكثر:
soloice ، لاحظ ، كيف يتم تمرير المعلمة التالية داخل الطبقة لاستدعاء batch_norm حول التعليق :
batch_norm_params = {'is_training': is_training، 'decay': 0.9، 'updates_collections': لا شيء}
بدون تعيين updates_collections
إلى None (لذلك ، يتم إجراء التحديثات في مكانها داخل BatchNorm) ، لن أتوقع أن تقوم الطبقة المحيطة (على سبيل المثال ، conv2d) بتنفيذ tf.GraphKeys.UPDATE_OPS اللازمة لطبقة BatchNorm لتحديث متوسط التشغيل و لذلك ستكون قادرًا على تشغيل بيانات الاختبار لاحقًا.
أو يمكنك محاولة تشغيل UPDATE_OPS بنفسك بشكل صريح كواحد هنا
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
if update_ops:
updates = tf.group(*update_ops)
cross_entropy = control_flow_ops.with_dependencies([updates], cross_entropy)
تحديث - لقد وجدت أنني نقلت عن شفرتك بالضبط وأنت تستخدم UPDATE_OPS.
بالنسبة إلى "البداية الباردة" ، كما ترى أعلاه في المناقشة ، فإن تقليل معدل تشغيل BatchNorm (معلمة الإدخال) من 0.999 الافتراضي إلى 0.95 يمكن أن يسرع بدء التشغيل
pavelbulanov إنه decay
لأرى كيف يساعد ذلك.
================
التحديث: استخدام انحلال صغير (على سبيل المثال ، 0.9 أو 0.95) يساعد كثيرًا. تنخفض خسارة التحقق من الصحة بسرعة كبيرة عند تعيين decay
على 0.9. ومع ذلك ، فإن عيب الاضمحلال الصغير هو أن نطاقه الفعال صغير: تسيطر على النتيجة بضع عينات حديثة ، وبالتالي فهي ليست تقديرًا جيدًا لمتوسط المجتمع / التباين. يحتاج المرء إلى التوازن بين البداية السريعة (الاضمحلال الصغير) ونطاق الفعالية الأطول (الاضمحلال الكبير).
مرحبا،
لقد حاولت تنفيذ طبقة تسوية دفعية بمساعدة الاقتراحات الواردة في هذه المشكلة ، ولكن لا يزال لدي خطأ بنسبة 70٪ في التحقق والاختبار ... لدي انخفاض أقل في المكالمات غير التدريبية ...
هذا هو الكود الخاص بي:
def BatchNorm(inputT, is_training=False, scope=None):
return tf.cond(
is_training,
lambda: tf.contrib.layers.batch_norm(inputT, is_training=True, reuse=None, decay=0.999, epsilon=1e-5, center=True, scale=True, updates_collections=None, scope=scope),
lambda: tf.contrib.layers.batch_norm(inputT, is_training=False, reuse=True, decay=0.900, epsilon=1e-5, center=True, scale=True, updates_collections=None, scope=scope)
)
شكرا لكم مقدما.
Alexivia يبدو أنك تستخدم طبقتين مختلفتين من طبقات تسوية الدفعات؟ يجب عليك استخدام طبقة BN واحدة فقط (بالطبع ، بمعامل مختلف is_training
).
شكرا لك على نصيحتكsoloice.
لقد حاولت الآن بمعلمات مختلفة فقط: is_training
و reuse
:
lambda: tf.contrib.layers.batch_norm(inputT, is_training=True, reuse=None, decay=0.9, epsilon=1e-5, center=True, scale=True, updates_collections=None, scope=scope),
lambda: tf.contrib.layers.batch_norm(inputT, is_training=False, reuse=True, decay=0.9, epsilon=1e-5, center=True, scale=True, updates_collections=None, scope=scope)
ما زلت لا تحصل على نتائج اختبار واختبار جيدة ...> 70٪ ...
مرحبا،
يرجى الاطلاع على غلافي أعلاه.
يجب عليك استخدام "مع tf.variable_scope (النطاق ، إعادة الاستخدام = إعادة الاستخدام):" أعتقد.
مرحبا ishaybee ،
لقد اتبعت نصيحتك ، الآن الكود الخاص بي هو:
def BatchNorm(inputT, is_training=False, reuse=True, scope=None):
with tf.variable_scope(scope, reuse=reuse):
return tf.contrib.layers.batch_norm(inputT, is_training=is_training, reuse=reuse, scope=scope, updates_collections=None, decay=0.9, center=True, scale=True)
وأطعم is_training
و reuse
خلال feed_dict ، لكنني الآن أتلقى الخطأ ValueError("The reuse parameter must be True or False or None.")
حاول تغذية إعادة الاستخدام كمتغير بيثون (إدخال من النموذج) وكعنصر نائب.
لقد جربت ذلك ، والآن توقفت عن الشكوى من القيمة ... لكنني أعتقد أن قيمة العنصر النائب لا يتم استخدامها ، لأنني لا أرى أي تغيير إذا فرضت القيم على الوظيفة batch_norm
، وفي TensorBoard ليس كذلك متصل بالرسم البياني ... (انظر الصورة المرفقة)
الكود الخاص بي على هذا النحو الآن:
غلاف التطبيع الدفعي
def BatchNorm(inputT, is_training=False, reuse=None, scope=None):
with tf.variable_scope(scope):
return tf.contrib.layers.batch_norm(inputT, is_training=is_training, reuse=reuse, scope=scope, updates_collections=None, decay=0.9, center=True, scale=True)
تعريف النموذج
def model(data, train=False, is_training=False, reuse=None):
# 1st conv layer
with tf.name_scope('conv1') as scope:
conv = tf.nn.conv2d(
<...>
norm = BatchNorm(pool, is_training=is_training, reuse=reuse, scope=scope)
تدريب
feed_dict = {train_data_node: batch_data,
train_labels_node: batch_labels,
is_training: True,
reuse: None}
# Run the optimizer to update weights.
sess.run(optimizer, feed_dict=feed_dict)
التحقق من الصحة
batch_predictions = sess.run(eval_prediction, feed_dict={eval_data: data[-EVAL_BATCH_SIZE:, ...], is_training: False, reuse: True})
على الرغم من أن إعادة استخدام is_traning يجب أن يكون منطقيًا ، ولا يمكن أن يكون موترًا أو عنصرًا نائبًا.
لست متأكدًا مما تحاول القيام به ، ففي معظم الحالات ، يؤدي استخدام القيم الثابتة إلى حل المشكلة. على سبيل المثال ، يعمل هذا النمط جيدًا:
def model(data, is_training=False, reuse=None, scope='my_model'):
# Define a variable scope to contain all the variables of your model
with tf.variable_scope(scope, 'model', data, reuse=reuse):
# 1 layer
net = tf.contrib.layers.conv2d(data, ....)
....
net = tf.contrib.layers.batch_norm(net, is_training)
return net
train_outputs = model(train_data, is_training=True)
eval_outputs = model(eval_data, is_training=False, reuse=True)
eval_predictions = sess.run(eval_outputs, feed_dict={eval_data: data[-EVAL_BATCH_SIZE:, ...]})
ما لم تكن بحاجة إلى تغيير سلوك النموذج ديناميكيًا ، فلن تحتاج إلى استخدام عنصر نائب لـ is_training. الحيلة هي بناء النموذج مرتين ، مع مشاركة المتغيرات في المرة الثانية.
شكرا لك sguada ! بعد تطبيق اقتراحاتك ، نجحت أخيرًا في العمل!
سيكون من المفيد أن تعكس وثائق API 1.0 أنك بحاجة إلى إضافة عمليات التحديث يدويًا إلى الرسم البياني. لكوني مستخدمًا جديدًا لـ tf ، وجدت أن خطأ الاختبار الخاص بي كان مجنونًا ، ثم اضطررت إلى قضاء وقت لا بأس به في تصحيح الرسم البياني الخاص بي حتى أدركت أن تسوية الدُفعات كانت هي المشكلة. ثم اضطررت إلى قضاء المزيد من الوقت في اكتشاف أنه افتراضيًا لا يتم تحديث المتغيرات التي تتبع اللحظات إلا إذا كنت تستخدم وظيفة مساهمة للتحسين. نظرًا لعدم وجود خيار في الإصدار 1.0 لتعيين update_collections إلى None ، لا يوجد مؤشر من الوثائق على أن هذا قد يكون مشكلة. بالإضافة إلى ذلك ، يبدو أنه قد يكون من المنطقي أن يكون لديك معلمة لإضافة تبعيات تدفق التحكم إلى المرجع الذي يتم تشغيله في حالة التدريب.
@ danrsc بالضبط. استخدام طبقة BN مربك للغاية. اقترحت إضافة مستندات أو برنامج تعليمي رسمي كامل حول تسوية الدُفعات ، لكن للأسف لم أتلق أي رد = =
أتفق تماما. أعتقد أن استخدام BN صعب للغاية وأن التوثيق حاليًا غير كافٍ. يجب أن يتم إصلاح هذا لطبقة شائعة الاستخدام.
إعادة الفتح لإبراز قضايا التوثيق.
sguada يعين لك
لقد ارتبكت للتو بسبب هذه المشكلة الأسبوع الماضي وأهدرت 3 أيام من التدريب ... آمل أن يتم إصلاح المستندات قريبًا ، ويمكن إضافة مثال تطبيع دفعة رسمي في مستندات API.
sguada لقد لاحظت أنك قلت "يمكن لـ tf.contrib.layers.batch_norm أن يأخذ التنسور على أنه تدريب ، لذلك لا داعي لفعل أي شيء خاص".
Howerver ، التعليق في الكود هو
إذا لم يكن is_training
له قيمة ثابتة ، لأنه Tensor
،
# a Variable
أو Placeholder
ثم is_training_value لن تكون بلا و
# needs_moments
سيكون صحيحًا.
هل يعني ذلك أن nees_moments سيكون صحيحًا حتى في مرحلة الاختبار إذا قمت بتعيين is_training كعنصر نائب؟
على حد علمي ، ليست هناك حاجة للحظات أثناء الاختبار.
لذا ، إذا كان is_training
هو Variable
أو Placeholder
، فهذا يعني أنه يمكن أن يتغير ، لذا فإن الرسم البياني لحساب اللحظات ضروري ، لذا فإن الطبقة تبنيها.
ثم في وقت التشغيل اعتمادًا على القيمة True
أو False
ستستخدم الدفعة moments
أو moving_mean
و moving_variance
.
لذلك أثناء الاختبار ، ستضبط القيمة على False
moments
ولن يتم استخدام
تضمين التغريدة
def batch_norm_layer(self, x,train_phase, scope_bn):
bn_train = batch_norm(x, decay=0.9, center=False, scale=True,
updates_collections=None,
is_training=True,
reuse=None,
variables_collections= [UPDATE_OPS_COLLECTION],
trainable=True,
scope=scope_bn)
bn_inference = batch_norm(x, decay=0.9, center=False, scale=True,
updates_collections=None,
is_training=False,
reuse=True,
variables_collections= [UPDATE_OPS_COLLECTION],
trainable=True,
scope=scope_bn)
z = tf.cond(train_phase, lambda: bn_train, lambda: bn_inference)
return z
أقوم بإنشاء دفعة عادية مثل هذا ، ومع ذلك ، يتم تحديث المتوسط المتحرك والمتغير المتحرك أثناء الاختبار ، ولا يمكنني العثور على السبب.
حاولت إنشاء نموذجين مثل sguada ، لكن نموذجي حيث is_training = False مجرد تعطل.
W tensorflow/core/framework/op_kernel.cc:993] Not found: Key fully_connected_5/weights not found in checkpoint
W tensorflow/core/framework/op_kernel.cc:993] Not found: Key fully_connected_6/weights not found in checkpoint
W tensorflow/core/framework/op_kernel.cc:993] Not found: Key fully_connected_7/biases not found in checkpoint
W tensorflow/core/framework/op_kernel.cc:993] Not found: Key fully_connected_6/biases not found in checkpoint
W tensorflow/core/framework/op_kernel.cc:993] Not found: Key fully_connected_7/weights not found in checkpoint
W tensorflow/core/framework/op_kernel.cc:993] Not found: Key history_embeddings_1 not found in checkpoint
W tensorflow/core/framework/op_kernel.cc:993] Not found: Key global_step_1 not found in checkpoint
أشعر أنه ربما يجب أن يكون هناك مثال ملموس على كيفية القيام بمعيار دفعي بشبكة متصلة بالكامل ، وكذلك مع شبكات CNN. تمتلئ بأنني دربت عارضات الأزياء لأيام أتوقع أن تعمل الأشياء قبل أن أرى أن كل شخص يحاول استخدام هذه الميزة يصبح مجنونًا.
ومن المثير للاهتمام أن الأمر يستغرق زليون سنة لاستعادة النموذج بعد التدريب باستخدام الدُفعة أيضًا. على الأرجح سينتظر حتى TF 2.0 لتجربة شيء كهذا مرة أخرى.
MisayaZ ، لست بحاجة إلى إنشاء طبقتين من شكل batch_norm ، يمكنك فقط اجتياز train_phase (على افتراض أنه ملف tf.bool) إلى batch_norm. كما أنك تقوم بتمرير UPDATE_OPS_COLLECTION variables_collections ، والتي تغير المجموعات التي هي المتغيرات المضافة إليها.
يجب أن يعمل ما يلي:
z = batch_norm(x, decay=0.9, center=False, scale=True, updates_collections=None,
is_training=train_phase, scope=scope_bn)
OktayGardener غير متأكد من النموذج الذي تحاول
تعمل batch_norm أيضًا مع الطبقات المتصلة بالكامل.
slim = tf.contrib.slim
def model(data, is_training=False, reuse=None, scope='my_model'):
# Define a variable scope to contain all the variables of your model
with tf.variable_scope(scope, 'model', data, reuse=reuse):
# Configure arguments of fully_connected layers
with slim.arg_scope([slim.fully_connected],
activation_fn=tf.nn.relu,
normalizer_fn=slim.batch_nom):
# Configure arguments of batch_norm layers
with slim.arg_scope([slim.batch_norm],
decay=0.9, # Adjust decay to the number of iterations
update_collections=None, # Make sure updates happen automatically
is_training=is_training, # Switch behavior from training to non-training):
net = slim.fully_connected(data, 100, scope='fc1')
net = slim.fully_connected(net, 200, scope='fc2')
....
# Don't use activation_fn nor batch_norm in the last layer
net = slim.fully_connected(net, 10, activation_fn=None, normalizer_fn=None, scope='fc10')
return net
sguada شكرًا ، أنا أقوم ببناء شبكة مع bathnorm والتي تم تنفيذها كما ذكرت أعلاه
z = batch_norm(x, decay=0.9, center=False, scale=True, updates_collections=None,
is_training=train_phase, scope=scope_bn)
السرعة بطيئة ، أستخدم معيار tensorflow للحصول على وقت الحساب على النحو التالي:
I tensorflow / core / util / stat_summarizer.cc: 392] ============================== الأعلى حسب وقت الحساب === ============================
I tensorflow / core / util / stat_summarizer.cc: 392] [نوع العقدة] [البدء] [الأول] [avg ms] [٪] [cdf٪] [mem KB] [الاسم]
I tensorflow / core / util / stat_summarizer.cc: 392] Conv2D 106.164 51.354 51.004 23.145٪ 23.145٪ 692.224 conv8 / Conv2D
I tensorflow / core / util / stat_summarizer.cc: 392] Conv2D 85.187 19.115 19.283 8.750٪ 31.896٪ 692.224 conv7 / Conv2D
I tensorflow / core / util / stat_summarizer.cc: 392] SquaredDifference 11.967 15.105 14.331 6.503٪ 38.399٪ 11075.584 conv1 / batch_norm / moment / enough_statistics / SquaredDifference
I tensorflow / core / util / stat_summarizer.cc: 392] Mul 11.970 14.162 13.495 6.124٪ 44.523٪ 11075.584 conv1 / batch_norm / batchnorm / mul_1
I tensorflow / core / util / stat_summarizer.cc: 392] Conv2D 3.948 8.170 7.986 3.624٪ 48.146٪ 11075.584 conv1 / Conv2D
I tensorflow / core / util / stat_summarizer.cc: 392] Sub 11.960 10.176 7.943 3.604٪ 51.751٪ 11075.584 conv1 / batch_norm / moment / enough_statistics / Sub
Tensorflow / core /
I tensorflow / core / util / stat_summarizer.cc: 392] Mul 45.574 7.755 6.902 3.132٪ 58.140٪ 5537.792 conv2 / batch_norm / batchnorm / mul_1
I tensorflow / core / util / stat_summarizer.cc: 392] Conv2D 40.692 5.408 4.845 2.199٪ 60.338٪ 5537.792 conv2 / Conv2D
I tensorflow / core / util / stat_summarizer.cc: 392] Sub 45.563 6.067 4.784 2.171٪ 62.509٪ 5537.792 con
لا أفهم سبب تنفيذ بعض العمليات في الوقت الحالي أثناء الاختبار وهي تكلف الكثير من الوقت ، مثل conv1 / batch_norm / moment / enough_statistics / SquaredDifference.
هذه اللحظة ليست ضرورية في الاختبار ، لماذا يتم تنفيذ بعض العمليات الجارية؟
مرحبا،
باستخدام الطبقة أعلاه batch_norm
في contrib.layers
، أحصل على nan
كمخرج للتحقق من صحة الرسم البياني بينما يعمل الرسم البياني للقطار بسلاسة. هل هناك أي شيء قد أفتقده؟
أنا استخدم:
def batchnormlayer(inputs, numout, train_model):
with tf.variable_scope("batch_norm") as scope_bn:
epsilon = 1e-3
return tf.contrib.layers.batch_norm(inputs, decay=0.9, updates_collections=None,
scale=True, scope=scope_bn,
is_training=train_model, epsilon=epsilon,
fused=True, reuse=scope_bn.reuse)
شكر
كمتابعة ، سأعيد استخدام 16 طبقة من الدُفعات.
ومع ذلك ، وجدت أن إعادة استخدام 4 طبقات تعمل.
لقد لاحظت للتو أنه إذا قتلت عملية tensorflow وأعدت تشغيلها ، فإن خطئي يزداد سوءًا لبضع فترات (أي أسوأ مما يجب أن يكون عند نقطة التفتيش الأخيرة). ألاحظ أيضًا أنه إذا قمت بإزالة batch_norm ، فستختفي هذه المشكلة. بعد النظر إلى الكود لفترة من الوقت ، أعتقد أن هذا قد يكون بسبب عدم استعادة قيم المتغيرات من متغيرات الظل كما هو الحال إذا تم استخدام فئة ExponentialMovingAverages لإدارة المتوسطات المتحركة. هذا يعني أيضًا أنني إذا استخدمت عملية منفصلة للتقييم ، فسأحصل على القيمة الأخيرة للمتغير وليس المتوسط المتحرك. هل أنا أفسر هذا بشكل صحيح وهل هذا هو السلوك المقصود؟ يبدو أنك تريد استعادة قيم متغير الظل ...
لقد اكتشفت المشكلة ، أصبح التباين المتحرك في حالتي سالبًا بعد بعض التكرارات.
ناتج الموتر: Model/clip_logits/batch_norm/moving_variance:0
موجود في tf.model_variables()
هو
Moving variance (shape = (101,)) =
[ 214.70379639 95.36338043 0.57885742 189.49542236 102.72473145
137.14886475 286.57333374 111.06427002 154.98750305 167.75219727
207.83955383 211.14007568 158.23495483 171.61665344 116.81361389
115.77380371 43.59399796 137.75064087 181.75245667 161.37339783
215.21934509 92.88521576 191.23846436 336.3946228 259.85919189
299.47039795 186.23222351 165.19311523 262.82446289 170.11567688
233.56843567 209.35050964 115.96807861 154.34109497 295.5770874
123.6055603 295.76187134 296.88583374 240.88217163 247.32983398
87.15661621 217.69897461 133.00698853 -4.80375671 344.77462769
291.50601196 117.77174377 265.83712769 207.90093994 194.186203
220.21418762 178.03738403 115.27571869 196.62184143 228.8089447
191.53205872 331.36807251 151.55435181 197.2951355 179.67504883
181.09727478 90.09922791 173.30133057 102.6836853 160.9434967
236.59512329 168.05305481 403.36340332 41.14326096 185.93409729
130.57434082 266.31509399 101.44387817 163.88059998 290.25015259
244.52597046 229.86647034 158.14352417 202.68774414 187.78227234
248.78218079 126.0978241 171.41891479 274.40740967 119.84254456
202.53045654 200.20608521 214.04730225 111.53284454 222.03184509
244.81187439 172.23052979 187.09806824 194.62802124 255.26345825
293.63598633 307.91036987 210.86982727 308.88919067 144.94792175
229.69013977]
كما ترى ، هناك تباين سلبي لأحد الأبعاد. كيف يكون هذا ممكن حتى ؟
ملاحظة: تُستخدم الطبقة المعيارية الدفعية بعد آخر طبقة متصلة بالكامل من الشبكة وقبل softmax.
@ raghavgoyal14 هل تستخدمه مع
abred : نعم ، لقد استخدمت fused=True
، نفس المشكلة.
sguada مرحبًا ، sguada ، لدي مشكلة.
تعريف Contrib.layers.batch_norm في Tensorflow:
def batch_norm (المدخلات ،
الاضمحلال = 0.999 ،
المركز = صحيح ،
مقياس = خطأ ،
إبسيلون = 0.001 ،
activation_fn = لا شيء ،
param_initializers = لا شيء ،
البارامترات = لا شيء ،
updates_collections = ops.GraphKeys.UPDATE_OPS ،
is_training = صحيح ،
إعادة الاستخدام = لا شيء ،
variables_collections = لا شيء ،
outputs_collections = لا شيء ،
قابل للتدريب = صحيح ،
دفعة_وزن = لا شيء ،
تنصهر = خطأ ،
data_format = DATA_FORMAT_NHWC ،
zero_debias_moving_mean = خطأ ،
النطاق = لا شيء ،
رينورم = خطأ ،
renorm_clipping = لا شيء ،
renorm_decay = 0.99):
المقياس: إذا كان صحيحًا ، اضرب في جاما. إذا كان خطأ ، فإن جاما هي
غير مستعمل. عندما تكون الطبقة التالية خطية (مثل nn.relu) ، يمكن أن يكون هذا
معطل لأن القياس يمكن أن يتم بواسطة الطبقة التالية.
إذا استخدمت tf.contrib.layers.batch_norm (المدخلات ، المقياس = خطأ) ، فإن "المقياس = خطأ" يعني ما إذا كانت جاما صفراً في "y = gamma * x + beta" أثناء التدريب. شكرا جزيلا.
عندما يكون المقياس = خطأ ، يكون جاما ثابتًا 1.
ppwwyyxx شكرا جزيلا لمساعدتك. أستخدم tf.contrib.layers.batch_norm (إدخال ، مقياس = خطأ) في Tensorflow ، والآن أقوم بتحويل دفعة Tensorflow إلى Caffe. كيفية تعيين معلمة BatchNormLayer و ScaleLayer في Caffe؟
شكرا جزيلا.
MisayaZ كنت أواجه نفس السلوك باستخدام Batchnorm مع عنصر نائب لـ "is_training". أرى في التتبع أنه يتم حساب اللحظات حتى في وقت الاختبار ، لذلك قررت الدخول في الكود المصدري ووجدت هذا:
# If `is_training` doesn't have a constant value, because it is a `Tensor`,
# a `Variable` or `Placeholder` then is_training_value will be None and
# `needs_moments` will be true.
is_training_value = utils.constant_value(is_training)
need_moments = is_training_value is None or is_training_value
if need_moments:
# here it defines the moments
يبدو أنه عندما تكون "is_training" متغيرًا أو عنصرًا نائبًا ، يتم تحديد اللحظات وأيضًا يتم حسابها في وقت التشغيل ، حتى عند تعيين العنصر النائب على "False". كنت أفضل تركه كعنصر نائب لأنه بهذه الطريقة يمكنني إجراء اختبار دوري أثناء التدريب دون إعادة تعريف الرسم البياني ، لكنني قررت استخدامه باعتباره ثابتًا وتحديد سلوكيات مختلفة للتدريب مقابل الاختبار ، والآن لا يتم حساب اللحظات في وقت الاختبار.
@ tano297 شكرا لك. أستخدم الآن أيضًا "is_training" كثابت. اتركه كعنصر نائب وسيؤدي إجراء اختبار دوري إلى تغيير قيمة المتوسط المتحرك والتباين المتحرك. وسيكون وقت الاستدلال أطول لأنه سيحسب متوسط وتباين المدخلات ويحدث المتوسط المتحرك والتباين المتحرك. الطريقة الصحيحة لإجراء الاختبار هي تحديد السلوكيات المختلفة للتدريب والاختبار كما ذكرت.
تضمين التغريدة
ولكن ليس "smart_cond" في
is_training_value = utils.constant_value(is_training)
need_updates = is_training_value is None or is_training_value
if need_updates:
...
outputs = utils.smart_cond(is_training, _force_updates, no_updates)
تأكد من أن التحديثات يتم حسابها وتطبيقها فقط إذا تم تقييم is_training إلى True؟
abred نعم بالفعل ، لكنك تشير إلى السطر 391 ، حيث يقوم بتحديث المتوسط المتحرك داخل _fused_batch_norm ():
# If `is_training` doesn't have a constant value, because it is a `Tensor`,
# a `Variable` or `Placeholder` then is_training_value will be None and
# `need_updates` will be true.
is_training_value = utils.constant_value(is_training)
need_updates = is_training_value is None or is_training_value
if need_updates:
...
outputs = utils.smart_cond(is_training, _force_updates, no_updates)
...
أنا أتحدث عن السطر 753 داخل batch_norm ():
# If `is_training` doesn't have a constant value, because it is a `Tensor`,
# a `Variable` or `Placeholder` then is_training_value will be None and
# `needs_moments` will be true.
is_training_value = utils.constant_value(is_training)
need_moments = is_training_value is None or is_training_value
if need_moments:
...
mean, variance = utils.smart_cond(is_training,
_force_updates,
moving_vars_fn)
...
تقرر الحالة الذكية في هذه الحالة (بقدر ما أشعر بالقلق) ما إذا كان يتم تحديث المتوسطات المتحركة أم لا ، ولكن لا يزال يتم حساب اللحظات.
@ tano297 أنت محق في ذلك ، كنت في المكان الخطأ ، لكن لا يزال:
السطر 755-770 يحسب اللحظات ، ولكن يتم استخدام اللحظات فقط في _force_updates والتي يتم تنفيذها فقط إذا تم تقييم is_training إلى True ، أليس كذلك؟
وهكذا
mean, variance = utils.smart_cond(is_training, _force_updates, moving_vars_fn)
يجب أن تكون مكافئة للسطر 804:
mean, variance = moving_mean, moving_variance
إذا قيمت is_training إلى False وبالتالي فإن جزء "اللحظات" من الرسم البياني لا يستخدم أبدًا وبالتالي لا ينبغي تنفيذه
لكنني لم أختبر ، لذلك قد أكون مخطئًا في ذلك :)
@ tano297abred أنت على حق. يتم تغيير المتوسط المتحرك والتباين المتحرك عندما استخدمت الدُفعة العادية مثل هذا:
def batch_norm_layer(self, x,train_phase, scope_bn):
bn_train = batch_norm(x, decay=0.9, center=False, scale=True,
updates_collections=None,
is_training=True,
reuse=None,
variables_collections= [UPDATE_OPS_COLLECTION],
trainable=True,
scope=scope_bn)
bn_inference = batch_norm(x, decay=0.9, center=False, scale=True,
updates_collections=None,
is_training=False,
reuse=True,
variables_collections= [UPDATE_OPS_COLLECTION],
trainable=True,
scope=scope_bn)
z = tf.cond(train_phase, lambda: bn_train, lambda: bn_inference)
return z
إذا كنت تستخدم ما يلي:
z = batch_norm(x, decay=0.9, center=False, scale=True, updates_collections=None,
is_training=train_phase, scope=scope_bn)
لن يتم تغيير المتوسط المتحرك والتباين المتحرك أثناء الاختبار ، لكن السرعة بطيئة للغاية.
مرحبا @ zhongyuk ،
لقد قابلت أيضًا مشكلة أنه يمكنني الحصول على نتائج جيدة عند استخدام is_training = True لكل من التدريب والاستدلال ، لكنني أحصل على نتائج سيئة عند ضبط is_training = False أثناء الاستدلال (أسوأ من الحالة باستخدام is_training = True). وفقًا لتحليلك ، إذا فهمت بشكل صحيح ، فإن ضبط الانحلال = 0.9 في BN يمكن أن يحل هذه المشكلة. هل انا على حق؟
راجع للشغل ، هل أحتاج إلى إعادة تدريب النموذج باستخدام الانحلال = 0.9 من نقطة الصفر؟ أو استئناف التدريب من نقطة التفتيش (أي ، التدريب عندما يكون الانحلال = 0.999) مناسبًا أيضًا؟
شكر!
تضمين التغريدة
مرحبًا ، لقد قابلت أيضًا مشكلة أنني قد أحصل على نتائج جيدة عند استخدام is_training = True لكل من التدريب والاستدلال ، لكنني أحصل على نتائج سيئة عند تعيين is_training = False أثناء الاستدلال (أسوأ من الحالة باستخدام is_training = True). هل حللتم هذه المشكلة يا رفاق؟ شكر!
tyshiwo لقد قمت للتو بتعيين الانحلال = 0.9 لـ batch_norm وهو يعمل بشكل جيد حتى الآن.
لقد كنت في حيرة من أمري بعد كل هذه التعليقات حول كيفية استخدام معيار الدُفعات بشكل صحيح: إذن هذا ما لدي. أرجوا أن تصحح لي إذا كنت مخطئا.
batch_norm = tf.contrib.layers.batch_norm(conv,
center=True,
scale=True,
reuse=phase_train_py,
scope='bn',
is_training=is_training)
حيث يعتبر stage_train_py متغيرًا منطقيًا من نوع Python و is_training هو عنصر نائب يأخذ متغيرًا منطقيًا. أعتقد أن استخدام tf.cond خطأ ، وإلا لكانت الوظيفة تأتي مع معلمات منطقية. بمعنى آخر ، إذا كان tf.cond
صحيحًا ، فيجب علينا استخدام وظيفة batch_norm
للتدريب وأخرى للاختبار. لذلك ، يسمح لنا المطورون بتغيير هذه المتغيرات المنطقية من أجل تغيير سلوك الوظيفة. لذا فإن ما أفعله هو: تعيين phase_train_py
إلى False أثناء التدريب بينما is_training
إلى True. والعكس أثناء الاختبار. نظرًا لأنه لا يمكننا سوى تغيير الموترات أو العناصر النائبة باستخدام sess.run
، فقد قمت بتغيير phase_train_py
قصد قبل تشغيل الرسم البياني. مثال:
if condition:
phase_train_py = False
sess.run(to_run_list, feed_dict={phase_train: True})
else:
phase_train_py = True
sess.run(to_run_list, feed_dict={phase_train: False})
++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++
ربما تحتاج إلى قراءة هذا
++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++
يبدو أنه لا تزال هناك مشاكل مع TF v1.3. أنا متأكد من أنني لاحظت التفاصيل التالية ، لكنني ما زلت أخفقت في استخدام tf.contrib.layers.batch_norm
الرسمي ، مع is_training=False
أثناء التقييم (لكن عندما أحافظ على is_training=True
دون تغيير أثناء التقييم ، فهو كذلك حسنا):
1. decay
، المتوسط المتحرك الأسي هو في الواقع مرشح ألفا في معالجة الإشارات ، وقت التقارب هو حوالي 1 / (1-decay) خطوة من القطار. بالنسبة للانحلال = 0.999 ، تحتاج إلى 1 / 0.001 = 1000 خطوة لتتقارب. لذا قم بتعيين الانحلال المناسب لأرقام خطوات التدريب الخاصة بك.
updates_collections=None
إذا كنت لا تريد إضافة تبعيات التحكم الخاصة بالتحديث إلى train_opreuse
إلى القيمة المناسبة.يبدو أن الطريقة الوحيدة لاستخدام الدُفعة الرسمية هي إنشاء رسمين بيانيين ، أحدهما للتدريب والآخر للتقييم ، باستخدام is_training=True
و is_training=False
على التوالي. بهذه الطريقة ، لا تحتاج إلى التبديل ديناميكيًا بين التدريب والتقييم. لكن هذه طريقة غبية لأنك تحتاج إلى إنشاء أكثر من رسم بياني.
أخيرًا ، أكتب متوسطًا متحركًا بنفسي ، وأجده يعمل! إنها كالتالي (بناءً على كود على الويب وعدّلته بنفسي)
def bn_layer(x, scope, is_training, epsilon=0.001, decay=0.99, reuse=None):
"""
Performs a batch normalization layer
Args:
x: input tensor
scope: scope name
is_training: python boolean value
epsilon: the variance epsilon - a small float number to avoid dividing by 0
decay: the moving average decay
Returns:
The ops of a batch normalization layer
"""
with tf.variable_scope(scope, reuse=reuse):
shape = x.get_shape().as_list()
# gamma: a trainable scale factor
gamma = tf.get_variable("gamma", shape[-1], initializer=tf.constant_initializer(1.0), trainable=True)
# beta: a trainable shift value
beta = tf.get_variable("beta", shape[-1], initializer=tf.constant_initializer(0.0), trainable=True)
moving_avg = tf.get_variable("moving_avg", shape[-1], initializer=tf.constant_initializer(0.0), trainable=False)
moving_var = tf.get_variable("moving_var", shape[-1], initializer=tf.constant_initializer(1.0), trainable=False)
if is_training:
# tf.nn.moments == Calculate the mean and the variance of the tensor x
avg, var = tf.nn.moments(x, np.arange(len(shape)-1), keep_dims=True)
avg=tf.reshape(avg, [avg.shape.as_list()[-1]])
var=tf.reshape(var, [var.shape.as_list()[-1]])
#update_moving_avg = moving_averages.assign_moving_average(moving_avg, avg, decay)
update_moving_avg=tf.assign(moving_avg, moving_avg*decay+avg*(1-decay))
#update_moving_var = moving_averages.assign_moving_average(moving_var, var, decay)
update_moving_var=tf.assign(moving_var, moving_var*decay+var*(1-decay))
control_inputs = [update_moving_avg, update_moving_var]
else:
avg = moving_avg
var = moving_var
control_inputs = []
with tf.control_dependencies(control_inputs):
output = tf.nn.batch_normalization(x, avg, var, offset=beta, scale=gamma, variance_epsilon=epsilon)
return output
def bn_layer_top(x, scope, is_training, epsilon=0.001, decay=0.99):
"""
Returns a batch normalization layer that automatically switch between train and test phases based on the
tensor is_training
Args:
x: input tensor
scope: scope name
is_training: boolean tensor or variable
epsilon: epsilon parameter - see batch_norm_layer
decay: epsilon parameter - see batch_norm_layer
Returns:
The correct batch normalization layer based on the value of is_training
"""
#assert isinstance(is_training, (ops.Tensor, variables.Variable)) and is_training.dtype == tf.bool
return tf.cond(
is_training,
lambda: bn_layer(x=x, scope=scope, epsilon=epsilon, decay=decay, is_training=True, reuse=None),
lambda: bn_layer(x=x, scope=scope, epsilon=epsilon, decay=decay, is_training=False, reuse=True),
)
فقط استخدم الدالة bn_layer_top
أثناء إنشاء رسم بياني ، فالمعامل is_training هو tf.placeholder
. إذن فأنت حر في تبديل العنصر النائب إلى True أثناء القطار و False أثناء التقييم ، feed_dict
.
اتمنى ان يساعد المجتمع
عند استخدام slim.batch_norm ، تأكد من استخدام "slim.learning.create_train_op" بدلاً من "tf.train.GradientDecentOptimizer (lr) .minimize (loss)" أو محسن آخر. جربه لترى ما إذا كان يعمل!
vincentvanhoucke لقد كتبت في موضوع آخر في هذا الموضوع:
يتم تطبيع غلاف الدُفعة النحيف على البعد الأخير لموتّر الإدخال. لذلك إذا كان موتر إدخال ثنائي الأبعاد قادمًا من طبقة متصلة بالكامل ، فإنه يتم تطبيعه على الدُفعة ، وبالتالي يقوم بإجراء تسوية لكل تنشيط. إذا كان موترًا رباعي الأبعاد قادمًا من التفاف ، فسيتم تطبيعه على الأبعاد الثلاثة الأولى (الدُفعة ، العرض ، العمق) ، وبالتالي إجراء تسوية لكل ميزة. sguada ربما يكون أكثر وصفيًا حول هذا الأمر.
هل تقصد مع "غلاف الدُفعات النحيفة" الدالة tf.contrib.layers.batch_norm
؟ إذا كان الأمر كذلك ، فإنني أقترح إضافة هذه المعلومات إلى نص التوثيق لهذه الوظيفة. وهكذا يصبح واضحًا جدًا ، أن هذه الوظيفة تؤدي تطبيع الدُفعات تمامًا كما هو موضح في الورقة ... لكل من FC-Layer و Conv2D-Layer. في الوقت الحالي ، لا يوجد سوى النص "يمكن استخدامه كدالة تسويقية لـ conv2d ومتصل بالكامل." ، حيث ليس من الواضح ما إذا كان هذا متعلقًا بموضوع محور التسوية.
ZahlGraf سأفكر بسعادة في العلاقات العامة التي توضح الوثائق. لقد كنا في هذا الأمر لفترة طويلة بحيث لم يعد لدي إحساس جيد بما هو واضح أو غير واضح ، وسأرحب بتوضيح الوثائق لشخص لديه منظور جديد حول هذا الموضوع.
تضمين التغريدة
لقد قمت بإنشاء علاقات عامة مع وصف أكثر تفصيلاً ، يعتمد بشكل أساسي على تصريحك في هذا الموضوع:
https://github.com/tensorflow/tensorflow/pull/15653
يرجى إزالة المحال إليه ، لأن هذه المشكلة تدعو إلى مساهمات خارجية. وإلا ، فقم بإزالة التصنيف contributions welcome
. شكرا لك.
يرجى إزالة المحال إليه ، لأن هذه المشكلة تدعو إلى مساهمات خارجية. وإلا ، فقم بإزالة التصنيف contributions welcome
. شكرا لك.
إغلاق هذا الخطأ منذ أن تمت معالجة الطلب الأصلي لإضافة طبقة معيار دفعة. يبدو أن بعض المشكلات الحديثة المتعلقة بالتوثيق لها علاقات عامة خاصة بها
إذا رأيت أي مشكلة في batch_norm ، فيرجى إما طرح سؤال على StackOverflow أو فتح مشكلة أخرى.
التعليق الأكثر فائدة
يوجد الآن طبقة
batch_norm
:https://github.com/tensorflow/tensorflow/blob/b826b79718e3e93148c3545e7aa3f90891744cc0/tensorflow/contrib/layers/python/layers/layers.py#L100