如何在优化器中获得偏差和神经元权重?

时间:2017-07-10 15:13:36

标签: python tensorflow

在TensorFlow优化器(python)中,方法apply_dense会调用神经元权重(图层连接)和偏差权重,但我想在此方法中同时使用它们。

def _apply_dense(self, grad, weight):
    ...

例如:一个完全连接的神经网络,其中两个隐藏层有两个神经元,每个神经网络都有偏差。

Neural network example

如果我们看一下第2层,我们会在apply_dense调用神经元权重:

neuron weights

并要求偏见权重:

bias weights

但我要么在apply_dense的一次调用中需要两个矩阵,要么像这样需要一个权重矩阵:

all weights from one layer

X_2X_4,B_1X_4,...只是两个神经元之间连接权重的表示法。因此B_1X_4只是B_1和X_4之间权重的占位符。

怎么做?

MWE

这里的最小工作示例是具有动量的随机梯度下降优化器实现。对于每一层,来自其他神经元的所有传入连接的动量都减少到平均值(参见ndims == 2)。我需要的不仅是来自神经元连接的动量值的平均值,还来自输入偏置连接的平均值(如上所述)。

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf
from tensorflow.python.training import optimizer


class SGDmomentum(optimizer.Optimizer):
    def __init__(self, learning_rate=0.001, mu=0.9, use_locking=False, name="SGDmomentum"):
        super(SGDmomentum, self).__init__(use_locking, name)
        self._lr = learning_rate
        self._mu = mu

        self._lr_t = None
        self._mu_t = None

    def _create_slots(self, var_list):
        for v in var_list:
            self._zeros_slot(v, "a", self._name)

    def _apply_dense(self, grad, weight):
        learning_rate_t = tf.cast(self._lr_t, weight.dtype.base_dtype)
        mu_t = tf.cast(self._mu_t, weight.dtype.base_dtype)
        momentum = self.get_slot(weight, "a")

        if momentum.get_shape().ndims == 2:  # neuron weights
            momentum_mean = tf.reduce_mean(momentum, axis=1, keep_dims=True)
        elif momentum.get_shape().ndims == 1:  # bias weights
            momentum_mean = momentum
        else:
            momentum_mean = momentum

        momentum_update = grad + (mu_t * momentum_mean)
        momentum_t = tf.assign(momentum, momentum_update, use_locking=self._use_locking)

        weight_update = learning_rate_t * momentum_t
        weight_t = tf.assign_sub(weight, weight_update, use_locking=self._use_locking)

        return tf.group(*[weight_t, momentum_t])

    def _prepare(self):
        self._lr_t = tf.convert_to_tensor(self._lr, name="learning_rate")
        self._mu_t = tf.convert_to_tensor(self._mu, name="momentum_term")

对于一个简单的神经网络:https://raw.githubusercontent.com/aymericdamien/TensorFlow-Examples/master/examples/3_NeuralNetworks/multilayer_perceptron.py(仅将优化器更改为自定义SGDmomentum优化器)

1 个答案:

答案 0 :(得分:1)

更新:我现在尝试给出一个更好的答案(或者至少是一些想法),因为我对你的目标有一些了解,但正如你在评论中所建议的那样,在TensorFlow中这不是绝对可靠的方式。

由于TF是一般计算框架,因此没有好的方法来确定模型中存在哪些权重和偏差对(或者它是否完全是神经网络)。以下是我能想到的问题的一些可能方法:

  • 注释张量。这可能不实用,因为您已经说过您无法控制模型,但一个简单的选择是为张量添加额外的属性以表示权重/偏差关系。例如,您可以执行W.bias = BB.weight = W之类的操作,然后在_apply_dense中检查hasattr(weight, "bias")hasattr(weight, "weight")(在这个意义上可能会有一些更好的设计)。
  • 您可以查看构建在TensorFlow之上的一些框架,您可以在其中获得有关模型结构的更好信息。例如,Keras是一个基于层的框架,它实现了自己的optimizer classes(基于TensorFlow或Theano)。我不太熟悉代码或它的可扩展性,但可能你有更多工具可供使用。
  • 自己从优化器中检测网络结构。这很复杂,但理论上可行。从丢失张量传递到优化器,应该可以在模型图中“爬上”以到达其所有节点(采用张量的.op和操作的.inputs 。您可以使用变量检测张量乘法和加法,并跳过其他所有内容(激活,损失计算等)来确定网络的结构;如果模型与您的期望不符(例如,没有乘法或没有后续添加的乘法),您可以引发一个异常,表明您的优化器不能用于该模型。

旧答案,为了保留而保留。

我不是100%清楚你要做什么,所以我不确定这是否真的能回答你的问题。

假设您有一个密集层,将大小为 M 的输入转换为大小为 N 的输出。根据你所展示的惯例,你有 N × M 权重矩阵 W N - 大小的偏向量 B 。然后,大小为 M 的输入向量 X (或一组大小 M × K 的输入)将由图层处理为 W · X + B ,然后应用激活功能(在批处理的情况下,添加将是一个“广播”的行动)。在TensorFlow中:

X = ...  # Input batch of size M x K
W = ...  # Weights of size N x M
B = ...  # Biases of size N

Y = tf.matmul(W, X) + B[:, tf.newaxis]  # Output of size N x K
# Activation...

如果需要,您可以随时将 W B 放在一个扩展权重矩阵 W *中,基本上可以添加 B 作为 W 中的新行,因此 W *将是( N + 1)× M 。然后你只需要在包含常量1的输入向量 X 中添加一个新元素(如果是一个批处理,则为新行),这样你就可以得到 X *大小 N + 1(或( N + 1)× K 批次)。产品 W X *将为您提供与之前相同的结果。在TensorFlow中:

X = ...  # Input batch of size M x K
W_star = ...  # Extended weights of size (N + 1) x M
# You can still have a "view" of the original W and B if you need it
W = W_star[:N]
B = W_star[-1]

X_star = tf.concat([X, tf.ones_like(X[:1])], axis=0)
Y = tf.matmul(W_star, X_star)  # Output of size N x K
# Activation...

现在,您可以一起计算权重和偏差的渐变和更新。这种方法的一个缺点是,如果你想应用正则化,那么你应该小心只将它应用于矩阵的权重部分,而不是偏差。