如何将可训练权重的张量添加到 Keras 张量?
How to add a tensor of trainable weights to a Keras tensor?
根据 https://arxiv.org/pdf/1503.08895.pdf 第 5 页的 "Temporal Encoding" 部分(顺便说一下,这是一篇优秀的论文),我说了 N 维 M 的嵌入向量。所以我的 Keras 张量是(批量大小, N, M) 并且我想将一个 N 乘 M 的权重矩阵添加到每个批量大小的样本中。为此,我创建了自己的 Keras 层:
from constants import BATCH_SIZE
class Added_Weights(Layer):
def __init__(self, input_dim, output_dim, **kwargs):
self.output_dim = output_dim
self.input_dim = input_dim
super(Added_Weights, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=(BATCH_SIZE, self.input_dim[0], self.input_dim[1]),
initializer=RandomNormal(mean=0., stddev=0.05, seed=None),
trainable=True)
print("kernel has shape "+self.kernel.shape + " or "+K.int_shape(self.kernel))
super(Added_Weights, self).build(input_shape)
def call(self, x, **kwargs):
return Add()([x, self.kernel])
def compute_output_shape(self, input_shape):
return (BATCH_SIZE, self.input_dim[0], self.input_dim[1])
这可行,但问题是 BATCH_SIZE 许多矩阵中的每一个都具有不同的权重。我需要为批次中的每个样本添加相同的权重。
所以我尝试了一些东西。 Keras 有一个内置的 RepeatVector 层,所以我尝试给内核形状 (N, M) 并做 RepeatVector (BATCH_SIZE)(kernel),但由于某种原因最终以形状 (N, BATCH_SIZE, M).我想在那里使用 Reshape,但 Reshape() 将第一个维度视为 batch_size 并且不允许我修改它。 Permute() 也有同样的问题。
另一个想法是使初始形状与代码中的一样,然后遍历张量以将切片 1 到 BATCH_SIZE-1 设置为等于切片 0,因此它们都持有相同的权重,但不允许我以这种方式为 Keras 张量赋值。
我唯一的其他想法就是尝试使用形状 (N, M) 并希望 Keras 足够聪明,可以将它添加到输入的每个切片中,但是在将 Add() 应用于我的 ( ?, N, M) 和 (N, M) 内核,不知何故我得到了一个 (N, N, M) 张量,此时我们已经死了。
我认为你把事情复杂化了。只需将权重定义为 build
中的 N x M 张量,然后与 call
中的输入张量求和。我按如下方式调整了您的代码:
from keras.engine.topology import Layer
from keras.models import Model
from keras.layers import Input
import numpy as np
N = 3
M = 4
BATCH_SIZE = 1
class Added_Weights(Layer):
def __init__(self, **kwargs):
super(Added_Weights, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=(input_shape[1], input_shape[2]),
initializer='ones', # TODO: Choose your initializer
trainable=True)
super(Added_Weights, self).build(input_shape)
def call(self, x, **kwargs):
# Implicit broadcasting occurs here.
# Shape x: (BATCH_SIZE, N, M)
# Shape kernel: (N, M)
# Shape output: (BATCH_SIZE, N, M)
return x + self.kernel
def compute_output_shape(self, input_shape):
return input_shape
a = Input(shape=(N, M))
layer = Added_Weights()(a)
model = Model(inputs=a,
outputs=layer)
a = np.zeros(shape=(BATCH_SIZE, N, M))
pred = model.predict(a)
print(pred)
请注意,self.kernel
在 call
中被隐式广播以匹配 x
的形状,因此相同的权重被添加到批次中的每个样本。
根据 https://arxiv.org/pdf/1503.08895.pdf 第 5 页的 "Temporal Encoding" 部分(顺便说一下,这是一篇优秀的论文),我说了 N 维 M 的嵌入向量。所以我的 Keras 张量是(批量大小, N, M) 并且我想将一个 N 乘 M 的权重矩阵添加到每个批量大小的样本中。为此,我创建了自己的 Keras 层:
from constants import BATCH_SIZE
class Added_Weights(Layer):
def __init__(self, input_dim, output_dim, **kwargs):
self.output_dim = output_dim
self.input_dim = input_dim
super(Added_Weights, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=(BATCH_SIZE, self.input_dim[0], self.input_dim[1]),
initializer=RandomNormal(mean=0., stddev=0.05, seed=None),
trainable=True)
print("kernel has shape "+self.kernel.shape + " or "+K.int_shape(self.kernel))
super(Added_Weights, self).build(input_shape)
def call(self, x, **kwargs):
return Add()([x, self.kernel])
def compute_output_shape(self, input_shape):
return (BATCH_SIZE, self.input_dim[0], self.input_dim[1])
这可行,但问题是 BATCH_SIZE 许多矩阵中的每一个都具有不同的权重。我需要为批次中的每个样本添加相同的权重。
所以我尝试了一些东西。 Keras 有一个内置的 RepeatVector 层,所以我尝试给内核形状 (N, M) 并做 RepeatVector (BATCH_SIZE)(kernel),但由于某种原因最终以形状 (N, BATCH_SIZE, M).我想在那里使用 Reshape,但 Reshape() 将第一个维度视为 batch_size 并且不允许我修改它。 Permute() 也有同样的问题。
另一个想法是使初始形状与代码中的一样,然后遍历张量以将切片 1 到 BATCH_SIZE-1 设置为等于切片 0,因此它们都持有相同的权重,但不允许我以这种方式为 Keras 张量赋值。
我唯一的其他想法就是尝试使用形状 (N, M) 并希望 Keras 足够聪明,可以将它添加到输入的每个切片中,但是在将 Add() 应用于我的 ( ?, N, M) 和 (N, M) 内核,不知何故我得到了一个 (N, N, M) 张量,此时我们已经死了。
我认为你把事情复杂化了。只需将权重定义为 build
中的 N x M 张量,然后与 call
中的输入张量求和。我按如下方式调整了您的代码:
from keras.engine.topology import Layer
from keras.models import Model
from keras.layers import Input
import numpy as np
N = 3
M = 4
BATCH_SIZE = 1
class Added_Weights(Layer):
def __init__(self, **kwargs):
super(Added_Weights, self).__init__(**kwargs)
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=(input_shape[1], input_shape[2]),
initializer='ones', # TODO: Choose your initializer
trainable=True)
super(Added_Weights, self).build(input_shape)
def call(self, x, **kwargs):
# Implicit broadcasting occurs here.
# Shape x: (BATCH_SIZE, N, M)
# Shape kernel: (N, M)
# Shape output: (BATCH_SIZE, N, M)
return x + self.kernel
def compute_output_shape(self, input_shape):
return input_shape
a = Input(shape=(N, M))
layer = Added_Weights()(a)
model = Model(inputs=a,
outputs=layer)
a = np.zeros(shape=(BATCH_SIZE, N, M))
pred = model.predict(a)
print(pred)
请注意,self.kernel
在 call
中被隐式广播以匹配 x
的形状,因此相同的权重被添加到批次中的每个样本。