2016-01-21 29 views
6

Tôi muốn thêm ràng buộc chuẩn tối đa vào một số ma trận trọng lượng trong đồ thị TensorFlow của tôi, phương pháp renorm của ala Torch.Làm chuẩn hóa lại ma trận trọng lượng sử dụng TensorFlow

Nếu chuẩn L2 của ma trận trọng lượng của bất kỳ nơron nào vượt quá max_norm, tôi muốn giảm tỷ lệ của nó xuống sao cho chỉ tiêu L2 của chúng chính xác là max_norm.

Cách tốt nhất để diễn tả điều này bằng cách sử dụng TensorFlow là gì?

Trả lời

1

Hãy xem chức năng clip_by_norm, thực hiện chính xác điều này. Phải mất một tensor đơn như đầu vào và trả về một tensor xuống.

+0

Cảm ơn các con trỏ! Điều đó trông rất gần với những gì tôi muốn, chỉ áp dụng cho toàn bộ ma trận, trong khi tôi muốn chuẩn hóa lại từng cột một cách độc lập (đổi tên của Ala Torch). Điều này có thể không? – danvk

+0

Có lẽ bằng cách thay thế cuộc gọi ['reduce_sum'] (https://github.com/tensorflow/tensorflow/blob/b11337ea5719a8799f279a41c2cd5c9e75a8acf7/tensorflow/python/ops/clip_ops.py#L90-L93) trong' clip_by_norm' bằng một thứ được đặt ['reduction_indices'] (https://www.tensorflow.org/versions/master/api_docs/python/math_ops.html#reduce_sum)? – danvk

+0

Ah, từ câu hỏi có vẻ như bạn muốn bình thường hóa toàn bộ ma trận bằng cách sử dụng tiêu chuẩn của nó và không phải cột riêng biệt. –

2

Sử dụng gợi ý Rafał và TensorFlow của implementation của clip_by_norm, đây là những gì tôi đã đưa ra:

def renorm(x, axis, max_norm): 
    '''Renormalizes the sub-tensors along axis such that they do not exceed norm max_norm.''' 
    # This elaborate dance avoids empty slices, which TF dislikes. 
    rank = tf.rank(x) 
    bigrange = tf.range(-1, rank + 1) 
    dims = tf.slice(
       tf.concat(0, [tf.slice(bigrange, [0], [1 + axis]), 
           tf.slice(bigrange, [axis + 2], [-1])]), 
       [1], rank - [1]) 

    # Determine which columns need to be renormalized. 
    l2norm_inv = tf.rsqrt(tf.reduce_sum(x * x, dims, keep_dims=True)) 
    scale = max_norm * tf.minimum(l2norm_inv, tf.constant(1.0/max_norm)) 

    # Broadcast the scalings 
    return tf.mul(scale, x) 

Nó dường như có hành vi mong muốn cho 2 chiều ma trận và cần khái quát để tensors:

> x = tf.constant([0., 0., 3., 4., 30., 40., 300., 400.], shape=(4, 2)) 
> print x.eval() 
[[ 0. 0.] # rows have norms of 0, 5, 50, 500 
[ 3. 4.] # cols have norms of ~302, ~402 
[ 30. 40.] 
[ 300. 400.]] 
> print renorm(x, 0, 10).eval() 
[[ 0.   0.  ] # unaffected 
[ 3.   4.  ] # unaffected 
[ 5.99999952 7.99999952] # rescaled 
[ 6.00000048 8.00000095]] # rescaled 
> print renorm(x, 1, 350).eval() 
[[ 0.   0.  ] # col 0 is unaffected 
[ 3.   3.48245788] # col 1 is rescaled 
[ 30.   34.82457733] 
[ 300.   348.24578857]] 
4

Dưới đây là triển khai có thể có:

import tensorflow as tf 

def maxnorm_regularizer(threshold, axes=1, name="maxnorm", collection="maxnorm"): 
    def maxnorm(weights): 
     clipped = tf.clip_by_norm(weights, clip_norm=threshold, axes=axes) 
     clip_weights = tf.assign(weights, clipped, name=name) 
     tf.add_to_collection(collection, clip_weights) 
     return None # there is no regularization loss term 
    return maxnorm 

Đây là cách bạn sẽ sử dụng nó:

from tensorflow.contrib.layers import fully_connected 
from tensorflow.contrib.framework import arg_scope 

with arg_scope(
     [fully_connected], 
     weights_regularizer=max_norm_regularizer(1.5)): 
    hidden1 = fully_connected(X, 200, scope="hidden1") 
    hidden2 = fully_connected(hidden1, 100, scope="hidden2") 
    outputs = fully_connected(hidden2, 5, activation_fn=None, scope="outs") 

max_norm_ops = tf.get_collection("max_norm") 

[...] 

with tf.Session() as sess: 
    sess.run(init) 
    for epoch in range(n_epochs): 
     for X_batch, y_batch in load_next_batch(): 
      sess.run(training_op, feed_dict={X: X_batch, y: y_batch}) 
      sess.run(max_norm_ops) 

Điều này tạo ra một mạng lưới thần kinh 3 lớp và huấn luyện nó với chính quy định mức tối đa tại mỗi lớp (với một ngưỡng 1,5). Tôi chỉ thử nó, dường như làm việc. Hi vọng điêu nay co ich! Đề xuất cải tiến được hoan nghênh. :)

Ghi chú

Mã này được dựa trên tf.clip_by_norm():

>>> x = tf.constant([0., 0., 3., 4., 30., 40., 300., 400.], shape=(4, 2)) 
>>> print(x.eval()) 
[[ 0. 0.] 
[ 3. 4.] 
[ 30. 40.] 
[ 300. 400.]] 
>>> clip_rows = tf.clip_by_norm(x, clip_norm=10, axes=1) 
>>> print(clip_rows.eval()) 
[[ 0.   0.  ] 
[ 3.   4.  ] 
[ 6.   8.  ] # clipped! 
[ 6.00000048 8.  ]] # clipped! 

Bạn cũng có thể cắt cột nếu bạn cần phải:

>>> clip_cols = tf.clip_by_norm(x, clip_norm=350, axes=0) 
>>> print(clip_cols.eval()) 
[[ 0.   0.  ] 
[ 3.   3.48245788] 
[ 30.   34.82457733] 
[ 300.   348.24578857]] 
       # clipped! 
Các vấn đề liên quan