Keras 不会将模型输出与为整个小批量设计的掩码进行广播相乘
Keras won't broadcast-multiply the model output with a mask designed for the entire mini batch
我有一个数据生成器,可以生成批量输入数据 (X
) 和目标 (Y
),还有一个应用于模型的掩码 (batch_mask
)输出(相同的掩码适用于批次中的所有数据点;不同的批次有不同的掩码,数据生成器负责执行此操作)。
因此,batch_mask
的第一个维度可能具有 1
或 batch_size
的形状(通过沿第一个维度重复相同的掩码 batch_size
次)。我期待 Keras 让我使用其中任何一个,我想简单地创建在第一维上具有 1
形状的蒙版。
但是,当我尝试这样做时,出现错误:
ValueError: Data cardinality is ambiguous:
x sizes: 128, 1
y sizes: 128
Make sure all arrays contain the same number of samples.
为什么Keras不会沿第一维度广播?看来这个应该不复杂。
下面是一些观察此行为的最小示例代码
import tensorflow.keras as tfk
import numpy as np
#######################
# 1. model definition #
#######################
# model parameters
nfeatures_in = 6
target_size = 8
# model inputs
input = tfk.layers.Input(nfeatures_in)
input_mask = tfk.layers.Input(target_size)
# model graph
out = tfk.layers.Dense(target_size)(input)
out_masked = tfk.layers.Multiply()((out,input_mask)) # multiply all model outputs in the batch by the same mask
model = tfk.Model(inputs=(input, input_mask), outputs=out_masked)
##########################
# 2. dummy data creation #
##########################
batch_size = 32
# create masks the batch
zeros_vector = np.zeros((1,target_size)) # "batch_size"==1
zeros_vector[0,:6] = 1
batch_mask = zeros_vector
# dummy data creation
X = np.random.randn(batch_size, 6)
Y = np.random.randn(batch_size, target_size)*batch_mask # the target is masked by design in each batch
############################
# 3. compile model and fit #
############################
model.compile(optimizer="Adam", loss="mse")
model.fit((X, batch_mask),Y, batch_size=batch_size)
我知道我可以通过以下任一方式完成这项工作:
- 重复掩码使
batch_mask
的第一个维度成为 X
的第一个维度的大小(而不是 1)。
- 使用纯 tensorflow(但我觉得沿着批次维度广播对于 Keras 应该不是问题)。
如何使用 Keras 进行这项工作?
谢谢!
您可以创建一个 IdentityLayer
接收作为外部输入参数的 batch_mask
和 returns 它作为张量。
class IdentityLayer(tfk.layers.Layer):
def __init__(self, my_mask, **kwargs):
super(IdentityLayer, self).__init__()
self.my_mask = my_mask
def call(self, _):
my_mask = tf.convert_to_tensor(self.my_mask, dtype=tf.float32)
return my_mask
def get_config(self):
config = super().get_config()
config.update({
"my_mask": self.my_mask,
})
return config
IdentityLayer
在模型中的用法很简单:
# model inputs
input = tfk.layers.Input(nfeatures_in)
input_mask = IdentityLayer(batch_mask)(input)
# model graph
out = tfk.layers.Dense(target_size)(input)
out_masked = tfk.layers.Multiply()((out,input_mask))
model = tfk.Model(inputs=input, outputs=out_masked)
其中 batch_mask
是按照您报告的方式创建的 numpy 数组:
zeros_vector = np.zeros((1,target_size)) # "batch_size"==1
zeros_vector[0,:6] = 1
batch_mask = zeros_vector
解决方案是(正确地)使用 DataGenerator
.
使用工作代码查看要点:https://gist.github.com/iranroman/2aaecf5b5621051df6b1b6b5394e5ef3
感谢 @Marco Cerliani 为找出解决方案而进行的讨论。
我有一个数据生成器,可以生成批量输入数据 (X
) 和目标 (Y
),还有一个应用于模型的掩码 (batch_mask
)输出(相同的掩码适用于批次中的所有数据点;不同的批次有不同的掩码,数据生成器负责执行此操作)。
因此,batch_mask
的第一个维度可能具有 1
或 batch_size
的形状(通过沿第一个维度重复相同的掩码 batch_size
次)。我期待 Keras 让我使用其中任何一个,我想简单地创建在第一维上具有 1
形状的蒙版。
但是,当我尝试这样做时,出现错误:
ValueError: Data cardinality is ambiguous:
x sizes: 128, 1
y sizes: 128
Make sure all arrays contain the same number of samples.
为什么Keras不会沿第一维度广播?看来这个应该不复杂。
下面是一些观察此行为的最小示例代码
import tensorflow.keras as tfk
import numpy as np
#######################
# 1. model definition #
#######################
# model parameters
nfeatures_in = 6
target_size = 8
# model inputs
input = tfk.layers.Input(nfeatures_in)
input_mask = tfk.layers.Input(target_size)
# model graph
out = tfk.layers.Dense(target_size)(input)
out_masked = tfk.layers.Multiply()((out,input_mask)) # multiply all model outputs in the batch by the same mask
model = tfk.Model(inputs=(input, input_mask), outputs=out_masked)
##########################
# 2. dummy data creation #
##########################
batch_size = 32
# create masks the batch
zeros_vector = np.zeros((1,target_size)) # "batch_size"==1
zeros_vector[0,:6] = 1
batch_mask = zeros_vector
# dummy data creation
X = np.random.randn(batch_size, 6)
Y = np.random.randn(batch_size, target_size)*batch_mask # the target is masked by design in each batch
############################
# 3. compile model and fit #
############################
model.compile(optimizer="Adam", loss="mse")
model.fit((X, batch_mask),Y, batch_size=batch_size)
我知道我可以通过以下任一方式完成这项工作:
- 重复掩码使
batch_mask
的第一个维度成为X
的第一个维度的大小(而不是 1)。 - 使用纯 tensorflow(但我觉得沿着批次维度广播对于 Keras 应该不是问题)。
如何使用 Keras 进行这项工作?
谢谢!
您可以创建一个 IdentityLayer
接收作为外部输入参数的 batch_mask
和 returns 它作为张量。
class IdentityLayer(tfk.layers.Layer):
def __init__(self, my_mask, **kwargs):
super(IdentityLayer, self).__init__()
self.my_mask = my_mask
def call(self, _):
my_mask = tf.convert_to_tensor(self.my_mask, dtype=tf.float32)
return my_mask
def get_config(self):
config = super().get_config()
config.update({
"my_mask": self.my_mask,
})
return config
IdentityLayer
在模型中的用法很简单:
# model inputs
input = tfk.layers.Input(nfeatures_in)
input_mask = IdentityLayer(batch_mask)(input)
# model graph
out = tfk.layers.Dense(target_size)(input)
out_masked = tfk.layers.Multiply()((out,input_mask))
model = tfk.Model(inputs=input, outputs=out_masked)
其中 batch_mask
是按照您报告的方式创建的 numpy 数组:
zeros_vector = np.zeros((1,target_size)) # "batch_size"==1
zeros_vector[0,:6] = 1
batch_mask = zeros_vector
解决方案是(正确地)使用 DataGenerator
.
使用工作代码查看要点:https://gist.github.com/iranroman/2aaecf5b5621051df6b1b6b5394e5ef3
感谢 @Marco Cerliani 为找出解决方案而进行的讨论。