qiskit-community / qiskit-machine-learning

Quantum Machine Learning
https://qiskit-community.github.io/qiskit-machine-learning/
Apache License 2.0
647 stars 316 forks source link

Error in gradient calculation in qGAN using Gradient() #70

Closed sychang42 closed 3 years ago

sychang42 commented 3 years ago

Information

What is the current behavior?

I was trying to apply "Phase shift rule" for gradient calculation in quantum GAN using the tutorial : https://qiskit.org/documentation/tutorials/machine_learning/04_qgans_for_loading_random_distributions.html.

To do so, I replaced the line :

qgan.set_generator(generator_circuit=g_circuit, generator_init_params=init_params)

by

qgan.set_generator(generator_circuit=g_circuit, generator_init_params=init_params, generator_gradient = Gradient())

with qiskit.aqua.operators.gradients.Gradient.

However, while running

result = qgan.run(quantum_instance)

with reps = 2 (2 blocks in the quantum generator), the code shows me an error message below :

ValueError                                Traceback (most recent call last)
~\Anaconda3\lib\site-packages\qiskit\aqua\components\neural_networks\quantum_generator.py in loss(self, x, weights)
    382             # pylint: disable=no-member
--> 383             loss = (-1) * np.dot(np.log(x).transpose(), weights)
    384         except Exception:  # pylint: disable=broad-except
<__array_function__ internals> in dot(*args, **kwargs)
ValueError: shapes (4,1) and (6,4) not aligned: 1 (dim 1) != 6 (dim 0)

Please also find the full error message below

.

Steps to reproduce the problem

Please also find the code here.

In the tutorial 04_qgans_for_loading_random_distributions.ipynb,

1) Import gradient object :

from qiskit.opflow import Gradient

2) Replace the line :

qgan.set_generator(generator_circuit=g_circuit, generator_init_params=init_params)

by

qgan.set_generator(generator_circuit=g_circuit, generator_init_params=init_params, generator_gradient = Gradient())`

3) Replace the line :

var_form = TwoLocal(int(np.sum(num_qubits)), 'ry', 'cz', entanglement=entangler_map, reps=1)

by

var_form = TwoLocal(int(np.sum(num_qubits)), 'ry', 'cz', entanglement=entangler_map, reps=2)

4) Add two more values for init_params (array of size 6)

5) Run the quantum GAN.

What is the expected behavior?

By the chain rule, the gradient of the generator is calculated as :

.

(c.f. Appendix B in Supplementary Information: Quantum Generative Adversarial Networks for Learning and Loading Random Distributions)

As we are summing over , the matrix multiplication performed in

loss_gradients = self.loss(prediction_generated, analytical_gradients).real

(line 411 in quantum_machine_learning.algorithms.distribution_learners.qgan.quantum_generator)

should take the form :

where

,

However,

analytical_gradients = np.array(grad_object.assign_parameters(value_dict).eval())

in

def _convert_to_gradient_function(self, gradient_object, quantum_instance, discriminator)

currently returns:

(line 410 in quantum_machine_learning.algorithms.distribution_learners.qgan.quantum_generator)

,

so the code returns an error for matrix multiplication.

Suggested solutions

I think the analytical gradients should be transposed :

analytical_gradients = np.array(grad_object.assign_parameters(value_dict).eval())

to

analytical_gradients = np.transpose(np.array(grad_object.assign_parameters(value_dict).eval()))
adekusar-drl commented 3 years ago

Closed in #77