Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Masking time steps in order to use TCN for variable length sequences #240

Open
fsbashiri opened this issue Oct 17, 2022 · 2 comments
Open

Comments

@fsbashiri
Copy link

fsbashiri commented Oct 17, 2022

Describe the bug
In my project, I am using TCN for sequence-to-sequence analysis of time series data that have variable lengths. I have defined a subclass of the Sequence class that pads each batch of data to its maximum sequence length (similar to what is suggested here). As for the model, I use a masking layer to compute and pass a mask to TCN (as suggested here issue #234). Supposedly, layers that support masking will automatically propagate the mask to the next layer. In the simplest form of my model, I have a masking layer, followed by a TCN, and a Dense layer with 1 unit.

Here are two issues that I've got:

  1. when I try to access the propagated mask from the output of the TCN layer, I get an error that says the object has no attribute _keras_mask.
  2. Apparently, it matters if a sequence is padded from the beginning of the sequence or a the end (whether to set padding argument of the pad_sequences 'pre' or 'post'). If it's padded from the beginning, the output of the TCN at those padded time steps is equal to zero. But you cannot expect zero output if it's padded at the end of the sequence.

Paste a snippet
Please see the following simple code:

mask_value = 1.0
x = np.random.rand(1, 3, 8)  # 1 sample, 3 time steps, 8 features
x_pre = np.append(mask_value * np.ones((1, 2, 8)), x, axis=1)  # append (pre-padding) 2 time steps with mask_value
x_post = np.append(x, mask_value * np.ones((1, 2, 8)), axis=1)  # append (post-padding) 2 time steps with mask_value
print(f"x_pre: \n{x_pre}")

# Sequential modeling
model = Sequential()
model.add(Masking(mask_value=mask_value))
model.add(TCN(nb_filters=64,
              nb_stacks=1,
              kernel_size=3,
              dilations=[1, 2],
              padding='causal',
              return_sequences=True))
model.add(TimeDistributed(Dense(1)))

out_pre = model(x_pre)
out_post = model(x_post)
print(f"out_pre: \n{out_pre}")
print(f"out_post: \n{out_post}")
print(f"out_pre._keras_mask: \n{out_pre._keras_mask}")

The output of the code:

x_pre: 
[[[1.         1.         1.         1.         1.         1.
   1.         1.        ]
  [1.         1.         1.         1.         1.         1.
   1.         1.        ]
  [0.66743025 0.3803879  0.06403598 0.6146936  0.34356068 0.08322509
   0.97064031 0.67479811]
  [0.38705443 0.18246054 0.17536628 0.8973423  0.63538071 0.35077733
   0.33901726 0.35183449]
  [0.10048297 0.33713389 0.61988985 0.74523683 0.48507557 0.21914819
   0.86720421 0.66290713]]]
out_pre: 
[[[ 0.        ]
  [ 0.        ]
  [-0.28437746]
  [-0.29050288]
  [-0.84733   ]]]
out_post: 
[[[-0.28437746]
  [-0.29050288]
  [-0.84733   ]
  [-0.05684387]
  [-0.7985336 ]]]
Traceback (most recent call last):
  File "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pydev/pydevd.py", line 1491, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/Users/fbashiri/Documents/Projects/MGP-AttTCN-master/src/loss_n_eval/Azi_test_loss.py", line 132, in <module>
    print(f"out_pre._keras_mask: \n{out_pre._keras_mask}")
AttributeError: 'tensorflow.python.framework.ops.EagerTensor' object has no attribute '_keras_mask'

Dependencies
I am using:
keras 2.4.3
keras-tan 3.1.1
Tensorflow-gpu 2.3.1

@philipperemy
Copy link
Owner

philipperemy commented Nov 7, 2022

@fsbashiri thanks for reporting! I propose an explanation. I'm not 100% sure, you can challenge me.

My clue is the TCN works a bit like an RNN even though it has no states like a LSTM would have.

The last outputs depend on the end of the sequence but also on the beginning.

  • If you use post, the end is padded with zeros. The last outputs will be non zeros because they also depend on the beginning of the sequence, which contains values (non zeros).
  • Conversely, the first outputs only depends on the beginning of the sequence. If you use pre, the beginning will be padded with 0 and the first outputs will be 0.

image

For your second point _keras_mask, I guess we should not directly try to call it. But it's strange if it does not exist. Does it exist for other Keras layers that support masking? Maybe we should add it somewhere in the layer because it's not inherited from the Layer object. I don't know.

@cruyffturn
Copy link

This problem is mentioned on issue #89. Author states "Con1d by keras lacking supports for Masking layer".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants