Keras 多输入掩码

Keras multiple inputs masking

我正在构建一个具有多个输入的 LSTM 模型(数字由 n_inputs 给出)。我缩放了 (0, 1) 中的输入,并将输入的所有 NaN 替换为 -1。现在我希望模型忽略这样的 NaN 值,因此我使用如下掩码:

model= Sequential()
model.add(Masking(mask_value=-1, input_shape=(window, n_inputs)))
model.add(LSTM(units=n_units), return_sequences=True)
model.add(Dropout(dropout_rate))
model.add(LSTM(units=n_units))
model.add(Dropout(dropout_rate))
model.add(Dense(units=1))

恐怕如果任何输入具有 NaN 值,Masking 会强制模型完全忽略数据的一个时间步长(我不确定如何检查是否是这种情况).但我想要的是:对于每个 timestemp,仅忽略 NaN 输入,但传递其他有效输入。 我的问题是:Masking 是否排除了至少一个输入为 NaN 的所有时间步长?如果是这样,我怎样才能让模型只忽略 NaN 输入?

好吧,因为我不知道答案并且对此很好奇,所以我做了一些实验。我首先创建了一个由 3 个时间步长和 3 个特征组成的序列:

inputs = np.ones([1, 3, 3]).astype(np.float32)

我创建了一个简单的网络,我在其中打印了两个中间层:

inp = tf.keras.layers.Input(shape=(3,3))
mask=tf.keras.layers.Masking(mask_value=-np.inf)(inp)
out=tf.keras.layers.Dense(1,
                           kernel_initializer=tf.keras.initializers.Ones(),
                           use_bias=False)(mask)

model_mask=tf.keras.models.Model(inp,mask)
model=tf.keras.models.Model(inp,out)
print(model_mask(inputs))
print(model(inputs))

我使用了 Dense 层,因为它支持 Masking 并且可以更好地理解正在发生的事情,但过程与 RNN 相同。我还选择将掩码值设置为 -inf 以查看掩码值是否被很好地掩码。 Dense 层的权重设置为 1 并且我禁用了偏差,因此该 Dense 层计算每个时间步长的输入总和。

如果我屏蔽时间步长的所有输入:

inputs[0, 2, :] = -np.inf

这就是我所拥有的:

tf.Tensor(
[[[ 1.  1.  1.]
  [ 1.  1.  1.]
  [nan nan nan]]], shape=(1, 3, 3), dtype=float32)
tf.Tensor(
[[[ 3.]
  [ 3.]
  [nan]]], shape=(1, 3, 1), dtype=float32)

因此正确考虑了掩码。

如果我想屏蔽一个值 :

inputs[0, 2, 0] = -np.inf

我的输出是:

tf.Tensor(
[[[  1.   1.   1.]
  [  1.   1.   1.]
  [-inf   1.   1.]]], shape=(1, 3, 3), dtype=float32)
tf.Tensor(
[[[  3.]
  [  3.]
  [-inf]]], shape=(1, 3, 1), dtype=float32)

所以我得出结论,屏蔽没有被处理。

您应该创建自己的面具。

我尝试了一个小例子,所以我希望这个例子可以用于你的项目。首先,我忘记了 keras 的 Vanilla Masking 层来使用我自己的遮罩。这个想法是创建一个掩码,将 1 放在掩码值上,将 0 放在实际值上。例如,如果您的值优于 0,则将 Nan 值替换为 -1 并创建 custom_mask:

inputs = np.array([[[1,2,1],[0.5,2,1],[1,0,3]]],dtype=np.float32)

inputs[:,1,0]=-1
inputs[:,2,2]=-1

custom_mask=inputs.copy()
custom_mask[inputs[:,:,:]>=0]=0
custom_mask[inputs[:,:,:]<0]=1

inputscustom_mask 分别为:

[[[ 1.  2.  1.]
  [-1.  2.  1.]
  [ 1.  0. -1.]]]
[[[0. 0. 0.]
  [1. 0. 0.]
  [0. 0. 1.]]]

然后,您将掩码乘以 -1E9,以便在您想要掩码输入的地方放置无限值。然后将其添加到张量中。一个简单的 ReLu 将屏蔽值设置为 0 :

inp = tf.keras.layers.Input(shape=(3,3))
input_mask=tf.keras.activations.relu(inp-custom_mask*1E9)
out=tf.keras.layers.Dense(1,
                           kernel_initializer=tf.keras.initializers.Ones(),
                           use_bias=False)(input_mask)

model=tf.keras.models.Model(inp,out)
print(model(inputs))

等于:

tf.Tensor(
[[[4.]
  [3.]
  [1.]]], shape=(1, 3, 1), dtype=float32)