Creating Quantum Layer for keras tensor input

Hello! I am having trouble passing my ‘keras tensor’ into qnode. Here is the code:
#this is the input to quantum node

    n_qubits = 8
    n_layers = 1       
    dev = qml.device("default.qubit", wires=n_qubits)
    tf.keras.backend.set_floatx('float32')
    @qml.qnode(dev, interface = 'tf')
    def circuit(inputs):    
        qml.AmplitudeEmbedding(features=inputs, wires=range(8), pad_with=0., normalize=True)
        qml.AngleEmbedding(inputs, wires=range(n_qubits))
        return qml.expval(qml.PauliZ(0))

     #As my input is large, I am flattening it and taking part of input (p1[0]) to see if it works
     a_cl = Flatten()(cl_input)   # 'cl_input' is of type <keras tensor> & has shape (None, 73,128) ---> 'a_cl' is of type <keras tensor> & has shape (None, 73*128)
       
     p1 = tf.split(a, num_or_size_splits=128, axis = -1) 
     q_input = p1[0]        #<keras tensor> & has shape (None, 73)               
     q_out = circuit(q_input)

I am facing the following error:

File “C:\Users\vaishnavi.chandilkar\Downloads\MolNet-2\model\model.py”, line 166, in model_molnet
q_out = circuit(q_input)
File “C:\Users\vaishnavi.chandilkar\Anaconda3\envs\maus\lib\site-packages\pennylane\qnode.py”, line 800, in call
self.construct(args, kwargs)
File “C:\Users\vaishnavi.chandilkar\Anaconda3\envs\maus\lib\site-packages\pennylane\qnode.py”, line 711, in construct
self._tape = make_qscript(self.func)(*args, **kwargs)
File “C:\Users\vaishnavi.chandilkar\Anaconda3\envs\maus\lib\site-packages\pennylane\tape\qscript.py”, line 1346, in wrapper
result = fn(*args, **kwargs)
File “C:\Users\vaishnavi.chandilkar\Downloads\MolNet-2\model\model.py”, line 136, in circuit
qml.AmplitudeEmbedding(features=inputs, wires=range(8), pad_with=0., normalize=True)
File “C:\Users\vaishnavi.chandilkar\Anaconda3\envs\maus\lib\site-packages\pennylane\templates\embeddings\amplitude.py”, line 129, in init
features = self._preprocess(features, wires, pad_with, normalize)
File “C:\Users\vaishnavi.chandilkar\Anaconda3\envs\maus\lib\site-packages\pennylane\templates\embeddings\amplitude.py”, line 180, in _preprocess
batched = qml.math.ndim(features) > 1
File “C:\Users\vaishnavi.chandilkar\Anaconda3\envs\maus\lib\site-packages\autoray\autoray.py”, line 79, in do
return get_lib_fn(backend, fn)(*args, **kwargs)
File “C:\Users\vaishnavi.chandilkar\Anaconda3\envs\maus\lib\site-packages\autoray\autoray.py”, line 433, in get_lib_fn
lib_fn = import_lib_fn(backend, fn)
File “C:\Users\vaishnavi.chandilkar\Anaconda3\envs\maus\lib\site-packages\autoray\autoray.py”, line 406, in import_lib_fn
raise ImportError(
ImportError: autoray couldn’t find function ‘ndim’ for backend ‘keras’.

Why does qnode not take keras tensor? Can anyone tell me which type should i convert my data to , so that it works fine!?

Hey @Nina!

There’s a couple problems with the code example you attached:

  1. You use two embedding procedures on the same set of inputs:

    qml.AmplitudeEmbedding(features=inputs, wires=range(8), pad_with=0., normalize=True)
    qml.AngleEmbedding(inputs, wires=range(n_qubits))
    

    I would stick to one.

  2. If you want to use Amplitude embedding, then the circuit must, given the classical inputs that you want to embed, have \log_2(\texttt{len(inputs)}) qubits (round up as needed). For your input data which is 73 by 128, \log_2(73\times 128) \approx 13.1, meaning you’ll need 14 qubits.

  3. If you want to use Angle embedding, then the circuit must, given the classical inputs you want to embed, have n_qubits = len(inputs) — each input is embedded into the circuit as a rotation gate on a qubit.

Here’s a code example that works:

import pennylane as qml
import tensorflow as tf

n_qubits = 8
dev = qml.device("default.qubit", wires=n_qubits)
tf.keras.backend.set_floatx('float32')

@qml.qnode(dev, interface = 'tf')
def circuit(inputs):
    qml.AngleEmbedding(inputs, wires=range(n_qubits))
    return qml.expval(qml.PauliZ(0))

inputs = tf.random.uniform(
    (2, 4), # here, the total number of inputs (8) equals n_qubits — I can use Angle embedding with 8 qubits.
    minval=0,
    maxval=None,
    dtype=tf.dtypes.float32,
    seed=None,
    name=None
)

print(inputs) 
'''
tf.Tensor(
[[0.6023785  0.7045171  0.1547221  0.8907907 ]
 [0.92709446 0.8886298  0.9490975  0.03580618]], shape=(2, 4), dtype=float32)
'''
inputs = inputs.numpy() # I find it easier to convert things to numpy arrays for, e.g., reshaping.
print(inputs)
'''
[[0.6023785  0.7045171  0.1547221  0.8907907 ]
 [0.92709446 0.8886298  0.9490975  0.03580618]]
'''

>>> circuit(inputs.reshape(-1)) # flattens the inputs to a 1D array
tf.Tensor(0.8239902865173543, shape=(), dtype=float64)
1 Like

Thank you @isaacdevlugt for the answer!! I understood the concept now clearly with your example.

Glad this works! Let us know if you have any more problems :rocket: