Làm cách nào để đặt tốc độ học tập thích ứng cho GradientDescentOptimizer?


104

Tôi đang sử dụng TensorFlow để đào tạo mạng nơ-ron. Đây là cách tôi khởi tạo 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)

Vấn đề ở đây là tôi không biết cách đặt quy tắc cập nhật cho tốc độ học hoặc giá trị giảm dần cho điều đó.

Làm cách nào để sử dụng tỷ lệ học tập thích ứng ở đây?


3
Một thói quen tốt là khởi tạo tất cả các biến sau khi bạn chỉ định trình tối ưu hóa của mình vì một số trình tối ưu hóa như AdamOptimizer sử dụng các biến của riêng nó cũng cần được khởi tạo. Nếu không, bạn có thể gặp lỗi giống như sau:FailedPreconditionError (see above for traceback): Attempting to use uninitialized value beta2_power
JYun

Tôi nhận được lỗi đã đề cập ở trên này khi tôi đang cố gắng đặt tốc độ học tập mới trong Tensorflow bằng tf.train.GradientDescentOptimizer(new_lr).minimize(loss). Có vẻ như, việc thiết lập một tỷ lệ học tập mới yêu cầu khởi tạo mô hình với các biến đã được đào tạo. Nhưng không thể tìm ra cách để làm điều đó.
Siladittya

Câu trả lời:


193

Trước hết, tf.train.GradientDescentOptimizerđược thiết kế để sử dụng tốc độ học không đổi cho tất cả các biến trong tất cả các bước. TensorFlow cũng cung cấp các trình tối ưu hóa thích ứng có sẵn bao gồm dấu tf.train.AdagradOptimizertf.train.AdamOptimizer, và chúng có thể được sử dụng như các bộ thay thế thả vào.

Tuy nhiên, nếu bạn muốn kiểm soát tốc độ học tập bằng cách khác-vani descent gradient, bạn có thể tận dụng lợi thế của thực tế là learning_rateđối số cho hàm tf.train.GradientDescentOptimizertạo có thể là một Tensorđối tượng. Điều này cho phép bạn tính toán một giá trị khác nhau cho tốc độ học tập trong mỗi bước, ví dụ:

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})

Ngoài ra, bạn có thể tạo một đại lượng vô hướng tf.Variablechứa tốc độ học và gán nó mỗi khi bạn muốn thay đổi tốc độ học.


Câu trả lời chính xác. Kỹ thuật tương tự có thể được sử dụng để cắt gradient không? tf.clip_by_normkhông chấp nhận một tensor cho chuẩn mực clip, vậy làm thế nào về việc làm [(tf.minimum(gv[0], ct), gv[1]) for gv in optimizer.compute_gradients(cost, vars)], nơict = tf.placeholder('float32', shape=[])
richizy

Điều đó sẽ hoạt động, vâng. (Mặc dù nhìn vào tf.clip_by_norm, điều duy nhất ngăn nó chấp nhận tensor làm đầu vào là constant_op.constant(1.0 / clip_norm). Thay thế biểu thức đó bằng math_ops.inv(clip_norm)sẽ làm cho nó hoạt động với đầu vào trình giữ chỗ (hoặc bất kỳ tensor nào khác).)
mrry

@mrry Tôi đã làm như bạn nói và một số cách tốc độ đào tạo chậm hơn nhiều. Nó có được mong đợi không?
tnq177 17/09/18

89

Tensorflow cung cấp một op để tự động áp dụng một phân rã theo cấp số nhân với một tensor tỷ lệ học: tf.train.exponential_decay. Để biết ví dụ về nó đang được sử dụng, hãy xem dòng này trong ví dụ về mô hình tích chập MNIST . Sau đó, sử dụng đề xuất của @ mrry ở trên để cung cấp biến này làm tham số learning_rate cho trình tối ưu hóa mà bạn lựa chọn.

Đoạn trích quan trọng cần xem là:

# 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)

Lưu ý global_step=batchtham số để giảm thiểu. Điều đó nói với trình tối ưu hóa để tăng một cách hữu ích tham số 'batch' cho bạn mỗi khi nó chạy.


3
Thông thường, biến mà bạn gọi batchđược gọi global_stepvà có một số hàm tiện lợi, một hàm để tạo nó tf.train.create_global_step()(chỉ đơn giản là tạo một số nguyên tf.Variablevà thêm nó vào tf.GraphKeys.GLOBAL_STEPbộ sưu tập) và tf.train.get_global_step().
Lenar Hoyt,

86

Thuật toán gradient descent sử dụng tốc độ học không đổi mà bạn có thể cung cấp trong quá trình khởi tạo . Bạn có thể vượt qua các tỷ lệ học tập khác nhau theo cách được chỉ ra bởi Mrry.

Nhưng thay vì nó, bạn cũng có thể sử dụng các trình tối ưu hóa nâng cao hơn có tốc độ hội tụ nhanh hơn và thích ứng với tình huống.

