จะกำหนดอัตราการเรียนรู้แบบปรับได้สำหรับ GradientDescentOptimizer ได้อย่างไร


104

ฉันใช้ TensorFlow เพื่อฝึกโครงข่ายประสาทเทียม นี่คือวิธีเริ่มต้นGradientDescentOptimizer:

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

mse        = tf.reduce_mean(tf.square(out - out_))
train_step = tf.train.GradientDescentOptimizer(0.3).minimize(mse)

สิ่งนี้คือฉันไม่รู้ว่าจะตั้งกฎการอัปเดตสำหรับอัตราการเรียนรู้หรือค่าลดลงอย่างไร

ฉันจะใช้อัตราการเรียนรู้แบบปรับได้ที่นี่ได้อย่างไร


3
เป็นนิสัยที่ดีในการเริ่มต้นตัวแปรทั้งหมดหลังจากที่คุณระบุเครื่องมือเพิ่มประสิทธิภาพของคุณเนื่องจากเครื่องมือเพิ่มประสิทธิภาพบางตัวเช่น AdamOptimizer ใช้ตัวแปรของตัวเองซึ่งจำเป็นต้องเริ่มต้นด้วย มิฉะนั้นคุณอาจได้รับข้อผิดพลาดที่มีลักษณะดังนี้:FailedPreconditionError (see above for traceback): Attempting to use uninitialized value beta2_power
JYun

ฉันได้รับข้อผิดพลาดดังกล่าวข้างต้นนี้เมื่อฉันพยายามที่จะกำหนดอัตราการเรียนรู้ใหม่ใน Tensorflow tf.train.GradientDescentOptimizer(new_lr).minimize(loss)โดย ดูเหมือนว่าการกำหนดอัตราการเรียนรู้ใหม่จำเป็นต้องเริ่มต้นโมเดลด้วยตัวแปรที่ฝึกฝนมาแล้ว แต่คิดไม่ออกว่าจะทำยังไง.
Siladittya

คำตอบ:


193

ก่อนอื่นtf.train.GradientDescentOptimizerได้รับการออกแบบมาเพื่อใช้อัตราการเรียนรู้คงที่สำหรับตัวแปรทั้งหมดในทุกขั้นตอน TensorFlow ยังมีเครื่องมือเพิ่มประสิทธิภาพการปรับตัวที่พร้อมใช้งานซึ่งรวมถึงtf.train.AdagradOptimizerและtf.train.AdamOptimizerและสิ่งเหล่านี้สามารถใช้แทนแบบดรอปอินได้

อย่างไรก็ตามหากคุณต้องการควบคุมอัตราการเรียนรู้ด้วยการไล่ระดับสีแบบอื่น - วานิลลาคุณสามารถใช้ประโยชน์จากข้อเท็จจริงที่ว่าlearning_rateอาร์กิวเมนต์ของตัวtf.train.GradientDescentOptimizerสร้างอาจเป็นTensorวัตถุได้ สิ่งนี้ช่วยให้คุณคำนวณค่าที่แตกต่างกันสำหรับอัตราการเรียนรู้ในแต่ละขั้นตอนตัวอย่างเช่น

learning_rate = tf.placeholder(tf.float32, shape=[])
# ...
train_step = tf.train.GradientDescentOptimizer(
    learning_rate=learning_rate).minimize(mse)

sess = tf.Session()

# Feed different values for learning rate to each training step.
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.01})
sess.run(train_step, feed_dict={learning_rate: 0.01})

หรือคุณสามารถสร้างสเกลาร์tf.Variableที่เก็บอัตราการเรียนรู้และกำหนดให้ทุกครั้งที่คุณต้องการเปลี่ยนอัตราการเรียนรู้


คำตอบที่ดี สามารถใช้เทคนิคเดียวกันนี้สำหรับการตัดแบบไล่ระดับสีได้หรือไม่ tf.clip_by_normไม่ยอมรับเทนเซอร์สำหรับบรรทัดฐานของคลิปแล้วจะทำ[(tf.minimum(gv[0], ct), gv[1]) for gv in optimizer.compute_gradients(cost, vars)]อย่างไรที่ไหนct = tf.placeholder('float32', shape=[])
richizy

