From 02ee6a7fa0ce8c3b1c5758e17aba0da03174a1b2 Mon Sep 17 00:00:00 2001 From: "M. Emre Sahin" <40424147+OkuyanBoga@users.noreply.github.com> Date: Mon, 16 Dec 2024 19:28:19 +0000 Subject: [PATCH] Fix callback compatibility for trainable_model (#878) * Fix callback compatibility for trainable_model * Update releasenotes/notes/fix-callback-trainable_model-ca52060260a3e466.yaml Co-authored-by: Edoardo Altamura <38359901+edoaltamura@users.noreply.github.com> * Update tests with callbacks * Disable pylint unused arguments in tests --------- Co-authored-by: Edoardo Altamura <38359901+edoaltamura@users.noreply.github.com> --- qiskit_machine_learning/algorithms/trainable_model.py | 5 +++-- .../fix-callback-trainable_model-ca52060260a3e466.yaml | 5 +++++ .../classifiers/test_neural_network_classifier.py | 9 +++++---- .../regressors/test_neural_network_regressor.py | 10 ++++++---- 4 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 releasenotes/notes/fix-callback-trainable_model-ca52060260a3e466.yaml diff --git a/qiskit_machine_learning/algorithms/trainable_model.py b/qiskit_machine_learning/algorithms/trainable_model.py index 108dcdecd..3b2bace9b 100644 --- a/qiskit_machine_learning/algorithms/trainable_model.py +++ b/qiskit_machine_learning/algorithms/trainable_model.py @@ -20,7 +20,7 @@ from .objective_functions import ObjectiveFunction from .serializable_model import SerializableModelMixin -from ..optimizers import Optimizer, SLSQP, OptimizerResult, Minimizer +from ..optimizers import Optimizer, SciPyOptimizer, SLSQP, OptimizerResult, Minimizer from ..utils import algorithm_globals from ..neural_networks import NeuralNetwork from ..utils.loss_functions import ( @@ -269,7 +269,8 @@ def _get_objective( def objective(objective_weights): objective_value = function.objective(objective_weights) - self._callback(objective_weights, objective_value) + if isinstance(self._optimizer, SciPyOptimizer): + self._callback(objective_weights, objective_value) return objective_value return objective diff --git a/releasenotes/notes/fix-callback-trainable_model-ca52060260a3e466.yaml b/releasenotes/notes/fix-callback-trainable_model-ca52060260a3e466.yaml new file mode 100644 index 000000000..dbdee5f73 --- /dev/null +++ b/releasenotes/notes/fix-callback-trainable_model-ca52060260a3e466.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed a compatibility issue for different `callback` functions when they are + used in :class:`~qiskit_machine_learning.algorithms.trainable_model` based algorithms. \ No newline at end of file diff --git a/test/algorithms/classifiers/test_neural_network_classifier.py b/test/algorithms/classifiers/test_neural_network_classifier.py index 69655b301..4cb40dae8 100644 --- a/test/algorithms/classifiers/test_neural_network_classifier.py +++ b/test/algorithms/classifiers/test_neural_network_classifier.py @@ -521,17 +521,18 @@ def test_callback_setter(self): loss_history = [] - def store_loss(_, loss): - loss_history.append(loss) + def store_loss(nfev, x_next, loss, update, is_accepted): # pylint: disable=unused-argument + if is_accepted: + loss_history.append(loss) # use setter for the callback instead of providing in the initialize method - classifier.callback = store_loss + classifier.optimizer.callback = store_loss features = np.array([[0, 0], [1, 1]]) labels = np.array([0, 1]) classifier.fit(features, labels) - self.assertEqual(len(loss_history), 3) + self.assertEqual(len(loss_history), 1) if __name__ == "__main__": diff --git a/test/algorithms/regressors/test_neural_network_regressor.py b/test/algorithms/regressors/test_neural_network_regressor.py index a7c9cb225..fb791167b 100644 --- a/test/algorithms/regressors/test_neural_network_regressor.py +++ b/test/algorithms/regressors/test_neural_network_regressor.py @@ -239,17 +239,19 @@ def test_callback_setter(self): loss_history = [] - def store_loss(_, loss): - loss_history.append(loss) + def store_loss(nfev, x_next, loss, update, is_accepted): # pylint: disable=unused-argument + + if is_accepted: + loss_history.append(loss) # use setter for the callback instead of providing in the initialize method - regressor.callback = store_loss + regressor.optimizer.callback = store_loss features = np.array([[0, 0], [0.1, 0.1], [0.4, 0.4], [1, 1]]) labels = np.array([0, 0.1, 0.4, 1]) regressor.fit(features, labels) - self.assertEqual(len(loss_history), 3) + self.assertEqual(len(loss_history), 1) if __name__ == "__main__":