Đây là một lời giải thích ngắn gọn dựa trên sự hiểu biết của tôi:

  • xung lượng giúp SGD điều hướng dọc theo các hướng có liên quan và làm dịu các dao động không liên quan. Nó chỉ đơn giản là thêm một phần nhỏ hướng của bước trước vào bước hiện tại. Điều này giúp khuếch đại tốc độ theo đúng hướng và làm dịu dao động sai hướng. Phân số này thường nằm trong khoảng (0, 1). Nó cũng có ý nghĩa khi sử dụng động lực thích ứng. Khi bắt đầu học, một động lượng lớn sẽ chỉ cản trở sự tiến bộ của bạn, vì vậy bạn nên sử dụng một cái gì đó như 0,01 và một khi tất cả các độ dốc cao biến mất, bạn có thể sử dụng một khoảnh khắc lớn hơn. Có một vấn đề với động lượng: khi chúng ta đang ở rất gần mục tiêu, động lượng của chúng ta trong hầu hết các trường hợp là rất cao và nó không biết rằng nó phải giảm tốc độ. Điều này có thể khiến nó bỏ lỡ hoặc dao động xung quanh cực tiểu
  • gradient gia tốc nesterov khắc phục vấn đề này bằng cách bắt đầu giảm tốc độ sớm. Trong động lượng, trước tiên chúng ta tính toán gradient và sau đó thực hiện một bước nhảy theo hướng đó được khuếch đại bởi bất kỳ động lượng nào chúng ta đã có trước đó. NAG làm điều tương tự nhưng theo một trình tự khác: lúc đầu, chúng tôi thực hiện một bước nhảy vọt dựa trên thông tin được lưu trữ của chúng tôi, sau đó chúng tôi tính toán gradient và thực hiện một hiệu chỉnh nhỏ. Thay đổi dường như không liên quan này mang lại tốc độ thực tế đáng kể.
  • AdaGrad hoặc gradient thích ứng cho phép tốc độ học tập thích ứng dựa trên các tham số. Nó thực hiện các bản cập nhật lớn hơn cho các thông số không thường xuyên và các bản cập nhật nhỏ hơn cho một lần thường xuyên. Bởi vì điều này rất phù hợp với dữ liệu thưa thớt (NLP hoặc nhận dạng hình ảnh). Một ưu điểm khác là về cơ bản nó không hạn chế nhu cầu điều chỉnh tốc độ học tập. Mỗi tham số có tốc độ học tập riêng của nó và do tính đặc thù của thuật toán, tốc độ học tập đang giảm dần. Điều này gây ra vấn đề lớn nhất: tại một số thời điểm tỷ lệ học tập quá nhỏ đến mức hệ thống ngừng học
  • AdaDelta giải quyết vấn đề tỷ lệ học tập giảm dần trong AdaGrad. Trong AdaGrad, tỷ lệ học tập được tính xấp xỉ bằng một chia cho tổng các căn bậc hai. Ở mỗi giai đoạn, bạn thêm một căn bậc hai vào tổng, điều này làm cho mẫu số liên tục giảm. Trong AdaDelta thay vì tính tổng tất cả các căn bậc hai trong quá khứ, nó sử dụng cửa sổ trượt cho phép tổng giảm. RMSprop rất giống với AdaDelta
  • Adam hay động lượng thích ứng là một thuật toán tương tự như AdaDelta. Nhưng ngoài việc lưu trữ tốc độ học tập cho từng tham số, nó cũng lưu trữ các thay đổi động lượng cho từng tham số riêng biệt

    Một vài hình dung : nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây


2
Để so sánh của tối ưu khác nhau trong TensorFlow có một cái nhìn tại sau ipython máy tính xách tay: github.com/vsmolyakov/experiments_with_python/blob/master/chp03/... cho
Vadim Smolyakov

Các trình tối ưu hóa nâng cao hơn sẽ không được sử dụng "thay thế" nhưng ngoài ra, hãy xem stats.stackexchange.com/questions/200063/…
Dima Lituiev

@DimaLituiev bạn có thể sử dụng hai trình tối ưu hóa cùng một lúc không? Nếu không thì bạn đang sử dụng trình tối ưu hóa1 thay vì trình tối ưu hóa2.
Salvador Dali

1
đó không phải là những gì tôi đang nói, và nó không phải là câu hỏi ở đây. Bạn đề xuất sử dụng các trình tối ưu hóa nâng cao thay vì tỷ lệ học tập thích ứng. Tôi nói rằng bạn muốn sử dụng tối ưu ảnh tiên tiến, thêm vào tỷ lệ học thích nghi
Dima Lituiev

7

Từ tài liệu chính thức của 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

Nếu bạn muốn đặt tốc độ học cụ thể cho các khoảng thời gian như thế nào 0 < a < b < c < .... Sau đó, bạn có thể xác định tốc độ học tập của mình dưới dạng một tensor có điều kiện, có điều kiện đối với bước tổng thể và cung cấp điều này như bình thường cho trình tối ưu hóa.

Bạn có thể đạt được điều này với một loạt các tf.condcâu lệnh lồng nhau , nhưng việc xây dựng đệ quy tensor dễ dàng hơn:

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,)
            )

Sau đó, để sử dụng nó, bạn cần biết có bao nhiêu bước đào tạo trong một kỷ nguyên, để chúng ta có thể sử dụng bước toàn cục để chuyển đổi vào đúng thời điểm, và cuối cùng xác định các kỷ nguyên và tốc độ học mà bạn muốn. Vì vậy, nếu tôi muốn tốc độ học tập [0.1, 0.01, 0.001, 0.0001]trong các khoảng thời gian [0, 19], [20, 59], [60, 99], [100, \infty]tương ứng, tôi sẽ làm:

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.