Closed gdeluca1 closed 6 months ago
The SamplerQNN is infact behaving as it should, with an output of 2^circuit.num_qubits, this can be modified if necessary to an output of different shape by using the parameters interpret and output_shape, both have to be used in unison to work.
In your case, as I see it explained here, you are really looking at a binary classification and so only need one y_train value (i.e. y_train[:,0]) to train on and see the probability of one class, output of 1 qubit. Please refer to examples as seen in this tutorial: https://qiskit-community.github.io/qiskit-machine-learning/tutorials/02_neural_network_classifier_and_regressor.html#Regression
Environment
What is happening?
When using a SamplerQNN, the output shape is related to the size of the quasi-probability distribution (for example, it would output 2 values if 1 qubit is used). However, when constructing a NeuralNetworkRegressor using the SamplerQNN, the output shape no longer reflects this. In my below example with 1000 training points, the shape is expected to be (1000,) when it should presumably be (1000,2).
How can we reproduce the issue?
(1000, 1) (1000, 2)
(2,) [[0.64765057 0.35234943]] [0.87265857 0.12734143] (2,)
QiskitMachineLearningError Traceback (most recent call last) Input In [9], in <cell line: 1>() ----> 1 regressor.fit(X_train, y_train)
Full Exception Details
File ~\anaconda3\envs\QC\lib\site-packages\qiskit_machine_learning\algorithms\trainable_model.py:201, in TrainableModel.fit(self, X, y) 198 if not self._warm_start: 199 self._fit_result = None --> 201 self._fit_result = self._fit_internal(X, y) 202 return self File ~\anaconda3\envs\QC\lib\site-packages\qiskit_machine_learning\algorithms\regressors\neural_network_regressor.py:46, in NeuralNetworkRegressor._fit_internal(self, X, y) 42 function = MultiClassObjectiveFunction(X, y, self._neural_network, self._loss) 44 objective = self._get_objective(function) ---> 46 return self._optimizer.minimize( 47 fun=objective, 48 x0=self._choose_initial_point(), 49 jac=function.gradient, 50 ) File ~\anaconda3\envs\QC\lib\site-packages\qiskit\algorithms\optimizers\scipy_optimizer.py:148, in SciPyOptimizer.minimize(self, fun, x0, jac, bounds) 145 swapped_deprecated_args = True 146 self._options["maxfun"] = self._options.pop("maxiter") --> 148 raw_result = minimize( 149 fun=fun, 150 x0=x0, 151 method=self._method, 152 jac=jac, 153 bounds=bounds, 154 options=self._options, 155 **self._kwargs, 156 ) 157 if swapped_deprecated_args: 158 self._options["maxiter"] = self._options.pop("maxfun") File ~\anaconda3\envs\QC\lib\site-packages\scipy\optimize\_minimize.py:699, in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options) 696 res = _minimize_newtoncg(fun, x0, args, jac, hess, hessp, callback, 697 **options) 698 elif meth == 'l-bfgs-b': --> 699 res = _minimize_lbfgsb(fun, x0, args, jac, bounds, 700 callback=callback, **options) 701 elif meth == 'tnc': 702 res = _minimize_tnc(fun, x0, args, jac, bounds, callback=callback, 703 **options) File ~\anaconda3\envs\QC\lib\site-packages\scipy\optimize\_lbfgsb_py.py:308, in _minimize_lbfgsb(fun, x0, args, jac, bounds, disp, maxcor, ftol, gtol, eps, maxfun, maxiter, iprint, callback, maxls, finite_diff_rel_step, **unknown_options) 305 else: 306 iprint = disp --> 308 sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, 309 bounds=new_bounds, 310 finite_diff_rel_step=finite_diff_rel_step) 312 func_and_grad = sf.fun_and_grad 314 fortran_int = _lbfgsb.types.intvar.dtype File ~\anaconda3\envs\QC\lib\site-packages\scipy\optimize\_optimize.py:263, in _prepare_scalar_function(fun, x0, jac, args, bounds, epsilon, finite_diff_rel_step, hess) 259 bounds = (-np.inf, np.inf) 261 # ScalarFunction caches. Reuse of fun(x) during grad 262 # calculation reduces overall function evaluations. --> 263 sf = ScalarFunction(fun, x0, args, grad, hess, 264 finite_diff_rel_step, bounds, epsilon=epsilon) 266 return sf File ~\anaconda3\envs\QC\lib\site-packages\scipy\optimize\_differentiable_functions.py:158, in ScalarFunction.__init__(self, fun, x0, args, grad, hess, finite_diff_rel_step, finite_diff_bounds, epsilon) 155 self.f = fun_wrapped(self.x) 157 self._update_fun_impl = update_fun --> 158 self._update_fun() 160 # Gradient evaluation 161 if callable(grad): File ~\anaconda3\envs\QC\lib\site-packages\scipy\optimize\_differentiable_functions.py:251, in ScalarFunction._update_fun(self) 249 def _update_fun(self): 250 if not self.f_updated: --> 251 self._update_fun_impl() 252 self.f_updated = True File ~\anaconda3\envs\QC\lib\site-packages\scipy\optimize\_differentiable_functions.py:155, in ScalarFunction.__init__.QiskitMachineLearningError: "Shapes don't match, predict: (1000,), target: (1000, 2)!"
What should happen?
I would expect the network to be able to train with a y_train array that has a shape of (1000,2) in my example without an exception. More generally, the shape of the y array should presumably be (n,k) where k is the number of elements in the quasi-probability distribution and n is the number of training samples.
Any suggestions?
No response