From 6232234d5bded42659e9a4228ca47e4942b4667c Mon Sep 17 00:00:00 2001 From: Sayak Paul Date: Tue, 2 Aug 2022 09:04:44 +0530 Subject: [PATCH 1/3] fix: keras fit tests for segformer tf and minor refactors. --- .../segformer/test_modeling_tf_segformer.py | 96 ++++++++++--------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/tests/models/segformer/test_modeling_tf_segformer.py b/tests/models/segformer/test_modeling_tf_segformer.py index fbf38fa1d6b2bb..e6572f07d0484b 100644 --- a/tests/models/segformer/test_modeling_tf_segformer.py +++ b/tests/models/segformer/test_modeling_tf_segformer.py @@ -331,63 +331,67 @@ def recursive_check(tuple_object, dict_object): # todo: incorporate label support for semantic segmentation in `test_modeling_tf_common.py`. + @unittest.skipIf( + not is_tf_available() or len(tf.config.list_physical_devices("GPU")) == 0, + reason="TF (<=2.8) does not support backprop for grouped convolutions on CPU.", + ) def test_dataset_conversion(self): - gpus = tf.config.list_physical_devices("GPU") - # Grouped convs aren't supported on CPUs for backprop. - if len(gpus) >= 1: - super().test_dataset_conversion() + super().test_dataset_conversion() + @unittest.skipIf( + not is_tf_available() or len(tf.config.list_physical_devices("GPU")) == 0, + reason="TF (<=2.8) does not support backprop for grouped convolutions on CPU.", + ) def test_keras_fit(self): config, _ = self.model_tester.prepare_config_and_inputs_for_common() - gpus = tf.config.list_physical_devices("GPU") def apply(model): - if getattr(model, "hf_compute_loss", None): - model_weights = model.get_weights() - - # Test that model correctly compute the loss with kwargs - for_segmentation = True if model_class.__name__ == "TFSegformerForSemanticSegmentation" else False - _, prepared_for_class = self.model_tester.prepare_config_and_inputs_for_keras_fit( - for_segmentation=for_segmentation - ) - - label_names = {"labels"} - self.assertGreater(len(label_names), 0, msg="No matching label names found!") - labels = {key: val for key, val in prepared_for_class.items() if key in label_names} - inputs_minus_labels = {key: val for key, val in prepared_for_class.items() if key not in label_names} - self.assertGreater(len(inputs_minus_labels), 0) - model.compile(optimizer=tf.keras.optimizers.SGD(0.0), run_eagerly=True) - - # Make sure the model fits without crashing regardless of where we pass the labels - history1 = model.fit( - prepared_for_class, - validation_data=prepared_for_class, - steps_per_epoch=1, - validation_steps=1, - shuffle=False, - ) - val_loss1 = history1.history["val_loss"][0] - - # We reinitialize the model here even though our learning rate was zero - # because BatchNorm updates weights by means other than gradient descent. - model.set_weights(model_weights) - history2 = model.fit( - inputs_minus_labels, - labels, - validation_data=(inputs_minus_labels, labels), - steps_per_epoch=1, - validation_steps=1, - shuffle=False, - ) - val_loss2 = history2.history["val_loss"][0] - self.assertTrue(np.allclose(val_loss1, val_loss2, atol=1e-2, rtol=1e-3)) + model(model.dummy_inputs) + model_weights = model.get_weights() + + model.compile(optimizer=tf.keras.optimizers.SGD(0.0), run_eagerly=True) + + # Test that model correctly compute the loss with kwargs + for_segmentation = True if model_class.__name__ == "TFSegformerForSemanticSegmentation" else False + _, input_for_model_fit = self.model_tester.prepare_config_and_inputs_for_keras_fit( + for_segmentation=for_segmentation + ) + + label_names = {"labels"} + self.assertGreater(len(label_names), 0, msg="No matching label names found!") + labels = {key: val for key, val in input_for_model_fit.items() if key in label_names} + inputs_minus_labels = {key: val for key, val in input_for_model_fit.items() if key not in label_names} + self.assertGreater(len(inputs_minus_labels), 0) + + # Make sure the model fits without crashing regardless of where we pass the labels + history1 = model.fit( + input_for_model_fit, + validation_data=input_for_model_fit, + steps_per_epoch=1, + validation_steps=1, + shuffle=False, + ) + val_loss1 = history1.history["val_loss"][0] + + # We reinitialize the model here even though our learning rate was zero + # because BatchNorm updates weights by means other than gradient descent. + model.set_weights(model_weights) + history2 = model.fit( + inputs_minus_labels, + labels, + validation_data=(inputs_minus_labels, labels), + steps_per_epoch=1, + validation_steps=1, + shuffle=False, + ) + val_loss2 = history2.history["val_loss"][0] + self.assertTrue(np.allclose(val_loss1, val_loss2, atol=1e-2, rtol=1e-3)) for model_class in self.all_model_classes: # Since `TFSegformerModel` cannot operate with the default `fit()` method. if model_class.__name__ != "TFSegformerModel": - # Grouped convs and backprop with them isn't supported on CPUs. model = model_class(config) - if len(gpus) > 1: + if getattr(model, "hf_compute_loss", None): apply(model) def test_loss_computation(self): From 0fc19d16ccb15c6037823abac198b72d8930e1aa Mon Sep 17 00:00:00 2001 From: Sayak Paul Date: Wed, 3 Aug 2022 10:38:16 +0530 Subject: [PATCH 2/3] refactor: test_keras_fit to make it simpler using the existing one. --- .../segformer/test_modeling_tf_segformer.py | 44 +------------------ 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/tests/models/segformer/test_modeling_tf_segformer.py b/tests/models/segformer/test_modeling_tf_segformer.py index e6572f07d0484b..c44f85f81af299 100644 --- a/tests/models/segformer/test_modeling_tf_segformer.py +++ b/tests/models/segformer/test_modeling_tf_segformer.py @@ -345,54 +345,12 @@ def test_dataset_conversion(self): def test_keras_fit(self): config, _ = self.model_tester.prepare_config_and_inputs_for_common() - def apply(model): - model(model.dummy_inputs) - model_weights = model.get_weights() - - model.compile(optimizer=tf.keras.optimizers.SGD(0.0), run_eagerly=True) - - # Test that model correctly compute the loss with kwargs - for_segmentation = True if model_class.__name__ == "TFSegformerForSemanticSegmentation" else False - _, input_for_model_fit = self.model_tester.prepare_config_and_inputs_for_keras_fit( - for_segmentation=for_segmentation - ) - - label_names = {"labels"} - self.assertGreater(len(label_names), 0, msg="No matching label names found!") - labels = {key: val for key, val in input_for_model_fit.items() if key in label_names} - inputs_minus_labels = {key: val for key, val in input_for_model_fit.items() if key not in label_names} - self.assertGreater(len(inputs_minus_labels), 0) - - # Make sure the model fits without crashing regardless of where we pass the labels - history1 = model.fit( - input_for_model_fit, - validation_data=input_for_model_fit, - steps_per_epoch=1, - validation_steps=1, - shuffle=False, - ) - val_loss1 = history1.history["val_loss"][0] - - # We reinitialize the model here even though our learning rate was zero - # because BatchNorm updates weights by means other than gradient descent. - model.set_weights(model_weights) - history2 = model.fit( - inputs_minus_labels, - labels, - validation_data=(inputs_minus_labels, labels), - steps_per_epoch=1, - validation_steps=1, - shuffle=False, - ) - val_loss2 = history2.history["val_loss"][0] - self.assertTrue(np.allclose(val_loss1, val_loss2, atol=1e-2, rtol=1e-3)) - for model_class in self.all_model_classes: # Since `TFSegformerModel` cannot operate with the default `fit()` method. if model_class.__name__ != "TFSegformerModel": model = model_class(config) if getattr(model, "hf_compute_loss", None): - apply(model) + super().test_keras_fit() def test_loss_computation(self): config, inputs_dict = self.model_tester.prepare_config_and_inputs_for_common() From dd39fc2f8b39e3edcbc8f1863b0785d3d3346b7a Mon Sep 17 00:00:00 2001 From: Sayak Paul Date: Wed, 3 Aug 2022 11:30:15 +0530 Subject: [PATCH 3/3] fix: styling issues. --- tests/models/segformer/test_modeling_tf_segformer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/models/segformer/test_modeling_tf_segformer.py b/tests/models/segformer/test_modeling_tf_segformer.py index c44f85f81af299..6cc2c77fe935fc 100644 --- a/tests/models/segformer/test_modeling_tf_segformer.py +++ b/tests/models/segformer/test_modeling_tf_segformer.py @@ -18,8 +18,6 @@ import unittest from typing import List, Tuple -import numpy as np - from transformers import SegformerConfig from transformers.file_utils import is_tf_available, is_vision_available from transformers.testing_utils import require_tf, slow