นั่นควรจะใช้งานได้ใช่ (แม้ว่าจะมองไปที่tf.clip_by_normสิ่งเดียวที่ป้องกันไม่ให้รับเทนเซอร์เป็นอินพุตคือการconstant_op.constant(1.0 / clip_norm)แทนที่นิพจน์นั้นด้วยmath_ops.inv(clip_norm)จะทำให้มันทำงานกับตัวยึดตำแหน่ง (หรืออินพุตเทนเซอร์อื่น ๆ ))
mrry

@mrry ฉันทำตามที่คุณพูดและความเร็วในการฝึกซ้อมช้ากว่ามาก คาดว่าจะได้โปรด?
tnq177

89

Tensorflow tf.train.exponential_decayให้สหกรณ์การใช้การชี้แจงสลายไปเมตริกซ์อัตราการเรียนรู้โดยอัตโนมัติ: สำหรับตัวอย่างของมันในการใช้งานให้ดูบรรทัดนี้ในความสับสนตัวอย่างเช่นรุ่น MNIST จากนั้นใช้คำแนะนำของ @ mrry ด้านบนเพื่อจัดหาตัวแปรนี้เป็นพารามิเตอร์ learning_rate ให้กับเครื่องมือเพิ่มประสิทธิภาพที่คุณเลือก

ข้อความที่ตัดตอนมาที่สำคัญคือ:

# Optimizer: set up a variable that's incremented once per batch and
# controls the learning rate decay.
batch = tf.Variable(0)

learning_rate = tf.train.exponential_decay(
  0.01,                # Base learning rate.
  batch * BATCH_SIZE,  # Current index into the dataset.
  train_size,          # Decay step.
  0.95,                # Decay rate.
  staircase=True)
# Use simple momentum for the optimization.
optimizer = tf.train.MomentumOptimizer(learning_rate,
                                     0.9).minimize(loss,
                                                   global_step=batch)

สังเกตglobal_step=batchพารามิเตอร์เพื่อย่อเล็กสุด นั่นเป็นการบอกให้เครื่องมือเพิ่มประสิทธิภาพเพิ่มพารามิเตอร์ "แบทช์" ให้คุณทุกครั้งที่ฝึก


3
โดยปกติแล้วตัวแปรที่คุณโทรbatchเรียกว่าglobal_stepและมีฟังก์ชั่นอำนวยความสะดวกหลายอย่างใดอย่างหนึ่งสำหรับการสร้างมันtf.train.create_global_step()(ซึ่งก็สร้างจำนวนเต็มtf.Variableและเพิ่มไปยังtf.GraphKeys.GLOBAL_STEPคอลเลกชัน) tf.train.get_global_step()และ
Lenar Hoyt

86

ขั้นตอนวิธีการไล่โทนสีเชื้อสายใช้อัตราการเรียนรู้อย่างต่อเนื่องซึ่งคุณสามารถให้ในช่วงเริ่มต้น คุณสามารถผ่านอัตราการเรียนรู้ที่หลากหลายด้วยวิธีที่ Mrry แสดง

แต่แทนที่จะเป็นเช่นนั้นคุณยังสามารถใช้เครื่องมือเพิ่มประสิทธิภาพขั้นสูงซึ่งมีอัตราการลู่เข้าที่เร็วกว่าและปรับให้เข้ากับสถานการณ์ได้

