Hello! This post is in regards to my previous reply in Cannot pass a symbolic Keras tensor to postselect argument of qml.measure() when running on Tensorflow graph mode.
I have a issue when I want to train using tf and my custom qnnode.
I had a look at the pennylane tutorials to try and recreate a minimal example.
Example “tutorial_qnn_module_tf.py” (qml/demonstrations/tutorial_qnn_module_tf.py at master · PennyLaneAI/qml · GitHub)
I used the exact code in the tutorial only adding:
import os
os.environ["TF_USE_LEGACY_KERAS"] = "1"
To use keras 2.
When changing the device from default.qubit to default tensor I get:
Epoch 1/6
/usr/local/lib/python3.10/dist-packages/cotengra/interface.py:719: UserWarning: Contraction cache disabled as one of the arguments is not hashable: {'dtype': 'complex128', 'simplify_sequence': 'ADCRS', 'simplify_atol': 0.0}.
warnings.warn(
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-2d534f3efa97> in <cell line: 169>()
167 # The model is now ready to be trained!
168
--> 169 fitting = model.fit(X, y_hot, epochs=6, batch_size=5, validation_split=0.25, verbose=2)
170
171 ###############################################################################
28 frames
/usr/local/lib/python3.10/dist-packages/tf_keras/src/utils/traceback_utils.py in error_handler(*args, **kwargs)
68 # To get the full stack trace, call:
69 # `tf.debugging.disable_traceback_filtering()`
---> 70 raise e.with_traceback(filtered_tb) from None
71 finally:
72 del filtered_tb
/usr/local/lib/python3.10/dist-packages/pennylane/qnn/keras.py in call(self, inputs)
412
413 # calculate the forward pass as usual
--> 414 results = self._evaluate_qnode(inputs)
415
416 # reshape to the correct number of batch dims
/usr/local/lib/python3.10/dist-packages/pennylane/qnn/keras.py in _evaluate_qnode(self, x)
435 **{k: 1.0 * w for k, w in self.qnode_weights.items()},
436 }
--> 437 res = self.qnode(**kwargs)
438
439 if isinstance(res, (list, tuple)):
/usr/local/lib/python3.10/dist-packages/pennylane/workflow/qnode.py in __call__(self, *args, **kwargs)
985 if qml.capture.enabled():
986 return qml.capture.qnode_call(self, *args, **kwargs)
--> 987 return self._impl_call(*args, **kwargs)
988
989
/usr/local/lib/python3.10/dist-packages/pennylane/workflow/qnode.py in _impl_call(self, *args, **kwargs)
975
976 try:
--> 977 res = self._execution_component(args, kwargs)
978 finally:
979 if old_interface == "auto":
/usr/local/lib/python3.10/dist-packages/pennylane/workflow/qnode.py in _execution_component(self, args, kwargs)
933
934 # pylint: disable=unexpected-keyword-arg
--> 935 res = qml.execute(
936 (self._tape,),
937 device=self.device,
/usr/local/lib/python3.10/dist-packages/pennylane/workflow/execution.py in execute(tapes, device, gradient_fn, interface, transform_program, inner_transform, config, grad_on_execution, gradient_kwargs, cache, cachesize, max_diff, device_vjp, mcm_config)
622
623 if interface in jpc_interfaces:
--> 624 results = ml_boundary_execute(tapes, execute_fn, jpc, device=device)
625 else:
626 results = ml_boundary_execute(
/usr/local/lib/python3.10/dist-packages/pennylane/workflow/interfaces/tensorflow.py in tf_execute(tapes, execute_fn, jpc, device, differentiable)
231 dtype = params_dtype if params_dtype in {tf.float64, tf.complex128} else None
232 # make sure is float64 if data is float64. May cause errors otherwise if device returns float32 precision
--> 233 res = _to_tensors(execute_fn(numpy_tapes), dtype=dtype, complex_safe=True)
234
235 @tf.custom_gradient
/usr/local/lib/python3.10/dist-packages/pennylane/workflow/execution.py in inner_execute(tapes, **_)
200
201 if transformed_tapes:
--> 202 results = device.execute(transformed_tapes, execution_config=execution_config)
203 else:
204 results = ()
/usr/local/lib/python3.10/dist-packages/pennylane/devices/modifiers/simulator_tracking.py in execute(self, circuits, execution_config)
28 @wraps(untracked_execute)
29 def execute(self, circuits, execution_config=DefaultExecutionConfig):
---> 30 results = untracked_execute(self, circuits, execution_config)
31 if isinstance(circuits, QuantumScript):
32 batch = (circuits,)
/usr/local/lib/python3.10/dist-packages/pennylane/devices/modifiers/single_tape_support.py in execute(self, circuits, execution_config)
30 is_single_circuit = True
31 circuits = (circuits,)
---> 32 results = batch_execute(self, circuits, execution_config)
33 return results[0] if is_single_circuit else results
34
/usr/local/lib/python3.10/dist-packages/pennylane/devices/default_tensor.py in execute(self, circuits, execution_config)
658 )
659 circuit = circuit.map_to_standard_wires()
--> 660 results.append(self.simulate(circuit))
661
662 return tuple(results)
/usr/local/lib/python3.10/dist-packages/pennylane/devices/default_tensor.py in simulate(self, circuit)
704 if len(circuit.measurements) == 1:
705 return self.measurement(circuit.measurements[0])
--> 706 return tuple(self.measurement(mp) for mp in circuit.measurements)
707
708 raise NotImplementedError # pragma: no cover
/usr/local/lib/python3.10/dist-packages/pennylane/devices/default_tensor.py in <genexpr>(.0)
704 if len(circuit.measurements) == 1:
705 return self.measurement(circuit.measurements[0])
--> 706 return tuple(self.measurement(mp) for mp in circuit.measurements)
707
708 raise NotImplementedError # pragma: no cover
/usr/local/lib/python3.10/dist-packages/pennylane/devices/default_tensor.py in measurement(self, measurementprocess)
728 """
729
--> 730 return self._get_measurement_function(measurementprocess)(measurementprocess)
731
732 def _get_measurement_function(
/usr/local/lib/python3.10/dist-packages/pennylane/devices/default_tensor.py in expval(self, measurementprocess)
766
767 obs = measurementprocess.obs
--> 768 return expval_core(obs, self)
769
770 def state(self, measurementprocess: MeasurementProcess): # pylint: disable=unused-argument
/usr/lib/python3.10/functools.py in wrapper(*args, **kw)
887 '1 positional argument')
888
--> 889 return dispatch(args[0].__class__)(*args, **kw)
890
891 funcname = getattr(func, '__name__', 'singledispatch function')
/usr/local/lib/python3.10/dist-packages/pennylane/devices/default_tensor.py in expval_core(obs, device)
1022 def expval_core(obs: Observable, device) -> float:
1023 """Dispatcher for expval."""
-> 1024 return device._local_expectation(qml.matrix(obs), tuple(obs.wires))
1025
1026
/usr/local/lib/python3.10/dist-packages/pennylane/devices/default_tensor.py in _local_expectation(self, matrix, wires)
808 qc = self._quimb_circuit.copy()
809
--> 810 exp_val = qc.local_expectation(
811 matrix,
812 wires,
/usr/local/lib/python3.10/dist-packages/quimb/tensor/circuit.py in local_expectation(self, G, where, normalized, **contract_opts)
4684 float
4685 """
-> 4686 return self._psi.local_expectation_canonical(
4687 G,
4688 where,
/usr/local/lib/python3.10/dist-packages/quimb/tensor/tensor_1d.py in local_expectation_canonical(self, G, where, normalized, info, **contract_opts)
2663 float
2664 """
-> 2665 rho = self.partial_trace_to_dense_canonical(
2666 where, normalized=normalized, info=info, **contract_opts
2667 )
/usr/local/lib/python3.10/dist-packages/quimb/tensor/tensor_1d.py in partial_trace_to_dense_canonical(self, where, normalized, info, **contract_opts)
2626
2627 # contract down to a matrix
-> 2628 rho = rho_tn.to_dense(kix, bix, **contract_opts)
2629
2630 if normalized:
/usr/local/lib/python3.10/dist-packages/quimb/tensor/tensor_core.py in to_dense(self, to_qarray, *inds_seq, **contract_opts)
8834 """
8835 tags = contract_opts.pop("tags", all)
-> 8836 t = self.contract(
8837 tags,
8838 output_inds=tuple(concat(inds_seq)),
/usr/local/lib/python3.10/dist-packages/quimb/tensor/tensor_core.py in contract(self, tags, output_inds, optimize, get, backend, preserve_tensor, max_bond, inplace, **opts)
8543 # contracting everything to single output
8544 if all_tags and not inplace:
-> 8545 return tensor_contract(*self.tensor_map.values(), **opts)
8546
8547 # contract some or all tensors, but keeping tensor network
/usr/lib/python3.10/functools.py in wrapper(*args, **kw)
887 '1 positional argument')
888
--> 889 return dispatch(args[0].__class__)(*args, **kw)
890
891 funcname = getattr(func, '__name__', 'singledispatch function')
/usr/local/lib/python3.10/dist-packages/quimb/tensor/tensor_core.py in tensor_contract(output_inds, optimize, get, backend, preserve_tensor, drop_tags, *tensors, **contract_opts)
295
296 # perform the contraction!
--> 297 data_out = array_contract(
298 arrays,
299 inds,
/usr/local/lib/python3.10/dist-packages/quimb/tensor/contraction.py in array_contract(arrays, inputs, output, optimize, backend, **kwargs)
284 if backend is None:
285 backend = get_contract_backend()
--> 286 return ctg.array_contract(
287 arrays, inputs, output, optimize=optimize, backend=backend, **kwargs
288 )
/usr/local/lib/python3.10/dist-packages/cotengra/interface.py in array_contract(arrays, inputs, output, optimize, cache_expression, backend, **kwargs)
784 """
785 shapes = tuple(map(ar.shape, arrays))
--> 786 expr = array_contract_expression(
787 inputs,
788 output,
/usr/local/lib/python3.10/dist-packages/cotengra/interface.py in array_contract_expression(inputs, output, size_dict, shapes, optimize, constants, canonicalize, cache, **kwargs)
722 )
723
--> 724 expr = _build_expression(
725 inputs, output, size_dict, optimize=optimize, **kwargs
726 )
TypeError: Exception encountered when calling layer 'keras_layer' (type KerasLayer).
_build_expression() got an unexpected keyword argument 'dtype'
Call arguments received by layer 'keras_layer' (type KerasLayer):
• inputs=tf.Tensor(shape=(5, 2), dtype=float64)
Is there a certain method to use default.tensor with tf?
Is there perhaps an example on using default.tensor in a tf environment?
I am running this on google colab but I get the same error on my own venv and on an ssh server.
Thank you in advance for the help.
This is my qml.about:
Name: PennyLane
Version: 0.39.0
Summary: 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.
Home-page: https://github.com/PennyLaneAI/pennylane
Author:
Author-email:
License: Apache License 2.0
Location: /usr/local/lib/python3.10/dist-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, packaging, pennylane-lightning, requests, rustworkx, scipy, toml, typing-extensions
Required-by: PennyLane_Lightning
Platform info: Linux-6.1.85+-x86_64-with-glibc2.35
Python version: 3.10.12
Numpy version: 1.26.4
Scipy version: 1.13.1
Installed devices:
- lightning.qubit (PennyLane_Lightning-0.39.0)
- default.clifford (PennyLane-0.39.0)
- default.gaussian (PennyLane-0.39.0)
- default.mixed (PennyLane-0.39.0)
- default.qubit (PennyLane-0.39.0)
- default.qutrit (PennyLane-0.39.0)
- default.qutrit.mixed (PennyLane-0.39.0)
- default.tensor (PennyLane-0.39.0)
- null.qubit (PennyLane-0.39.0)
- reference.qubit (PennyLane-0.39.0)