Hi Pennylane devs/support team,
I’m working in a team on a project to evaluate how efficient VQCs are for predicting future points in time series, but we struggle with the interface between pennylane and TensorFlow because it’s our first time working with it. I saw other questions about batches, but I’m unsure if they are totally related, so I wanted to create my own topic.
The current goal is to implement a tf model that takes a qml circuit to train on a dataset and make predictions on it. We have a hybrid model that works fine with the integrated quantum layers, but when I start on implementing a model that takes a circuit as input, I realize that the input/output shapes are not trivial. The only config that worked was for one batch or when using a LSTM layer beforehand. The optimal goal would be a tf model that looks like this:
def create_pvc_model(self, circuit, config):
inputs = Input(shape=(config['time_steps'], 1))
qlayer = qml.qnn.KerasLayer(circuit.run(), circuit.get_weights(), output_dim=1)(dense1)
output = Dense(config['future_steps'], activation='linear')(qlayer)
model = Model(inputs=inputs, outputs=output)
model.compile(optimizer=Adam(learning_rate=config['learning_rate']),
loss=config['loss_function'])
return model
Because we might use circuits that have a different amount of wires than the Input/Output size, I added layers to adapt to the right size. There might be a more elegant way to archive this, but my first intuition looked like this:
def create_pvc_model(self, circuit, config):
inputs = Input(shape=(config['time_steps'], 1))
dense1 = Dense(circuit.get_wires(), activation='relu')(inputs)
qlayer = qml.qnn.KerasLayer(circuit.run(), circuit.get_weights(), output_dim=1)(dense1)
qlayer = tf.reshape(qlayer, (-1, 1))
output = Dense(config['future_steps'], activation='linear')(qlayer)
model = Model(inputs=inputs, outputs=output)
model.compile(optimizer=Adam(learning_rate=config['learning_rate']),
loss=config['loss_function'])
return model
To give a better idea, the very basic example circuit looked like this:
class new_RYXZ_Circuit(BaseCircuit):
def __init__(self):
super().__init__()
self.weight_shapes = {"weights_0": (1,), "weights_1": (1,), "weights_2": (1,)}
self.n_wires = 1
def run(self):
training_device = qml.device("default.qubit", wires=self.n_wires)
@qml.qnode(training_device, interface='tf', diff_method='backprop')
def _circuit(inputs, weights_0, weights_1, weights_2):
qml.RY(inputs[0], wires=0)
qml.RX(weights_0, wires=0)
qml.RY(weights_1, wires=0)
qml.RZ(weights_2, wires=0)
return qml.expval(qml.PauliZ(wires=0))
return _circuit
def get_weights(self):
return self.weight_shapes
def get_wires(self):
return self.n_wires
We tried a number of different changes but feel overwhelmed because we can’t grape the underlying structure when and when not the shapes changes. The general error always looks like this:
tensorflow.python.framework.errors_impl.InvalidArgumentError: Exception encountered when calling layer 'keras_layer' (type KerasLayer).
{{function_node __wrapped__Reshape_device_/job:localhost/replica:0/task:0/device:CPU:0}} Input to reshape is a tensor with 1 values, but the requested shape has 3200 [Op:Reshape] name:
Call arguments received by layer 'keras_layer' (type KerasLayer):
• inputs=tf.Tensor(shape=(64, 50, 1), dtype=float32)
I’m still unsure if the problem is trivial or if there are fundamental limits to what we can do with our general idea. It would help a lot if you could point us in the right direction or suggest an alternative way of implementing the concept that perhaps circumvents the issue. I’m saying thanks in advance, any help might bring us far enough to get the gears running again.
I will link all relevant scripts if you want to take a closer look, some modules might need to be imported but should be trivial:
predict_pipeline.py (4.2 KB)
predict_iterative_forecasting.py (1.3 KB)
predict_plots_and_metrics.py (5.3 KB)
predict_variable_circuit_model.py (2.4 KB)
predict_hybrid_model.py (3.3 KB)
dataset_manager.py (5.4 KB)
variable_circuit.py (2.0 KB)
qml.about()
:
Name: PennyLane
Version: 0.36.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: GitHub - 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.
Author:
Author-email:
License: Apache License 2.0
Location: C:\Users\TomBi\PycharmProjects\ProbDist_QCP2\VQC_project\desktop_venv\Lib\site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane_Lightning
Platform info: Windows-10-10.0.22621-SP0
Python version: 3.11.8
Numpy version: 1.26.4
Scipy version: 1.13.1
Installed devices:
- default.clifford (PennyLane-0.36.0)
- default.gaussian (PennyLane-0.36.0)
- default.mixed (PennyLane-0.36.0)
- default.qubit (PennyLane-0.36.0)
- default.qubit.autograd (PennyLane-0.36.0)
- default.qubit.jax (PennyLane-0.36.0)
- default.qubit.legacy (PennyLane-0.36.0)
- default.qubit.tf (PennyLane-0.36.0)
- default.qubit.torch (PennyLane-0.36.0)
- default.qutrit (PennyLane-0.36.0)
- default.qutrit.mixed (PennyLane-0.36.0)
- null.qubit (PennyLane-0.36.0)
- lightning.qubit (PennyLane_Lightning-0.36.0)