2016-01-22 24 views
29

Tôi tự hỏi nếu có một cách mà tôi có thể sử dụng tỷ lệ học tập khác nhau cho các lớp khác nhau như những gì trong Caffe. Tôi đang cố gắng sửa đổi một mô hình được đào tạo trước và sử dụng nó cho các nhiệm vụ khác. Những gì tôi muốn là tăng tốc độ đào tạo cho các lớp mới được thêm vào và giữ cho các lớp được đào tạo ở tỷ lệ học tập thấp để ngăn chặn chúng khỏi bị bóp méo. ví dụ: tôi có mô hình được đào tạo trước 5 lớp. Bây giờ tôi thêm một lớp đối tượng mới và tinh chỉnh nó. 5 lớp đầu tiên sẽ có tỷ lệ học tập là 0,00001 và lớp cuối cùng sẽ có 0,001. Bất kỳ ý tưởng làm thế nào để đạt được điều này?Làm thế nào để thiết lập tốc độ học tập lớp khôn ngoan trong Tensorflow?

Trả lời

53

Nó có thể đạt được khá dễ dàng với 2 tối ưu:

var_list1 = [variables from first 5 layers] 
var_list2 = [the rest of variables] 
train_op1 = GradientDescentOptimizer(0.00001).minimize(loss, var_list=var_list1) 
train_op2 = GradientDescentOptimizer(0.0001).minimize(loss, var_list=var_list2) 
train_op = tf.group(train_op1, train_op2) 

Một bất lợi của thực hiện này là nó tính tf.gradients hai lần bên trong tối ưu và do đó nó có thể không được tối ưu về (.) tốc độ thực thi. Điều này có thể được giảm nhẹ bằng cách gọi một cách rõ ràng tf.gradients (.), Chia danh sách thành 2 và chuyển các gradient tương ứng cho cả hai trình tối ưu hóa.

câu hỏi liên quan: Holding variables constant during optimizer

EDIT: Thêm hiệu quả hơn nhưng còn thực hiện:

var_list1 = [variables from first 5 layers] 
var_list2 = [the rest of variables] 
opt1 = tf.train.GradientDescentOptimizer(0.00001) 
opt2 = tf.train.GradientDescentOptimizer(0.0001) 
grads = tf.gradients(loss, var_list1 + var_list2) 
grads1 = grads[:len(var_list1)] 
grads2 = grads[len(var_list1):] 
tran_op1 = opt1.apply_gradients(zip(grads1, var_list1)) 
train_op2 = opt2.apply_gradients(zip(grads2, var_list2)) 
train_op = tf.group(train_op1, train_op2) 

Bạn có thể sử dụng tf.trainable_variables() để có được tất cả các biến đào tạo và quyết định để chọn từ họ. Sự khác biệt là trong lần triển khai đầu tiên, tf.gradients(.) được gọi hai lần bên trong trình tối ưu hóa. Điều này có thể khiến một số hoạt động dự phòng được thực thi (ví dụ: các gradient trên lớp đầu tiên có thể sử dụng lại một số tính toán cho các gradient của các lớp sau).

+0

Cảm ơn câu trả lời của bạn Rafal. Tôi vẫn còn một chút tự hỏi khi bạn nói những bất lợi của nó về tốc độ, bao nhiêu nó sẽ ảnh hưởng đến hiệu suất. Nếu tôi đào tạo một mạng lưới lớn, nếu đây là một gánh nặng lớn, nó sẽ không phải là một lựa chọn tốt. Ngoài ra, bạn có thể cụ thể hơn về phương pháp thứ hai của mình không? Làm thế nào để gọi một cách rõ ràng tf.gradients()? Xin lỗi, tôi vẫn là một newbie. –

+0

Đã chỉnh sửa câu trả lời. –

+0

thx man, là dòng cuối cùng thứ hai được cho là "train_op2 = opt2.apply_gradients (.)"? nếu tôi hiểu đúng. –

6

Cập nhật 22 tháng 1: công thức dưới đây chỉ là một ý tưởng tốt cho GradientDescentOptimizer, tối ưu hóa khác mà giữ một trung bình chạy sẽ áp dụng tỷ lệ học trước khi cập nhật thông số, vì vậy công thức dưới đây sẽ không ảnh hưởng đến một phần của phương trình

