Skip to content

Commit

Permalink
Merge pull request #5709 from RasaHQ/revert-5565-mask-vs-sequence
Browse files Browse the repository at this point in the history
Revert model breaking changes in 1.9.x
  • Loading branch information
erohmensing committed Apr 23, 2020
2 parents 23a5137 + c0b3065 commit 984a07f
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 58 deletions.
6 changes: 6 additions & 0 deletions changelog/5709.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Reverted changes in 1.9.6 that led to model incompatibility. Upgrade to 1.9.7 to fix
``self.sequence_lengths_for(tf_batch_data[TEXT_SEQ_LENGTH][0]) IndexError: list index out of range``
error without needing to retrain earlier 1.9 models.

Therefore, all 1.9 models `except for 1.9.6` will be compatible; a model trained on 1.9.6 will need
to be retrained on 1.9.7.
56 changes: 20 additions & 36 deletions rasa/nlu/classifiers/diet_classifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@

TEXT_FEATURES = f"{TEXT}_features"
LABEL_FEATURES = f"{LABEL}_features"
TEXT_MASK = f"{TEXT}_mask"
LABEL_MASK = f"{LABEL}_mask"
LABEL_IDS = f"{LABEL}_ids"
TAG_IDS = "tag_ids"
TEXT_SEQ_LENGTH = f"{TEXT}_lengths"
LABEL_SEQ_LENGTH = f"{LABEL}_lengths"


