CQCL / lambeq

A high-level Python library for Quantum Natural Language Processing
https://cqcl.github.io/lambeq-docs
Apache License 2.0
450 stars 108 forks source link

QuantumTrainer.fit(train_dataset) error - examples / quantum_pipeline.ipynb #83

Closed dtchang closed 1 year ago

dtchang commented 1 year ago

For either the MC or RP dataset, with training and test data, calling fit(train_dataset, logging_step=12) generates the following error:


ValueError Traceback (most recent call last) ~\AppData\Local\Temp\ipykernel_34608\45519830.py in ...

C:\Anaconda3\lib\site-packages\lambeq\training\quantum_trainer.py in fit(self, train_dataset, val_dataset, evaluation_step, logging_step) 197 self.model._training = True 198 --> 199 super().fit(train_dataset, val_dataset, evaluation_step, logging_step) 200 201 self.model._training = False

...

C:\Anaconda3\lib\site-packages\discopy\quantum\tk.py in get_counts(self, backend, *others, **params) 131 if compilation is not None: 132 for circuit in (self, ) + others: --> 133 compilation.apply(circuit) 134 handles = backend.process_circuits( 135 (self, ) + others, n_shots=n_shots, seed=seed)

ValueError: Non-unitary matrix passed to two_qubit_canonical

Thommy257 commented 1 year ago

Can you tell us more about your system? OS, python version, version of lambeq, pytket, discopy etc. Also, which notebook are you running?

This is possibly related to #75

dimkart commented 1 year ago

@dtchang Please include the full trace of the error, as well as the versions of the python packages (lambeq, pytket, discopy) as requested by @Thommy257.

dtchang commented 1 year ago

Thanks for looking into this.

Here is the information on the python packages: lambeq: 0.3.1 discopy: 0.5.1.1 pytket: 1.11.1 Python: 3.9.15 JupyterLab: 3.5.2 Windows 10

Here is the full trace:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_8264\45519830.py in <module>
      1 #trainer.fit(train_dataset, val_dataset, logging_step=12)
----> 2 trainer.fit(train_dataset, logging_step=12)

C:\Anaconda3\lib\site-packages\lambeq\training\quantum_trainer.py in fit(self, train_dataset, val_dataset, evaluation_step, logging_step)
    197         self.model._training = True
    198 
--> 199         super().fit(train_dataset, val_dataset, evaluation_step, logging_step)
    200 
    201         self.model._training = False

C:\Anaconda3\lib\site-packages\lambeq\training\trainer.py in fit(self, train_dataset, val_dataset, evaluation_step, logging_step)
    373                     step += 1
    374                     x, y_label = batch
--> 375                     y_hat, loss = self.training_step(batch)
    376                     if (self.evaluate_on_train
    377                             and self.evaluate_functions is not None):

C:\Anaconda3\lib\site-packages\lambeq\training\quantum_trainer.py in training_step(self, batch)
    161         """
    162         self.model._clear_predictions()
--> 163         loss = self.optimizer.backward(batch)
    164         y_hat = self.model._train_predictions[-1]
    165         self.train_costs.append(loss)

C:\Anaconda3\lib\site-packages\lambeq\training\spsa_optimizer.py in backward(self, batch)
    139         xplus = self.project(x + self.ck * delta)
    140         self.model.weights = xplus
--> 141         y0 = self.model(diagrams)
    142         loss0 = self.loss_fn(y0, targets)
    143 

C:\Anaconda3\lib\site-packages\lambeq\training\quantum_model.py in __call__(self, *args, **kwargs)
    144 
    145     def __call__(self, *args: Any, **kwargs: Any) -> Any:
--> 146         out = self.forward(*args, **kwargs)
    147         if self._training:
    148             self._log_prediction(out)

C:\Anaconda3\lib\site-packages\lambeq\training\tket_model.py in forward(self, x)
    131 
    132         """
--> 133         return self.get_diagram_output(x)

C:\Anaconda3\lib\site-packages\lambeq\training\tket_model.py in get_diagram_output(self, diagrams)
    100 
    101         lambdified_diagrams = [self._make_lambda(d) for d in diagrams]
--> 102         tensors = Circuit.eval(
    103             *[diag_f(*self.weights) for diag_f in lambdified_diagrams],
    104             **self.backend_config,

C:\Anaconda3\lib\site-packages\discopy\quantum\circuit.py in eval(self, backend, mixed, contractor, *others, **params)
    286             return type(box)(box.dom, box.cod, box.array + 0j)
    287         circuits = [circuit.to_tk() for circuit in (self, ) + others]
--> 288         results, counts = [], circuits[0].get_counts(
    289             *circuits[1:], backend=backend, **params)
    290         for i, circuit in enumerate(circuits):

C:\Anaconda3\lib\site-packages\discopy\quantum\tk.py in get_counts(self, backend, *others, **params)
    131         if compilation is not None:
    132             for circuit in (self, ) + others:
--> 133                 compilation.apply(circuit)
    134         handles = backend.process_circuits(
    135             (self, ) + others, n_shots=n_shots, seed=seed)

ValueError: Non-unitary matrix passed to two_qubit_canonical
dimkart commented 1 year ago

Thanks for the information. It seems you are using an older notebook from lambeq version 0.2.8, which creates this error when running with lambeq 0.3.0 or higher. The reason is that you are using custom loss functions, which do not work very well with the new initialisation we introduced in lambeq 0.3.0. The easy solution would be to use lambeq's losses, e.g. BinaryCrossEntropyLoss, as we do in the updated notebooks. If you still prefer to use your own losses, you have to add some additional safeguards which prevent situations such as 0-div (check source code of the lambeq's loss functions).

dimkart commented 1 year ago

@yousrabou this might be also relevant to your problem (Issue #75)

yousrabou commented 1 year ago

using : lambeq : 0.3.1 pytket : 1.14.0 pytket-qiskit : 0.38.0 and the BinaryCrossEntropyLoss function for training RP dataset on GoogleColab envirenement the following error is produced !!

ValueError Traceback (most recent call last) in <cell line: 1>() ----> 1 trainer.fit(train_dataset, logging_step=12)

7 frames /usr/local/lib/python3.10/dist-packages/lambeq/training/loss.py in _match_shapes(self, y1, y2) 64 y2: np.ndarray | jnp.ndarray) -> None: 65 if y1.shape != y2.shape: ---> 66 raise ValueError('Provided arrays must be of equal shape. Got ' 67 f'arrays of shape {y1.shape} and {y2.shape}.') 68

ValueError: Provided arrays must be of equal shape. Got arrays of shape (30,) and (30, 2).

nikhilkhatri commented 1 year ago

Hi @yousrabou , It would help to know the following:

  1. What is the codomain of the diagrams in the dataset (1 qubit or 0 qubits (scalar)?)
  2. The code snippet where you prepare y_true targets.

I'd recommend taking a look at the documentation for the loss function, which describes the expected param shapes.

dtchang commented 1 year ago

I tried the updated notebook for both the MC and RP datasets with only training and test data. No error. So, this issue is resolved.

dimkart commented 1 year ago

This issue is now resolved and will be closed -- @yousrabou please follow-up your question in #90.