Keras多输入掩码

1wnzp6jl  于 2023-11-19  发布在  其他
关注(0)|答案(2)|浏览(119)

我正在构建一个具有多个输入的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输入?

aoyhnmkz

aoyhnmkz1#

好吧,因为我不知道答案,也很好奇,我做了一些实验。我首先创建了一个由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层,因为它支持掩码,可以更好地理解发生了什么,但过程与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,以便将无限个值放在你想要屏蔽输入的地方。然后将其添加到Tensor中。一个简单的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)

qmb5sa22

qmb5sa222#

我通过创建一个可分离的掩蔽层来解决这个问题,该掩蔽层独立地作用于每个通道。

import TensorFlow.keras.layers as tfl
class SeperableMaskingLayer(tfl.Layer):
def __init__(self, masking_value, time_steps) -> None:
    super(SeperableMaskingLayer, self).__init__()
    self.masking_layers = [tfl.Masking(mask_value=masking_value) for _ in range(time_steps)]
    self.squeeze = tfl.Lambda(lambda x: tf.squeeze(x, axis=1))

def call(self, inputs):
    outputs = []
    for i,x in enumerate(tf.split(inputs, num_or_size_splits=len(self.masking_layers), axis=1)):
        x = self.squeeze(x)
        outputs.append(self.masking_layers[i](x))
    return tf.stack(outputs, axis=1)

字符串

相关问题