【问题标题】:Keras multiple inputs maskingKeras 多输入屏蔽
【发布时间】:2021-03-03 21:01:47
【问题描述】:

我正在构建一个具有多个输入的 LSTM 模型(数字由 n_inputs 给出)。我缩放了(0, 1) 中的输入,并用-1 替换了所有NaN 输入。现在我希望模型忽略这样的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 会强制模型完全忽略数据的一个时间步长(我不确定如何检查是否是这种情况)。我想要的是:对于每个时间,只忽略 NaN 输入,但传递其他有效的输入。 我的问题是:Masking 是否排除了至少一个输入为NaN 的所有时间步?如果是这样,我怎样才能让模型只忽略 NaN 输入?

【问题讨论】:

    标签: python keras lstm masking multiple-input


    【解决方案1】:

    好吧,因为我不知道答案并且对此感到好奇,所以我做了一些实验。我首先创建了一个由 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)
    

    【讨论】:

      猜你喜欢
      • 2021-09-18
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 2021-01-04
      • 2013-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多