Python 用张量流重正化权矩阵

Python 用张量流重正化权矩阵,python,tensorflow,Python,Tensorflow,我想给我的TensorFlow图中的几个权重矩阵添加一个最大范数约束,即ala Torch的方法 如果任何神经元权重矩阵的L2范数超过max\u范数,我想缩小它的权重,使它们的L2范数正好是max\u范数 使用TensorFlow来表达这一点的最佳方式是什么?看看函数,它正是这样做的。它将一个张量作为输入,并返回一个按比例缩小的张量。使用Rafał的建议和TensorFlow的clip_by_norm,我得出以下结论: def renorm(x, axis, max_norm): '''

我想给我的TensorFlow图中的几个权重矩阵添加一个最大范数约束,即ala Torch的方法

如果任何神经元权重矩阵的L2范数超过
max\u范数
,我想缩小它的权重,使它们的L2范数正好是
max\u范数


使用TensorFlow来表达这一点的最佳方式是什么?

看看函数,它正是这样做的。它将一个张量作为输入,并返回一个按比例缩小的张量。

使用Rafał的建议和TensorFlow的
clip_by_norm
,我得出以下结论:

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)
它似乎具有二维矩阵所需的行为,应该 推广到张量:

> 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]]

下面是一个可能的实现:

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
以下是您将如何使用它:

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)
这将创建一个三层神经网络,并在每一层(阈值为1.5)使用最大范数正则化对其进行训练。我刚试过,似乎有用。希望这有帮助!欢迎提出改进建议。:)

注释

此代码基于
tf.clip\u by\u norm()

如果需要,还可以剪裁列:

>>> 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!

谢谢你的指点!这看起来非常接近我想要的,只是它适用于整个矩阵,而我想独立地重新规范化每个列(ala Torch的renorm)。这是可能的吗?也许通过将in
clip\u替换为\u norm
来设置?啊,从问题来看,似乎您希望使用其norm而不是单独使用列来规范化整个矩阵。是的,添加参数以将\u sum减少到给定行或列的聚合,就足以获得规范。此外,我们需要用独立值更新最终矩阵。解决这一问题的简单方法是通过额外的参数keep_dims=True并让广播处理所有事情。最后的更改是:
reduce\u axis=1;或者行为0
reduce\u sum(t*t,reduce\u axis,keep\u dims=True)
我将这些建议转换为新的答案。欢迎反馈,特别是关于是否有更好的方法生成列表,如
[0,1,3,4]
:缺少一个元素的范围。
>>> 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!