【问题标题】:How to get bias and neuron weights in optimizer?如何在优化器中获得偏差和神经元权重?
【发布时间】:2017-12-14 09:42:04
【问题描述】:

在 TensorFlow 优化器 (python) 中,方法 apply_dense 确实会为神经元权重(层连接)和偏置权重调用,但我想在此方法中同时使用这两种方法。

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

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

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

并呼吁偏置权重:

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

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 优化器)

【问题讨论】:

  • 您需要更加明确。你叫什么方法?你能给我们一个最小的工作示例吗?
  • 我正在实现一个优化器。我已经添加了这样一个优化器的 MWE,并根据我的问题描述了需求。
  • 我不明白你在问什么。您是在问如何获得网络中的权重?
  • @RyanStout:不。我正在编写一个优化器,并希望同时访问优化器的 apply_dense 方法中的神经元和偏置权重。
  • 你是说 _apply_dense 被调用了两次,一次是将权重矩阵传递给名为“weight”的参数,一次将偏置向量传递给名为“weight”的参数?我想我也没有理解为什么你的问题中有 weights=[[B_1*X_4],[B_2*X_5]]。

标签: python tensorflow


【解决方案1】:

更新:既然我对您的目标有所了解,我会尝试给出更好的答案(或至少一些想法),但是,正如您在 cmets 中建议的那样,可能有在 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...

如果你愿意,你可以随时将 WB 放在一个扩展权重矩阵 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...

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

【讨论】:

  • 感谢您尝试回答我的问题。可悲的是,您是对的,这不是我问题的实际答案。我试图解决的问题是,从优化器的角度来看,我无法控制网络的外观。所以给定 Y = tf.matmul(W, X) + B 我仍然想在一次 apply_dense 调用中使用 W 和 B。我的问题的答案只能来自优化器的角度,而不是像你的答案那样来自外部。限制是我只能更改优化器而不是网络。
  • @Spen 好的,我已经查看了基本优化器类,并且看到了您现在想要做的那种事情。但是我还是不明白,如果你不能控制模型的样子,你怎么能保证真的会有偏差呢?或者模型根本就是一个神经网络?在 TF 中,bias 和 wieghts 将只是两个独立变量对象,如果您无法控制模型,我不确定您如何知道哪些是 weights 和 biases 对。
  • 是的,我也看到了这个问题。我只是认为相应的权重和偏差是一个给定的,并且权重矩阵的维度为 2,而偏差矩阵的维度为 1。但也许你是对的,没有保存在张量流中做到这一点的方法。在其他框架中,这是可能的,因为您可以访问整个网络,但在 tensorflow 中,这种访问似乎是不可能的。由于赏金快用完了,而你是唯一一个试图帮助的人,我会把它奖励给你。
  • @Spen 你真是太好了,谢谢 :) 我已经用一些更好的建议更新了答案,尽管就像你说的那样,可能没有直接的解决方案。
猜你喜欢
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 2018-03-01
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2018-10-20
相关资源
最近更新 更多