Python 用张量流重正化权矩阵
我想给我的TensorFlow图中的几个权重矩阵添加一个最大范数约束,即ala Torch的方法 如果任何神经元权重矩阵的L2范数超过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): '''
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!