我正在对可变长度序列训练一个有状态的 RNN(可选:有关更多详细信息,请参阅我之前的问题)。
我用值 -1 将序列填充到固定长度。
加载批次时,某些样本将完全为-1。(例如,批次是形状 [batchsize, ...],样本 1、6、8 可能完全由 -1 组成)。我想:
- 在损失函数计算中不包括这些样本
- 不对其进行操作以加快训练速度。
尝试1:
我尝试使用tf.Keras.layers.Masking如下:
input = tf.Keras.layers.Masking(mask_val=-1)(input)
但是,这似乎没有任何作用。后续操作仍在执行,据我所知,样本仍包含在损失函数中。为什么是这样?
尝试2:
我尝试制作自己的自定义层,它实际上会删除被屏蔽的样本(参见下面的代码)。例如,输入形状从[batchsize, ...]
到[adj_batchsize, ...]
where adj_batchsize = batchsize - num_removed_samples
。这可行,但速度极慢,因为每次输入形状发生变化时,都需要重新分配 GPU 内存,这会大大减慢训练速度。
class MaskLayer(K.Model):
def __init__(self, mask_val):
'''
This layer takes input tensor of [batchsize, ...] and returns tensor of shape [bs_out, ...]
Where all samples composed entirely of mask_val are removed and bs_out is the number of remaining
samples
'''
super(MaskLayer, self).__init__()
self.mask_val = mask_val
self.mask = tf.keras.layers.Masking(mask_value=mask_val)
def call(self, data, lbls):
good_batches = tf.where(tf.math.reduce_all(self.mask.compute_mask(data), axis=range(1,data.ndim-1)))[:,0]
data = tf.gather(data, good_batches)
lbls = tf.gather(lbls, good_batches)
return data, lbls
那么最好的方法是什么?
注意:这个问题之前在 stackoverflow.coom 上被问过,但由于缺乏回应而被删除。我认为这将是一个更好的家。