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
与 inputs
和 custom_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)
我正在构建一个具有多个输入的 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
与 inputs
和 custom_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)