นี่คือคำอธิบายสั้น ๆ ตามความเข้าใจของฉัน:

  • โมเมนตัม ช่วยให้ SGD นำทางไปตามทิศทางที่เกี่ยวข้องและทำให้การแกว่งเบาลงในส่วนที่ไม่เกี่ยวข้อง เพียงแค่เพิ่มเศษเสี้ยวของทิศทางของขั้นตอนก่อนหน้าให้กับขั้นตอนปัจจุบัน สิ่งนี้บรรลุการขยายความเร็วในการเบี่ยงเบนที่ถูกต้องและทำให้การสั่นเบาลงในทิศทางที่ไม่ถูกต้อง เศษส่วนนี้มักจะอยู่ในช่วง (0, 1) นอกจากนี้ยังมีเหตุผลที่จะใช้โมเมนตัมการปรับตัว ในช่วงเริ่มต้นของการเรียนรู้โมเมนตัมใหญ่จะขัดขวางความก้าวหน้าของคุณดังนั้นจึงควรใช้บางอย่างเช่น 0.01 และเมื่อการไล่ระดับสีสูงทั้งหมดหายไปคุณสามารถใช้โมเมนต์ที่ใหญ่กว่าได้ มีปัญหาอย่างหนึ่งเกี่ยวกับโมเมนตัมคือเมื่อเราเข้าใกล้เป้าหมายมากโมเมนตัมของเราในกรณีส่วนใหญ่จะสูงมากและไม่รู้ว่าควรจะช้าลง ซึ่งอาจทำให้พลาดหรือแกว่งไปรอบ ๆ มินิมา
  • การไล่ระดับสีแบบเร่ง nesterovสามารถเอาชนะปัญหานี้ได้โดยการเริ่มช้าลงในช่วงต้น ในโมเมนตัมเราคำนวณการไล่ระดับสีก่อนแล้วจึงกระโดดไปในทิศทางนั้นโดยขยายด้วยโมเมนตัมที่เราเคยมีมาก่อน NAG ทำสิ่งเดียวกัน แต่ในลำดับอื่น: ในตอนแรกเราทำการกระโดดครั้งใหญ่โดยอาศัยข้อมูลที่เก็บไว้ของเราจากนั้นเราจะคำนวณการไล่ระดับสีและทำการแก้ไขเล็กน้อย การเปลี่ยนแปลงที่ดูเหมือนไม่เกี่ยวข้องนี้ทำให้เกิดการเร่งความเร็วในทางปฏิบัติที่สำคัญ
  • AdaGradหรือการไล่ระดับสีแบบปรับได้ช่วยให้อัตราการเรียนรู้ปรับตามพารามิเตอร์ ทำการอัปเดตที่ใหญ่ขึ้นสำหรับพารามิเตอร์ที่ไม่บ่อยและการอัปเดตที่มีขนาดเล็กลงสำหรับพารามิเตอร์ที่ใช้บ่อย ด้วยเหตุนี้จึงเหมาะอย่างยิ่งสำหรับข้อมูลกระจัดกระจาย (NLP หรือการจดจำภาพ) ข้อดีอีกประการหนึ่งคือโดยพื้นฐานแล้วไม่จำเป็นต้องปรับอัตราการเรียนรู้ พารามิเตอร์แต่ละตัวมีอัตราการเรียนรู้ของตัวเองและเนื่องจากลักษณะเฉพาะของอัลกอริทึมทำให้อัตราการเรียนรู้ลดลงอย่างจำเจ สิ่งนี้ทำให้เกิดปัญหาใหญ่ที่สุด: ในบางช่วงเวลาอัตราการเรียนรู้น้อยมากจนระบบหยุดเรียนรู้
  • AdaDeltaแก้ปัญหาอัตราการเรียนรู้ที่ลดลงอย่างจำเจใน AdaGrad ใน AdaGrad อัตราการเรียนรู้คำนวณโดยประมาณโดยหารด้วยผลรวมของรากที่สอง ในแต่ละขั้นตอนคุณจะเพิ่มรากที่สองเข้าไปในผลรวมซึ่งทำให้ตัวส่วนลดลงอย่างต่อเนื่อง ใน AdaDelta แทนที่จะรวมสแควร์รูทที่ผ่านมาทั้งหมดจะใช้หน้าต่างบานเลื่อนซึ่งทำให้ผลรวมลดลง RMSpropคล้ายกับ AdaDelta มาก
  • อดัมหรือโมเมนตัมการปรับตัวเป็นอัลกอริทึมที่คล้ายกับ AdaDelta แต่นอกเหนือจากการจัดเก็บอัตราการเรียนรู้สำหรับแต่ละพารามิเตอร์แล้วยังจัดเก็บการเปลี่ยนแปลงโมเมนตัมสำหรับแต่ละพารามิเตอร์แยกกัน

    การแสดงภาพบางส่วน : ป้อนคำอธิบายภาพที่นี่ ป้อนคำอธิบายภาพที่นี่


