如何使用 TensorFlow 后端屏蔽 Keras 中的损失函数?
How do I mask a loss function in Keras with the TensorFlow backend?
我正在尝试使用 Keras 的 LSTM 和 TensorFlow 后端来实现一个序列到序列的任务。输入是长度可变的英语句子。为了构建具有二维形状 [batch_number, max_sentence_length]
的数据集,我在行尾添加 EOF
并用足够的占位符填充每个句子,例如#
。然后将句子中的每个字符转换为一个单热向量,使数据集具有 3-D 形状 [batch_number, max_sentence_length, character_number]
。在 LSTM 编码器和解码器层之后,计算输出和目标之间的 softmax 交叉熵。
为了消除模型训练中的填充效应,可以对输入和损失函数使用掩码。 Keras 中的 Mask 输入可以使用 layers.core.Masking
来完成。在 TensorFlow 中,可以按如下方式对损失函数进行掩码:custom masked loss function in TensorFlow.
但是,我找不到在 Keras 中实现它的方法,因为 Keras 中的用户定义损失函数只接受参数 y_true
和 y_pred
。那么损失函数和mask怎么输入truesequence_lengths
呢?
此外,我在\keras\engine\training.py
中找到一个函数_weighted_masked_objective(fn)
。它的定义是
Adds support for masking and sample-weighting to an objective function.
但是函数好像只能接受fn(y_true, y_pred)
。有没有办法使用这个功能来解决我的问题?
具体的,我修改了Yu-Yang的例子
from keras.models import Model
from keras.layers import Input, Masking, LSTM, Dense, RepeatVector, TimeDistributed, Activation
import numpy as np
from numpy.random import seed as random_seed
random_seed(123)
max_sentence_length = 5
character_number = 3 # valid character 'a, b' and placeholder '#'
input_tensor = Input(shape=(max_sentence_length, character_number))
masked_input = Masking(mask_value=0)(input_tensor)
encoder_output = LSTM(10, return_sequences=False)(masked_input)
repeat_output = RepeatVector(max_sentence_length)(encoder_output)
decoder_output = LSTM(10, return_sequences=True)(repeat_output)
output = Dense(3, activation='softmax')(decoder_output)
model = Model(input_tensor, output)
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()
X = np.array([[[0, 0, 0], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0]],
[[0, 0, 0], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0]]])
y_true = np.array([[[0, 0, 1], [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 1, 0]], # the batch is ['##abb','#babb'], padding '#'
[[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0]]])
y_pred = model.predict(X)
print('y_pred:', y_pred)
print('y_true:', y_true)
print('model.evaluate:', model.evaluate(X, y_true))
# See if the loss computed by model.evaluate() is equal to the masked loss
import tensorflow as tf
logits=tf.constant(y_pred, dtype=tf.float32)
target=tf.constant(y_true, dtype=tf.float32)
cross_entropy = tf.reduce_mean(-tf.reduce_sum(target * tf.log(logits),axis=2))
losses = -tf.reduce_sum(target * tf.log(logits),axis=2)
sequence_lengths=tf.constant([3,4])
mask = tf.reverse(tf.sequence_mask(sequence_lengths,maxlen=max_sentence_length),[0,1])
losses = tf.boolean_mask(losses, mask)
masked_loss = tf.reduce_mean(losses)
with tf.Session() as sess:
c_e = sess.run(cross_entropy)
m_c_e=sess.run(masked_loss)
print("tf unmasked_loss:", c_e)
print("tf masked_loss:", m_c_e)
Keras和TensorFlow中的输出对比如下:
如上所示,在某些层之后禁用了遮罩。那么如何在添加这些层时屏蔽 Keras 中的损失函数呢?
如果你没有像Yu-Yang的回答那样使用口罩,你可以试试这个。
如果您的目标数据 Y
具有长度并填充了掩码值,您可以:
import keras.backend as K
def custom_loss(yTrue,yPred):
#find which values in yTrue (target) are the mask value
isMask = K.equal(yTrue, maskValue) #true for all mask values
#since y is shaped as (batch, length, features), we need all features to be mask values
isMask = K.all(isMask, axis=-1) #the entire output vector must be true
#this second line is only necessary if the output features are more than 1
#transform to float (0 or 1) and invert
isMask = K.cast(isMask, dtype=K.floatx())
isMask = 1 - isMask #now mask values are zero, and others are 1
#multiply this by the inputs:
#maybe you might need K.expand_dims(isMask) to add the extra dimension removed by K.all
yTrue = yTrue * isMask
yPred = yPred * isMask
return someLossFunction(yTrue,yPred)
如果你只对输入数据进行填充,或者如果 Y 没有长度,你可以在函数外有自己的掩码:
masks = [
[1,1,1,1,1,1,0,0,0],
[1,1,1,1,0,0,0,0,0],
[1,1,1,1,1,1,1,1,0]
]
#shape (samples, length). If it fails, make it (samples, length, 1).
import keras.backend as K
masks = K.constant(masks)
由于掩码取决于您的输入数据,您可以使用您的掩码值来了解在何处放置零,例如:
masks = np.array((X_train == maskValue).all(), dtype='float64')
masks = 1 - masks
#here too, if you have a problem with dimensions in the multiplications below
#expand masks dimensions by adding a last dimension = 1.
并让您的函数从外部获取掩码(如果您更改输入数据,则必须重新创建损失函数):
def customLoss(yTrue,yPred):
yTrue = masks*yTrue
yPred = masks*yPred
return someLossFunction(yTrue,yPred)
有谁知道keras是否自动屏蔽了损失函数??
由于它提供了一个掩蔽层并且对输出没有任何说明,也许它会自动完成?
如果您的模型中有掩码,它将逐层传播并最终应用于损失。因此,如果您以正确的方式填充和屏蔽序列,填充占位符上的损失将被忽略。
一些细节:
解释整个过程有点复杂,所以我将其分解为几个步骤:
- 在
compile()
中,通过调用 compute_mask()
收集掩码并将其应用于损失(为清楚起见,忽略不相关的行)。
weighted_losses = [_weighted_masked_objective(fn) for fn in loss_functions]
# Prepare output masks.
masks = self.compute_mask(self.inputs, mask=None)
if masks is None:
masks = [None for _ in self.outputs]
if not isinstance(masks, list):
masks = [masks]
# Compute total loss.
total_loss = None
with K.name_scope('loss'):
for i in range(len(self.outputs)):
y_true = self.targets[i]
y_pred = self.outputs[i]
weighted_loss = weighted_losses[i]
sample_weight = sample_weights[i]
mask = masks[i]
with K.name_scope(self.output_names[i] + '_loss'):
output_loss = weighted_loss(y_true, y_pred,
sample_weight, mask)
- 在
Model.compute_mask()
里面,调用了run_internal_graph()
。
- 在
run_internal_graph()
内部,通过对每一层迭代调用 Layer.compute_mask()
,模型中的蒙版从模型的输入逐层传播到输出。
因此,如果您在模型中使用 Masking
层,则不必担心填充占位符的丢失。正如您可能已经在 _weighted_masked_objective()
.
中看到的那样,这些条目的损失将被掩盖
一个小例子:
max_sentence_length = 5
character_number = 2
input_tensor = Input(shape=(max_sentence_length, character_number))
masked_input = Masking(mask_value=0)(input_tensor)
output = LSTM(3, return_sequences=True)(masked_input)
model = Model(input_tensor, output)
model.compile(loss='mae', optimizer='adam')
X = np.array([[[0, 0], [0, 0], [1, 0], [0, 1], [0, 1]],
[[0, 0], [0, 1], [1, 0], [0, 1], [0, 1]]])
y_true = np.ones((2, max_sentence_length, 3))
y_pred = model.predict(X)
print(y_pred)
[[[ 0. 0. 0. ]
[ 0. 0. 0. ]
[-0.11980877 0.05803877 0.07880752]
[-0.00429189 0.13382857 0.19167568]
[ 0.06817091 0.19093043 0.26219055]]
[[ 0. 0. 0. ]
[ 0.0651961 0.10283815 0.12413475]
[-0.04420842 0.137494 0.13727818]
[ 0.04479844 0.17440712 0.24715884]
[ 0.11117355 0.21645413 0.30220413]]]
# See if the loss computed by model.evaluate() is equal to the masked loss
unmasked_loss = np.abs(1 - y_pred).mean()
masked_loss = np.abs(1 - y_pred[y_pred != 0]).mean()
print(model.evaluate(X, y_true))
0.881977558136
print(masked_loss)
0.881978
print(unmasked_loss)
0.917384
从这个例子可以看出,屏蔽部分(y_pred
中的零)的损失被忽略,model.evaluate()
的输出等于masked_loss
。
编辑:
如果存在 return_sequences=False
的循环层,掩码停止传播(即返回的掩码为 None
)。在 RNN.compute_mask()
:
def compute_mask(self, inputs, mask):
if isinstance(mask, list):
mask = mask[0]
output_mask = mask if self.return_sequences else None
if self.return_state:
state_mask = [None for _ in self.states]
return [output_mask] + state_mask
else:
return output_mask
在你的情况下,如果我理解正确,你想要一个基于 y_true
的掩码,并且只要 y_true
的值是 [0, 0, 1]
( "#") 您希望掩盖损失。如果是这样,您需要以类似于 Daniel 的回答的方式来掩盖损失值。
主要区别在于最终平均值。平均值应接管未屏蔽值的数量,即 K.sum(mask)
。而且,y_true
可以直接与 one-hot 编码向量 [0, 0, 1]
进行比较。
def get_loss(mask_value):
mask_value = K.variable(mask_value)
def masked_categorical_crossentropy(y_true, y_pred):
# find out which timesteps in `y_true` are not the padding character '#'
mask = K.all(K.equal(y_true, mask_value), axis=-1)
mask = 1 - K.cast(mask, K.floatx())
# multiply categorical_crossentropy with the mask
loss = K.categorical_crossentropy(y_true, y_pred) * mask
# take average w.r.t. the number of unmasked entries
return K.sum(loss) / K.sum(mask)
return masked_categorical_crossentropy
masked_categorical_crossentropy = get_loss(np.array([0, 0, 1]))
model = Model(input_tensor, output)
model.compile(loss=masked_categorical_crossentropy, optimizer='adam')
以上代码的输出显示损失仅在未屏蔽的值上计算:
model.evaluate: 1.08339476585
tf unmasked_loss: 1.08989
tf masked_loss: 1.08339
该值与您的不同,因为我已将 tf.reverse
中的 axis
参数从 [0,1]
更改为 [1]
。
我接受了两个答案,并为多个时间步、单个缺失目标值、LSTM(或其他 RecurrentNN)的损失改进了一种方法 return_sequences=True。
由于 isMask = K.all(isMask, axis=-1)
,Daniels 的回答对于多个目标来说是不够的。删除这个聚合可能会使函数不可微分。我不确定,因为我从来没有 运行 纯函数,也不知道它是否适合模型。
我将 Yu-Yangs 和 Daniels 的答案融合在一起,它奏效了。
from tensorflow.keras.layers import Layer, Input, LSTM, Dense, TimeDistributed
from tensorflow.keras import Model, Sequential
import tensorflow.keras.backend as K
import numpy as np
mask_Value = -2
def get_loss(mask_value):
mask_value = K.variable(mask_value)
def masked_loss(yTrue,yPred):
#find which values in yTrue (target) are the mask value
isMask = K.equal(yTrue, mask_Value) #true for all mask values
#transform to float (0 or 1) and invert
isMask = K.cast(isMask, dtype=K.floatx())
isMask = 1 - isMask #now mask values are zero, and others are 1
isMask
#multiply this by the inputs:
#maybe you might need K.expand_dims(isMask) to add the extra dimension removed by K.all
yTrue = yTrue * isMask
yPred = yPred * isMask
# perform a root mean square error, whereas the mean is in respect to the mask
mean_loss = K.sum(K.square(yPred - yTrue))/K.sum(isMask)
loss = K.sqrt(mean_loss)
return loss
#RootMeanSquaredError()(yTrue,yPred)
return masked_loss
# define timeseries data
n_sample = 10
timesteps = 5
feat_inp = 2
feat_out = 2
X = np.random.uniform(0,1, (n_sample, timesteps, feat_inp))
y = np.random.uniform(0,1, (n_sample,timesteps, feat_out))
# define model
model = Sequential()
model.add(LSTM(50, activation='relu',return_sequences=True, input_shape=(timesteps, feat_inp)))
model.add(Dense(feat_out))
model.compile(optimizer='adam', loss=get_loss(mask_Value))
model.summary()
# %%
model.fit(X, y, epochs=50, verbose=0)
我正在尝试使用 Keras 的 LSTM 和 TensorFlow 后端来实现一个序列到序列的任务。输入是长度可变的英语句子。为了构建具有二维形状 [batch_number, max_sentence_length]
的数据集,我在行尾添加 EOF
并用足够的占位符填充每个句子,例如#
。然后将句子中的每个字符转换为一个单热向量,使数据集具有 3-D 形状 [batch_number, max_sentence_length, character_number]
。在 LSTM 编码器和解码器层之后,计算输出和目标之间的 softmax 交叉熵。
为了消除模型训练中的填充效应,可以对输入和损失函数使用掩码。 Keras 中的 Mask 输入可以使用 layers.core.Masking
来完成。在 TensorFlow 中,可以按如下方式对损失函数进行掩码:custom masked loss function in TensorFlow.
但是,我找不到在 Keras 中实现它的方法,因为 Keras 中的用户定义损失函数只接受参数 y_true
和 y_pred
。那么损失函数和mask怎么输入truesequence_lengths
呢?
此外,我在\keras\engine\training.py
中找到一个函数_weighted_masked_objective(fn)
。它的定义是
Adds support for masking and sample-weighting to an objective function.
但是函数好像只能接受fn(y_true, y_pred)
。有没有办法使用这个功能来解决我的问题?
具体的,我修改了Yu-Yang的例子
from keras.models import Model
from keras.layers import Input, Masking, LSTM, Dense, RepeatVector, TimeDistributed, Activation
import numpy as np
from numpy.random import seed as random_seed
random_seed(123)
max_sentence_length = 5
character_number = 3 # valid character 'a, b' and placeholder '#'
input_tensor = Input(shape=(max_sentence_length, character_number))
masked_input = Masking(mask_value=0)(input_tensor)
encoder_output = LSTM(10, return_sequences=False)(masked_input)
repeat_output = RepeatVector(max_sentence_length)(encoder_output)
decoder_output = LSTM(10, return_sequences=True)(repeat_output)
output = Dense(3, activation='softmax')(decoder_output)
model = Model(input_tensor, output)
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()
X = np.array([[[0, 0, 0], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0]],
[[0, 0, 0], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0]]])
y_true = np.array([[[0, 0, 1], [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 1, 0]], # the batch is ['##abb','#babb'], padding '#'
[[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0]]])
y_pred = model.predict(X)
print('y_pred:', y_pred)
print('y_true:', y_true)
print('model.evaluate:', model.evaluate(X, y_true))
# See if the loss computed by model.evaluate() is equal to the masked loss
import tensorflow as tf
logits=tf.constant(y_pred, dtype=tf.float32)
target=tf.constant(y_true, dtype=tf.float32)
cross_entropy = tf.reduce_mean(-tf.reduce_sum(target * tf.log(logits),axis=2))
losses = -tf.reduce_sum(target * tf.log(logits),axis=2)
sequence_lengths=tf.constant([3,4])
mask = tf.reverse(tf.sequence_mask(sequence_lengths,maxlen=max_sentence_length),[0,1])
losses = tf.boolean_mask(losses, mask)
masked_loss = tf.reduce_mean(losses)
with tf.Session() as sess:
c_e = sess.run(cross_entropy)
m_c_e=sess.run(masked_loss)
print("tf unmasked_loss:", c_e)
print("tf masked_loss:", m_c_e)
Keras和TensorFlow中的输出对比如下:
如上所示,在某些层之后禁用了遮罩。那么如何在添加这些层时屏蔽 Keras 中的损失函数呢?
如果你没有像Yu-Yang的回答那样使用口罩,你可以试试这个。
如果您的目标数据 Y
具有长度并填充了掩码值,您可以:
import keras.backend as K
def custom_loss(yTrue,yPred):
#find which values in yTrue (target) are the mask value
isMask = K.equal(yTrue, maskValue) #true for all mask values
#since y is shaped as (batch, length, features), we need all features to be mask values
isMask = K.all(isMask, axis=-1) #the entire output vector must be true
#this second line is only necessary if the output features are more than 1
#transform to float (0 or 1) and invert
isMask = K.cast(isMask, dtype=K.floatx())
isMask = 1 - isMask #now mask values are zero, and others are 1
#multiply this by the inputs:
#maybe you might need K.expand_dims(isMask) to add the extra dimension removed by K.all
yTrue = yTrue * isMask
yPred = yPred * isMask
return someLossFunction(yTrue,yPred)
如果你只对输入数据进行填充,或者如果 Y 没有长度,你可以在函数外有自己的掩码:
masks = [
[1,1,1,1,1,1,0,0,0],
[1,1,1,1,0,0,0,0,0],
[1,1,1,1,1,1,1,1,0]
]
#shape (samples, length). If it fails, make it (samples, length, 1).
import keras.backend as K
masks = K.constant(masks)
由于掩码取决于您的输入数据,您可以使用您的掩码值来了解在何处放置零,例如:
masks = np.array((X_train == maskValue).all(), dtype='float64')
masks = 1 - masks
#here too, if you have a problem with dimensions in the multiplications below
#expand masks dimensions by adding a last dimension = 1.
并让您的函数从外部获取掩码(如果您更改输入数据,则必须重新创建损失函数):
def customLoss(yTrue,yPred):
yTrue = masks*yTrue
yPred = masks*yPred
return someLossFunction(yTrue,yPred)
有谁知道keras是否自动屏蔽了损失函数?? 由于它提供了一个掩蔽层并且对输出没有任何说明,也许它会自动完成?
如果您的模型中有掩码,它将逐层传播并最终应用于损失。因此,如果您以正确的方式填充和屏蔽序列,填充占位符上的损失将被忽略。
一些细节:
解释整个过程有点复杂,所以我将其分解为几个步骤:
- 在
compile()
中,通过调用compute_mask()
收集掩码并将其应用于损失(为清楚起见,忽略不相关的行)。
weighted_losses = [_weighted_masked_objective(fn) for fn in loss_functions]
# Prepare output masks.
masks = self.compute_mask(self.inputs, mask=None)
if masks is None:
masks = [None for _ in self.outputs]
if not isinstance(masks, list):
masks = [masks]
# Compute total loss.
total_loss = None
with K.name_scope('loss'):
for i in range(len(self.outputs)):
y_true = self.targets[i]
y_pred = self.outputs[i]
weighted_loss = weighted_losses[i]
sample_weight = sample_weights[i]
mask = masks[i]
with K.name_scope(self.output_names[i] + '_loss'):
output_loss = weighted_loss(y_true, y_pred,
sample_weight, mask)
- 在
Model.compute_mask()
里面,调用了run_internal_graph()
。 - 在
run_internal_graph()
内部,通过对每一层迭代调用Layer.compute_mask()
,模型中的蒙版从模型的输入逐层传播到输出。
因此,如果您在模型中使用 Masking
层,则不必担心填充占位符的丢失。正如您可能已经在 _weighted_masked_objective()
.
一个小例子:
max_sentence_length = 5
character_number = 2
input_tensor = Input(shape=(max_sentence_length, character_number))
masked_input = Masking(mask_value=0)(input_tensor)
output = LSTM(3, return_sequences=True)(masked_input)
model = Model(input_tensor, output)
model.compile(loss='mae', optimizer='adam')
X = np.array([[[0, 0], [0, 0], [1, 0], [0, 1], [0, 1]],
[[0, 0], [0, 1], [1, 0], [0, 1], [0, 1]]])
y_true = np.ones((2, max_sentence_length, 3))
y_pred = model.predict(X)
print(y_pred)
[[[ 0. 0. 0. ]
[ 0. 0. 0. ]
[-0.11980877 0.05803877 0.07880752]
[-0.00429189 0.13382857 0.19167568]
[ 0.06817091 0.19093043 0.26219055]]
[[ 0. 0. 0. ]
[ 0.0651961 0.10283815 0.12413475]
[-0.04420842 0.137494 0.13727818]
[ 0.04479844 0.17440712 0.24715884]
[ 0.11117355 0.21645413 0.30220413]]]
# See if the loss computed by model.evaluate() is equal to the masked loss
unmasked_loss = np.abs(1 - y_pred).mean()
masked_loss = np.abs(1 - y_pred[y_pred != 0]).mean()
print(model.evaluate(X, y_true))
0.881977558136
print(masked_loss)
0.881978
print(unmasked_loss)
0.917384
从这个例子可以看出,屏蔽部分(y_pred
中的零)的损失被忽略,model.evaluate()
的输出等于masked_loss
。
编辑:
如果存在 return_sequences=False
的循环层,掩码停止传播(即返回的掩码为 None
)。在 RNN.compute_mask()
:
def compute_mask(self, inputs, mask):
if isinstance(mask, list):
mask = mask[0]
output_mask = mask if self.return_sequences else None
if self.return_state:
state_mask = [None for _ in self.states]
return [output_mask] + state_mask
else:
return output_mask
在你的情况下,如果我理解正确,你想要一个基于 y_true
的掩码,并且只要 y_true
的值是 [0, 0, 1]
( "#") 您希望掩盖损失。如果是这样,您需要以类似于 Daniel 的回答的方式来掩盖损失值。
主要区别在于最终平均值。平均值应接管未屏蔽值的数量,即 K.sum(mask)
。而且,y_true
可以直接与 one-hot 编码向量 [0, 0, 1]
进行比较。
def get_loss(mask_value):
mask_value = K.variable(mask_value)
def masked_categorical_crossentropy(y_true, y_pred):
# find out which timesteps in `y_true` are not the padding character '#'
mask = K.all(K.equal(y_true, mask_value), axis=-1)
mask = 1 - K.cast(mask, K.floatx())
# multiply categorical_crossentropy with the mask
loss = K.categorical_crossentropy(y_true, y_pred) * mask
# take average w.r.t. the number of unmasked entries
return K.sum(loss) / K.sum(mask)
return masked_categorical_crossentropy
masked_categorical_crossentropy = get_loss(np.array([0, 0, 1]))
model = Model(input_tensor, output)
model.compile(loss=masked_categorical_crossentropy, optimizer='adam')
以上代码的输出显示损失仅在未屏蔽的值上计算:
model.evaluate: 1.08339476585
tf unmasked_loss: 1.08989
tf masked_loss: 1.08339
该值与您的不同,因为我已将 tf.reverse
中的 axis
参数从 [0,1]
更改为 [1]
。
我接受了两个答案,并为多个时间步、单个缺失目标值、LSTM(或其他 RecurrentNN)的损失改进了一种方法 return_sequences=True。
由于 isMask = K.all(isMask, axis=-1)
,Daniels 的回答对于多个目标来说是不够的。删除这个聚合可能会使函数不可微分。我不确定,因为我从来没有 运行 纯函数,也不知道它是否适合模型。
我将 Yu-Yangs 和 Daniels 的答案融合在一起,它奏效了。
from tensorflow.keras.layers import Layer, Input, LSTM, Dense, TimeDistributed
from tensorflow.keras import Model, Sequential
import tensorflow.keras.backend as K
import numpy as np
mask_Value = -2
def get_loss(mask_value):
mask_value = K.variable(mask_value)
def masked_loss(yTrue,yPred):
#find which values in yTrue (target) are the mask value
isMask = K.equal(yTrue, mask_Value) #true for all mask values
#transform to float (0 or 1) and invert
isMask = K.cast(isMask, dtype=K.floatx())
isMask = 1 - isMask #now mask values are zero, and others are 1
isMask
#multiply this by the inputs:
#maybe you might need K.expand_dims(isMask) to add the extra dimension removed by K.all
yTrue = yTrue * isMask
yPred = yPred * isMask
# perform a root mean square error, whereas the mean is in respect to the mask
mean_loss = K.sum(K.square(yPred - yTrue))/K.sum(isMask)
loss = K.sqrt(mean_loss)
return loss
#RootMeanSquaredError()(yTrue,yPred)
return masked_loss
# define timeseries data
n_sample = 10
timesteps = 5
feat_inp = 2
feat_out = 2
X = np.random.uniform(0,1, (n_sample, timesteps, feat_inp))
y = np.random.uniform(0,1, (n_sample,timesteps, feat_out))
# define model
model = Sequential()
model.add(LSTM(50, activation='relu',return_sequences=True, input_shape=(timesteps, feat_inp)))
model.add(Dense(feat_out))
model.compile(optimizer='adam', loss=get_loss(mask_Value))
model.summary()
# %%
model.fit(X, y, epochs=50, verbose=0)