使用线性激活对密集层的输出进行归一化

数据挖掘 Python 深度学习 张量流
2022-02-16 17:11:40

我的网络架构如下:

def net_one(message):
    weight1 = np.random.normal(loc=0.0, scale=0.01, size=[16, 16])
    init1 = tf.constant_initializer(weight1)
    out1 = tf.layers.dense(inputs=message, units=16, activation=tf.nn.relu, kernel_initializer=init1)
    weight2 = np.random.normal(loc=0.0, scale=0.01, size=[16, 7])
    init2 = tf.constant_initializer(weight2)
    out2 = tf.layers.dense(inputs=out1, units=7, activation=None, kernel_initializer=init2)
    return out2

现在由于网络的输出是线性的(None在 tensorflow 中对应于线性激活函数),因此输出是无界的。我需要输出的平方2-norm是一个常数,n(出于能量约束的目的)。我不想使用sigmoidtanh因为它们妨碍性能。我尝试了以下方法:

code = net_one(input_bits)
code = code * tf.sqrt(n) / tf.linalg.norm(code)

我有两个问题:

  1. 它是否达到了我期望它达到的效果?
  2. 有没有更好的方法(如果这确实是正确的)或任何替代方法来实现这一点?
1个回答

你的方法似乎是正确的。我会建议您可能想尝试的另一种方法(也许它不会让您的生活变得更好,但仍然如此):由于您希望数据点基本上位于球体上,因此您可以在球坐标中训练角度。将半径固定为n这样你的网络就必须少学习一维。我不确定这将如何影响性能。

在张量流中实现这一点的一种方法可能是

def spherical(input):
    layer = []

    for i in range(input.get_shape()[1]+1):
        elem = 1
        for j in range(i):
            elem = elem*tf.sin(input[:,j])
        if i < input.get_shape()[1]:
            elem = elem*tf.cos(input[:,i])
        layer.append(elem)

    return tf.transpose(tf.convert_to_tensor(layer))

input这会将任何(带有 的张量)映射shape=(ndatapoints, ndims)到 中的单位球体ndims+1通过乘法和移位,您可以将其映射到您想要的任何球体。这可能不是最优雅的方式,但它可以完成工作。映射不是单射的,如果需要,您必须确保元素input坚持各自的间隔。

如果你最终尝试了这个,请告诉我它是怎么回事;)