在 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优化器)
最佳答案
更新:既然我对您的目标有了一些了解,我会尝试给出更好的答案(或至少一些想法),但是,正如您在评论中建议的那样,可能在 TensorFlow 中执行此操作并非万无一失。
由于 TF 是一个通用的计算框架,因此没有很好的方法来确定模型中有哪些权重和偏差对(或者它是否是一个神经网络)。以下是我能想到的解决该问题的一些可能方法:
- 注释张量。这可能不切实际,因为您已经说过您无法控制模型,但一个简单的选择是向张量添加额外的属性以表示权重/偏差关系。例如,您可以执行类似
W.bias = B
和B.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。然后,您只需向输入向量 X 添加一个新元素,其中包含常量 1(如果是批处理,则添加一个新行),这样您就可以得到 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...
现在您可以一起计算权重和偏差的梯度和更新。这种方法的一个缺点是,如果您想应用正则化,那么您应该小心地将其仅应用于矩阵的权重部分,而不是偏差。
关于python - 如何在优化器中获得偏差和神经元权重?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45015709/