2016-07-13 23 views
7

Tôi muốn thực hiện trong TensorFlow kỹ thuật "Hướng dẫn truyền lại" được giới thiệu trong Paper và được mô tả trong recipe này.Hướng dẫn sao chép ngược trong TensorFlow

Tính toán có nghĩa là khi tôi tính toán độ dốc, ví dụ: của giá trị đầu vào. đầu ra của NN, tôi sẽ phải sửa đổi các gradient được tính tại mỗi đơn vị RELU. Cụ thể, tín hiệu truyền lại trên các đơn vị đó phải được ngưỡng bằng 0, để làm cho kỹ thuật này hoạt động. Nói cách khác, đạo hàm một phần của các RELU là âm phải được bỏ qua.

Vì tôi chỉ muốn áp dụng các phép tính gradient này trên ví dụ kiểm tra, tức là tôi không muốn cập nhật tham số của mô hình - tôi sẽ làm như thế nào?

tôi đã cố gắng (không thành công) hai điều cho đến nay:

  1. Sử dụng tf.py_func quấn phiên bản numpy đơn giản của tôi về một RELU, sau đó là đủ điều kiện để xác định lại nó hoạt động Gradient qua g .gradient_override_map trình quản lý ngữ cảnh.

  2. Thu thập các giá trị chuyển tiếp/lùi của BackProp và áp dụng quy trình làm nổi bật trên các giá trị xuất phát từ Relus.

Tôi không thành công với cả hai phương pháp tiếp cận vì chúng cần một số kiến ​​thức về nội bộ của TF hiện tại tôi không có.

Có ai có thể đề xuất bất kỳ tuyến đường nào khác hoặc phác họa mã không?

Cảm ơn rất nhiều.

Trả lời

5

tf.gradients có thông số grad_ys có thể được sử dụng cho mục đích này. Giả sử mạng của bạn có chỉ là một relu lớp như sau:

before_relu = f1(inputs, params) 
after_relu = tf.nn.relu(before_relu) 
loss = f2(after_relu, params, targets) 

Thứ nhất, tính đạo hàm lên đến after_relu.

Dafter_relu = tf.gradients(loss, after_relu)[0] 

Sau đó, giảm độ dốc mà bạn gửi xuống.

Dafter_relu_thresholded = tf.select(Dafter_relu < 0.0, 0.0, Dafter_relu) 

Tính toán độ dốc thực tế từ 0.39.t đến params.

Dparams = tf.gradients(after_relu, params, grad_ys=Dafter_relu_thresholded) 

Bạn có thể dễ dàng mở rộng cùng phương thức này cho mạng có nhiều lớp relu.

+0

Xin chào Kaveman, cảm ơn rất nhiều vì đã trả lời nhanh chóng. Trong tf.gradients cuối cùng của bạn gọi bạn đang cố ý vượt qua Dafter_relu như là đối số đầu tiên? – Peter

+1

Ngoài ra, tôi vẫn còn bối rối wrt. làm thế nào để khái quát hóa điều này trên một mạng với nhiều lớp theo cách hoạt động cho bất kỳ NN nào có các phần tử RELU. Đối với phần này bạn sẽ không cần phải theo dõi tất cả các đầu vào/đầu ra của mỗi phần tử RELU và 'chuỗi' logic đã mô tả trước đây của bạn? Cảm ơn. – Peter

+0

@Peter, xin lỗi, đó là lỗi đánh máy. Cuộc gọi thứ hai tới 'tf.gradients' là' after_relu' w.r.t. 'params'. – keveman

5

Giải pháp tốt hơn (cách tiếp cận của bạn 1) với ops.RegisterGradienttf.Graph.gradient_override_map. Họ cùng nhau ghi đè lên tính toán gradient cho Op được xác định trước, ví dụ: Relu trong ngữ cảnh gradient_override_map chỉ sử dụng mã python.

@ops.RegisterGradient("GuidedRelu") 
def _GuidedReluGrad(op, grad): 
    return tf.where(0. < grad, gen_nn_ops._relu_grad(grad, op.outputs[0]), tf.zeros(grad.get_shape())) 

... 
with g.gradient_override_map({'Relu': 'GuidedRelu'}): 
    y = tf.nn.relu(x) 

đây là ví dụ thực hiện đầy đủ relu hướng dẫn: https://gist.github.com/falcondai/561d5eec7fed9ebf48751d124a77b087

Cập nhật: trong Tensorflow> = 1.0, tf.select được đổi tên thành tf.where. Tôi đã cập nhật đoạn mã cho phù hợp. (Cảm ơn @sbond vì đã chú ý đến điều này :)

+2

hãy cẩn thận rằng bạn cần phải bọc cấu trúc đồ thị liên quan đến relu op * bên trong * ngữ cảnh 'gradient_override_map'. – Falcon

+1

Cảm ơn bạn, @ Falcon, điều này hoạt động tốt. Tôi cũng đã phải thay thế tf.select bởi tf.where, như tôi đang sử dụng TF phiên bản 1.2. – sbond

+0

@sbond Cảm ơn bạn đã cập nhật. Tôi đã chỉnh sửa bài đăng của tôi để bao gồm nhận xét của bạn. – Falcon

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