PennyLaneAI / pennylane

PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
https://pennylane.ai
Apache License 2.0
2.27k stars 585 forks source link

PyTorch Lightning Example #1288

Open tchaton opened 3 years ago

tchaton commented 3 years ago

Dear people from PennyLaneAI,

First of all, this framework looks absolutely amazing ! Congratulations !!!

I was wondering if you would be willing to collaborate with the PyTorch Lightning Team to add a PyTorch Lightning example to this repo as PyTorch seems to be supported.

It would make https://pennylane.ai/qml/demos/tutorial_quantum_transfer_learning.html simpler and we could promote your awesome framework by the same occasion.

Note: Here is the exact same example in Lightning Flash: https://github.com/PyTorchLightning/lightning-flash/blob/master/flash_examples/finetuning/image_classification.py#L25, so it should be pretty fast to do :)

Best, Thomas Chaton.

josh146 commented 3 years ago

Hi @tchaton! It would be great to add an example using Lightning with PennyLane (this is something that has been previously requested by users). In fact, the website you link to is open source and built by the https://github.com/PennyLaneAI/qml repository (the particular tutorial linked in your post here), so it should be relatively easy to add a PyTorch lightning version.

m-pedro commented 3 years ago

@josh146 can you do this?

PabloAMC commented 3 years ago

Hi everyone! I made a small example of creating a VQE Pytorch Lightning module: https://colab.research.google.com/drive/1vtJuYNnmZJFv5BLyslF0OpQ4FNiHZ2J0?usp=sharing It still needs some debugging though, specially with the weight_shape parameter in the torch_layer @josh146

trbromley commented 3 years ago

Thanks @PabloAMC, looks exciting! Regarding the weight_shapes dictionary, every key should match one of the arguments of your circuit function, except for inputs. So you could either define a single shape for weights (though not sure if that makes sense in this case) or have phi and psi as the argument names in circuit.

Note however that returning qml.ExpvalCost is not supported - see here for example usage.

PabloAMC commented 3 years ago

Hey @trbromley I think I am close to making it work. I am however having trouble with

    H, n_qubits = qml.qchem.molecular_hamiltonian(self.symbols, coordinates.cpu().numpy())

It seems it is not adapted to broadcasting a batch

m-pedro commented 3 years ago

This looks awesome, thanks @PabloAMC. @tchaton - take a look!

trbromley commented 3 years ago

Hey @PabloAMC! If I understand correctly, you would like to evaluate

H, n_qubits = qml.qchem.molecular_hamiltonian(self.symbols, coordinates.cpu().numpy())

where coordinates might be a batch of coordinates? Right now, the molecular_hamiltonian() function doesn't support batching so you may have to adapt into a for loop if you have multiple coordinates. This tutorial has an example of iterating over multiple coordinates when creating the Hamiltonian.

PabloAMC commented 3 years ago

Thanks @trbromley ! I'll take a look, but right now I'm having a weird error:

ImportError: PennyLane-QChem not installed. 

To access the qchem module, you can install PennyLane-QChem via pip:

pip install pennylane-qchem

For more details, see the quantum chemistry documentation:
https://pennylane.readthedocs.io/en/stable/introduction/chemistry.html

but I clearly am installing it before execution. You know what may be going on?

anthayes92 commented 3 years ago

Hi @PabloAMC ,

Thanks for sharing your code and the details of the error. We have been able to run your code without hitting the qchem related ImportError. Please see the following colab notebook:

https://colab.research.google.com/drive/1W1QXripTfZjsxHedPUznxQ5R1mZp_975?usp=sharing

however it does now raise a ValueError. Perhaps the inputs of molecular_hamiltonian may need reviewing?

PabloAMC commented 3 years ago

Hi @anthayes92! Actually, you're right, there were some lines at the end of the installation

WARNING: The following packages were previously imported in this runtime:
  [google]
You must restart the runtime in order to use newly installed versions.

When restarting it did correctly worked, I'm working on the inputs to the molecular hamiltonian :)

PabloAMC commented 3 years ago

I'm now having trouble in

      E = self.qlayer([hf,coord, H])

I had tried

    @qml.qnode(self.dev, interface="torch")
    def ansatz(inputs, phi, psi):
      hf, coordinates, H = inputs
      ...
      return qml.expval(H)

    weight_shapes = {"psi": (1,1), "phi": (len(list(itertools.combinations(range(self.qubits), r=2))),1)}
    self.qlayer = qml.qnn.TorchLayer(ansatz, weight_shapes)

but seems like qlayer does not want complex inputs, just torch tensors or numpy arrays:

<ipython-input-27-c665599b18bf> in forward(self, coordinates)
     54       coord = np.array(coord)
     55       print(type(hf),type(H))
---> 56       E = self.qlayer([hf,coord, H])
     57       E_list.append(E)
     58     E_tensor = torch.tensor(E_list)

/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1049         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1050                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1051             return forward_call(*input, **kwargs)
   1052         # Do not call functions when jit is used
   1053         full_backward_hooks, non_full_backward_hooks = [], []

/usr/local/lib/python3.7/dist-packages/pennylane/qnn/torch.py in forward(self, inputs)
    267         """
    268 
--> 269         if len(inputs.shape) > 1:
    270             # If the input size is not 1-dimensional, unstack the input along its first dimension, recursively call
    271             # the forward pass on each of the yielded tensors, and then stack the outputs back into the correct shape

AttributeError: 'list' object has no attribute 'shape'

Any idea how to bypass this?

anthayes92 commented 3 years ago

Hi @PabloAMC,

That's great that you got past the ImportError!

Yes it looks as though the qlayer does not accept list data types. Have you tried converting your list to an np.array e.g E = self.qlayer(np.array([hf,coord, H])) which would provide the input with a shape attribute.