Ngoài phương pháp của Rafal, bạn có thể sử dụng giao diện compute_gradients, apply_gradients của Optimizer. Ví dụ, đây là một mạng đồ chơi mà tôi sử dụng 2x tỷ lệ học cho tham số thứ hai

x = tf.Variable(tf.ones([])) 
y = tf.Variable(tf.zeros([])) 
loss = tf.square(x-y) 
global_step = tf.Variable(0, name="global_step", trainable=False) 

opt = tf.GradientDescentOptimizer(learning_rate=0.1) 
grads_and_vars = opt.compute_gradients(loss, [x, y]) 
ygrad, _ = grads_and_vars[1] 
train_op = opt.apply_gradients([grads_and_vars[0], (ygrad*2, y)], global_step=global_step) 

init_op = tf.initialize_all_variables() 
sess = tf.Session() 
sess.run(init_op) 
for i in range(5): 
    sess.run([train_op, loss, global_step]) 
    print sess.run([x, y]) 

Bạn sẽ thấy

[0.80000001, 0.40000001] 
[0.72000003, 0.56] 
[0.68800002, 0.62400001] 
[0.67520005, 0.64960003] 
[0.67008007, 0.65984005] 
+1

Tốt khi sử dụng SGD nhưng không chắc liệu nó có tối ưu cho các trình tối ưu hóa ưa thích hơn tính toán số liệu thống kê so với các giá trị quá khứ hay không… Có thể không tạo ra sự khác biệt miễn là bạn không muốn thay đổi tốc độ học tập đó trong quá trình đào tạo. –

+0

điểm tốt, câu trả lời cập nhật –

+0

Cảm ơn người đàn ông, điều này có vẻ rực rỡ. –

3

Thu thập học nhân tỷ lệ cho mỗi biến như:

self.lr_multipliers[var.op.name] = lr_mult 

và sau đó áp dụng chúng trong khi trước khi áp dụng các gradient như:

def _train_op(self): 
    tf.scalar_summary('learning_rate', self._lr_placeholder) 
    opt = tf.train.GradientDescentOptimizer(self._lr_placeholder) 
    grads_and_vars = opt.compute_gradients(self._loss) 
    grads_and_vars_mult = [] 
    for grad, var in grads_and_vars: 
    grad *= self._network.lr_multipliers[var.op.name] 
    grads_and_vars_mult.append((grad, var)) 
    tf.histogram_summary('variables/' + var.op.name, var) 
    tf.histogram_summary('gradients/' + var.op.name, grad) 
    return opt.apply_gradients(grads_and_vars_mult) 

Bạn có thể tìm thấy toàn bộ ví dụ here.

0

5 lớp đầu tiên sẽ có tỷ lệ học là 0.00001 và lớp cuối cùng sẽ có 0,001. Bất kỳ ý tưởng làm thế nào để đạt được điều này?

Có một cách dễ dàng để thực hiện việc đó bằng tf.stop_gradient. Dưới đây là một ví dụ với 3 lớp:

x = layer1(input) 
x = layer2(x) 
output = layer3(x) 

Bạn có thể thu nhỏ gradient của bạn trong hai lớp đầu tiên của một tỷ lệ 1/100:

x = layer1(input) 
x = layer2(x) 
x = 1/100*x + (1-1/100)*tf.stop_gradient(x) 
output = layer3(x) 

Trên layer2, các "dòng chảy" là phân chia thành hai nhánh: một nhánh có đóng góp 1/100 tính gradient của nó thường xuyên nhưng với độ dốc được co lại theo tỷ lệ 1/100, nhánh kia cung cấp "dòng chảy" còn lại mà không góp phần vào gradient do tf .stop_gradient operator. Kết quả là, nếu bạn sử dụng tỷ lệ học tập là 0,001 trên trình tối ưu hóa mô hình của bạn, hai lớp đầu tiên hầu như sẽ có tỷ lệ học tập là 0.00001.

Các vấn đề liên quan