2
สำหรับการเปรียบเทียบเครื่องมือเพิ่มประสิทธิภาพที่แตกต่างกันใน TensorFlow โปรดดูที่สมุดบันทึก ipython ต่อไปนี้: github.com/vsmolyakov/experiments_with_python/blob/master/chp03/…สำหรับ
Vadim Smolyakov

ไม่ควรใช้เครื่องมือเพิ่มประสิทธิภาพขั้นสูงเพิ่มเติม "แทน" แต่นอกจากนี้โปรดดูstats.stackexchange.com/questions/200063/…
Dima Lituiev

@DimaLituiev คุณใช้เครื่องมือเพิ่มประสิทธิภาพสองตัวพร้อมกันได้ไหม ถ้าไม่แสดงว่าคุณกำลังใช้ optimizer1 แทน optimizer2
Salvador Dali

1
นั่นไม่ใช่สิ่งที่ฉันกำลังพูดและมันไม่ใช่คำถามที่นี่ คุณแนะนำให้ใช้เครื่องมือเพิ่มประสิทธิภาพขั้นสูงแทนอัตราการเรียนรู้แบบปรับได้ ฉันกำลังบอกว่าคุณควรใช้เครื่องมือเพิ่มประสิทธิภาพขั้นสูงนอกเหนือจากอัตราการเรียนรู้แบบปรับตัวได้
Dima Lituiev

7

จากเอกสารทางการของtensorflow

global_step = tf.Variable(0, trainable=False)
starter_learning_rate = 0.1
learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step,
                                       100000, 0.96, staircase=True)

# Passing global_step to minimize() will increment it at each step.
learning_step = (
tf.train.GradientDescentOptimizer(learning_rate)
.minimize(...my loss..., global_step=global_step))

0

0 < a < b < c < ...หากคุณต้องการอัตราการเรียนรู้ชุดที่เฉพาะเจาะจงสำหรับช่วงเวลาของยุคสมัยเช่น จากนั้นคุณสามารถกำหนดอัตราการเรียนรู้ของคุณเป็นเทนเซอร์แบบมีเงื่อนไขตามเงื่อนไขในขั้นตอนทั่วโลกและป้อนข้อมูลนี้ตามปกติสำหรับเครื่องมือเพิ่มประสิทธิภาพ

คุณสามารถบรรลุสิ่งนี้ได้ด้วยtf.condคำสั่งซ้อน ๆ กันแต่มันง่ายกว่าที่จะสร้างเทนเซอร์ซ้ำ ๆ :

def make_learning_rate_tensor(reduction_steps, learning_rates, global_step):
    assert len(reduction_steps) + 1 == len(learning_rates)
    if len(reduction_steps) == 1:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: learning_rates[1]
        )
    else:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: make_learning_rate_tensor(
                reduction_steps[1:],
                learning_rates[1:],
                global_step,)
            )

จากนั้นจึงจะใช้งานได้คุณจำเป็นต้องทราบว่ามีขั้นตอนการฝึกอบรมกี่ขั้นตอนในยุคเดียวเพื่อที่เราจะได้ใช้ขั้นตอนทั่วโลกเพื่อเปลี่ยนในเวลาที่เหมาะสมและสุดท้ายกำหนดยุคและอัตราการเรียนรู้ที่คุณต้องการ ดังนั้นหากฉันต้องการอัตราการเรียนรู้[0.1, 0.01, 0.001, 0.0001]ในช่วงยุค[0, 19], [20, 59], [60, 99], [100, \infty]ตามลำดับฉันจะทำ:

global_step = tf.train.get_or_create_global_step()
learning_rates = [0.1, 0.01, 0.001, 0.0001]
steps_per_epoch = 225
epochs_to_switch_at = [20, 60, 100]
epochs_to_switch_at = [x*steps_per_epoch for x in epochs_to_switch_at ]
learning_rate = make_learning_rate_tensor(epochs_to_switch_at , learning_rates, global_step)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.