class DIETClassifier(IntentClassifier, EntityExtractor):
Expand Down Expand Up @@ -484,7 +484,7 @@ def _create_label_data(
# to track correctly dynamic sequences
label_data.add_features(LABEL_IDS, [np.expand_dims(label_ids, -1)])

label_data.add_lengths(LABEL_SEQ_LENGTH, LABEL_FEATURES)
label_data.add_mask(LABEL_MASK, LABEL_FEATURES)

return label_data

Expand Down Expand Up @@ -558,8 +558,8 @@ def _create_model_data(
model_data.add_features(LABEL_IDS, [np.expand_dims(label_ids, -1)])
model_data.add_features(TAG_IDS, [tag_ids])

model_data.add_lengths(TEXT_SEQ_LENGTH, TEXT_FEATURES)
model_data.add_lengths(LABEL_SEQ_LENGTH, LABEL_FEATURES)
model_data.add_mask(TEXT_MASK, TEXT_FEATURES)
model_data.add_mask(LABEL_MASK, LABEL_FEATURES)

return model_data

Expand Down Expand Up @@ -1165,6 +1165,10 @@ def _prepare_entity_recognition_layers(self) -> None:
average="micro",
)

@staticmethod
def _get_sequence_lengths(mask: tf.Tensor) -> tf.Tensor:
return tf.cast(tf.reduce_sum(mask[:, :, 0], axis=1), tf.int32)

def _combine_sparse_dense_features(
self,
features: List[Union[np.ndarray, tf.Tensor, tf.SparseTensor]],
Expand Down Expand Up @@ -1246,23 +1250,16 @@ def _create_sequence(
outputs = self._tf_layers[f"{name}_transformer"](
transformer_inputs, 1 - mask, self._training
)

if self.config[NUM_TRANSFORMER_LAYERS] > 0:
# apply activation
outputs = tfa.activations.gelu(outputs)
outputs = tfa.activations.gelu(outputs)

return outputs, inputs, seq_ids, lm_mask_bool

def _create_all_labels(self) -> Tuple[tf.Tensor, tf.Tensor]:
all_label_ids = self.tf_label_data[LABEL_IDS][0]

label_lengths = self.sequence_lengths_for(
self.tf_label_data[LABEL_SEQ_LENGTH][0]
)
mask_label = self._compute_mask(label_lengths)

x = self._create_bow(
self.tf_label_data[LABEL_FEATURES], mask_label, self.label_name,
self.tf_label_data[LABEL_FEATURES],
self.tf_label_data[LABEL_MASK][0],
self.label_name,
)
all_labels_embed = self._tf_layers[f"embed.{LABEL}"](x)

Expand Down Expand Up @@ -1356,23 +1353,13 @@ def _calculate_entity_loss(

return loss, f1

@staticmethod
def _compute_mask(sequence_lengths: tf.Tensor) -> tf.Tensor:
mask = tf.sequence_mask(sequence_lengths, dtype=tf.float32)
# explicitly add last dimension to mask
# to track correctly dynamic sequences
return tf.expand_dims(mask, -1)

def sequence_lengths_for(self, sequence_lengths: tf.Tensor) -> tf.Tensor:
return tf.cast(sequence_lengths, dtype=tf.int32)

def batch_loss(
self, batch_in: Union[Tuple[tf.Tensor], Tuple[np.ndarray]]
) -> tf.Tensor:
tf_batch_data = self.batch_to_model_data_format(batch_in, self.data_signature)

sequence_lengths = self.sequence_lengths_for(tf_batch_data[TEXT_SEQ_LENGTH][0])
mask_text = self._compute_mask(sequence_lengths)
mask_text = tf_batch_data[TEXT_MASK][0]
sequence_lengths = self._get_sequence_lengths(mask_text)

(
text_transformed,
Expand Down Expand Up @@ -1401,14 +1388,11 @@ def batch_loss(
# get _cls_ vector for intent classification
cls = self._last_token(text_transformed, sequence_lengths)

label_lengths = self.sequence_lengths_for(
tf_batch_data[LABEL_SEQ_LENGTH][0]
)
mask_label = self._compute_mask(label_lengths)

label_ids = tf_batch_data[LABEL_IDS][0]
label = self._create_bow(
tf_batch_data[LABEL_FEATURES], mask_label, self.label_name,
tf_batch_data[LABEL_FEATURES],
tf_batch_data[LABEL_MASK][0],
self.label_name,
)
loss, acc = self._calculate_label_loss(cls, label, label_ids)
self.intent_loss.update_state(loss)
Expand All @@ -1434,8 +1418,8 @@ def batch_predict(
batch_in, self.predict_data_signature
)

sequence_lengths = self.sequence_lengths_for(tf_batch_data[TEXT_SEQ_LENGTH][0])
mask_text = self._compute_mask(sequence_lengths)
mask_text = tf_batch_data[TEXT_MASK][0]
sequence_lengths = self._get_sequence_lengths(mask_text)

text_transformed, _, _, _ = self._create_sequence(
tf_batch_data[TEXT_FEATURES], mask_text, self.text_name
Expand Down
28 changes: 10 additions & 18 deletions rasa/nlu/selectors/response_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
DIET,
TEXT_FEATURES,
LABEL_FEATURES,
TEXT_MASK,
LABEL_MASK,
LABEL_IDS,
TEXT_SEQ_LENGTH,
LABEL_SEQ_LENGTH,
)
from rasa.utils.tensorflow.constants import (
LABEL,
Expand Down Expand Up @@ -432,10 +432,8 @@ def _prepare_layers(self) -> None:
def _create_all_labels(self) -> Tuple[tf.Tensor, tf.Tensor]:
all_label_ids = self.tf_label_data[LABEL_IDS][0]

sequence_lengths_label = self.sequence_lengths_for(
self.tf_label_data[LABEL_SEQ_LENGTH][0]
)
mask_label = self._compute_mask(sequence_lengths_label)
mask_label = self.tf_label_data[LABEL_MASK][0]
sequence_lengths_label = self._get_sequence_lengths(mask_label)

label_transformed, _, _, _ = self._create_sequence(
self.tf_label_data[LABEL_FEATURES], mask_label, self.label_name
Expand All @@ -451,10 +449,8 @@ def batch_loss(
) -> tf.Tensor:
tf_batch_data = self.batch_to_model_data_format(batch_in, self.data_signature)

sequence_lengths_text = self.sequence_lengths_for(
tf_batch_data[TEXT_SEQ_LENGTH][0]
)
mask_text = self._compute_mask(sequence_lengths_text)
mask_text = tf_batch_data[TEXT_MASK][0]
sequence_lengths_text = self._get_sequence_lengths(mask_text)

(
text_transformed,
Expand All @@ -469,10 +465,8 @@ def batch_loss(
sequence_ids=True,
)

sequence_lengths_label = self.sequence_lengths_for(
tf_batch_data[LABEL_SEQ_LENGTH][0]
)
mask_label = self._compute_mask(sequence_lengths_label)
mask_label = tf_batch_data[LABEL_MASK][0]
sequence_lengths_label = self._get_sequence_lengths(mask_label)

label_transformed, _, _, _ = self._create_sequence(
tf_batch_data[LABEL_FEATURES], mask_label, self.label_name
Expand Down Expand Up @@ -512,10 +506,8 @@ def batch_predict(
batch_in, self.predict_data_signature
)

sequence_lengths_text = self.sequence_lengths_for(
tf_batch_data[TEXT_SEQ_LENGTH][0]
)
mask_text = self._compute_mask(sequence_lengths_text)
mask_text = tf_batch_data[TEXT_MASK][0]
sequence_lengths_text = self._get_sequence_lengths(mask_text)

text_transformed, _, _, _ = self._create_sequence(
tf_batch_data[TEXT_FEATURES], mask_text, self.text_name
Expand Down
11 changes: 7 additions & 4 deletions rasa/utils/tensorflow/model_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,20 @@ def add_features(self, key: Text, features: List[np.ndarray]):
# update number of examples
self.num_examples = self.number_of_examples()

def add_lengths(self, key: Text, from_key: Text) -> None:
"""Adds np.array of lengths of sequences to data under given key."""
def add_mask(self, key: Text, from_key: Text):
"""Calculate mask for given key and put it under specified key."""

if not self.data.get(from_key):
return

self.data[key] = []

for data in self.data[from_key]:
if data.size > 0:
lengths = np.array([x.shape[0] for x in data])
self.data[key].append(lengths)
# explicitly add last dimension to mask
# to track correctly dynamic sequences
mask = np.array([np.ones((x.shape[0], 1)) for x in data])
self.data[key].append(mask)
break

def split(
Expand Down

0 comments on commit 984a07f

Please sign in to comment.