Unused parameters for the quantum layer in keras hybrid model

Hello!
I tried adding forward pass through my model before printing the summary but I encounter this error:

InvalidArgumentError: Exception encountered when calling layer "keras_layer" (type KerasLayer).

slice index 10 of dimension 0 out of bounds. [Op:StridedSlice] name: sequential/keras_layer/strided_slice/

Call arguments received:
inputs=tf.Tensor(shape=(2, 48, 1), dtype=float32)

This is the shape of my data:

print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
(1709, 48, 1) (1709, 24) (427, 48, 1) (427, 24)

This is my model:

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Input(shape=()))
model.add(qlayer)
model.add(tf.keras.layers.Reshape((48,32)))
model.add(tf.keras.layers.GRU(units=36, return_sequences=True, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.GRU(units=36, return_sequences=True))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.GRU(units=24))
model.add(tf.keras.layers.Dense(units=24))
model(X_test[:2])

And this is my qlayer:

n_qubits = 10
dev = qml.device("default.qubit.tf", wires=n_qubits) 
@qml.qnode(dev)
def qnode(inputs,weights_0,weights_1,weights_2,weights_3):
    for i in range(10):
        qml.RY(np.arctan(inputs[i]),wires=i) 
        qml.Hadamard(i)
        qml.RX(np.arctan(inputs[10+i]),wires=i) 
    
    qml.CNOT(wires=[0, 1])
    qml.CNOT(wires=[2, 3])
    qml.CNOT(wires=[4, 5])
    qml.CNOT(wires=[6, 7])
    qml.CNOT(wires=[8, 9])
    for i in range(10): 
        qml.RZ(np.arctan(inputs[20+i]),wires=i) 
    
    for j,w in enumerate(weights_0): 
        qml.RY(w, wires=j)   
        
    qml.CNOT(wires=[0, 1])
    
    qml.CNOT(wires=[4, 3])
    
    qml.CNOT(wires=[3, 2])    
    
    qml.CNOT(wires=[2, 1])
    
    list_index = [1,3,5,7,9]
    for j,w in enumerate(weights_1):
        qml.RY(w, wires=list_index[j])      
        

    qml.Hadamard(1)
    qml.Hadamard(3)
    qml.Hadamard(5)
    qml.Hadamard(7)
    qml.Hadamard(9)
    
    for j,w in enumerate(weights_2):
        qml.RX(w, wires=j)
    
    qml.CNOT(wires=[0, 1])
    
    qml.CNOT(wires=[4, 3])
    
    qml.CNOT(wires=[3, 2])    
    
    qml.CNOT(wires=[2, 1])
    
    list_index = [1,3,5,7,9]
    for j,w in enumerate(weights_3):
        qml.RX(w, wires=list_index[j])     
        
    qml.Hadamard(1)
    qml.Hadamard(3)
    qml.Hadamard(5)
    qml.Hadamard(7)
    qml.Hadamard(9)
    return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1)), qml.expval(qml.PauliZ(2)), qml.expval(qml.PauliZ(3)), qml.expval(qml.PauliZ(4)),qml.expval(qml.PauliZ(5)), qml.expval(qml.PauliZ(6)), qml.expval(qml.PauliZ(7)), qml.expval(qml.PauliZ(8)), qml.expval(qml.PauliZ(9))
        
weight_shapes = {"weights_0": 10, "weights_1": 5, "weights_2": 10, "weights_3": 5}#,"weights_5": 1,"weights_6": 1,"weights_7": 1,"weights_8": 1,"weights_9": 1}
qlayer = qml.qnn.KerasLayer(qnode, weight_shapes, output_dim=(48,32))

I’m not sure if my output shape is correct because when I try to fit my model, I get this error:

InvalidArgumentError: Exception encountered when calling layer "keras_layer" (type KerasLayer).

slice index 10 of dimension 0 out of bounds. [Op:StridedSlice] name: sequential_1/keras_layer/strided_slice/

Call arguments received:
inputs=tf.Tensor(shape=(32, 48, 1), dtype=float32)

More information about the error:

<ipython-input-10-3e198aa82acd> in qnode(inputs, weights_0, weights_1, weights_2, weights_3)
     11         qml.RY(np.arctan(inputs[i]),wires=i) #first 10 inputs apply in ry
     12         qml.Hadamard(i)
---> 13         qml.RX(np.arctan(inputs[10+i]),wires=i) #the 10-20 inputs apply in rx
     14 
     15     qml.CNOT(wires=[0, 1])

InvalidArgumentError: Exception encountered when calling layer "keras_layer" (type KerasLayer).

slice index 10 of dimension 0 out of bounds. [Op:StridedSlice] name: sequential_1/keras_layer/strided_slice/

Call arguments received:
  • inputs=tf.Tensor(shape=(32, 48, 1), dtype=float32)

Hi @aouie, it’s hard to tell for sure what’s going on but my impression is that you have an “inputs” parameter that goes into your qnode, but when you create the qlayer you only add the weight shapes so the qnode is getting confused there. I would suggest creating a minimum example in a few lines so that you can understand where the error comes from and it will make it easier for us to help you too.

I am trying this one but I changed the dataset that I am using, also, I am using 10 qubits.
Quantum-Counselor-for-Portfolio-Investment/pennylane_stock_price_hybrid_algorithm.ipynb at main · alejomonbar/Quantum-Counselor-for-Portfolio-Investment · GitHub

I am trying this because I want to perform Ry in the first 30% of my data, followed by Rx (second 30%) and Rz for the last 40%

Hi @aouie, from what I can see in their code they are also using 10 qubits. They have built their code for data that has a similar shape to theirs so you might have to seriously modify their code in order to run it with a very different data shape such as yours.

I think the best option for you is to modify your dataset so that it looks similar to theirs. First run their code with your modified data and then if it works try to add one new change at a time.

Okay! Thank you for that!

Hi @aouie , I’m having the same problem, the qlayer is being added exactly, but through model.summary(), I find that the qlayer parameter is not being used. Can you please tell me if you found a solution? The reason for this is that the classification accuracy is very low and I don’t know how to get the parameters enabled correctly.
image

Hi @RX1 ,

The “parameters unused” issue can be fixed by doing a forward pass through the model before printing the summary.

You can check the code example I shared here.

I hope this helps!

Hi @CatalinaAlbornoz Thanks for your reply, I copied your DEMO and modified my case and the result parameter is still unused.

import pennylane as qml
from pennylane import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

tf.keras.backend.set_floatx('float64')

num_modes = 4
dim = int(num_modes / 2)
cutoff_dim = 10

dev = qml.device('strawberryfields.tf', wires=num_modes, cutoff_dim=cutoff_dim)

def encode_data(inputs, params, reg):
    for i in range(dim):
        qml.Squeezing(params[i], 0.0, wires=i + reg * dim)
        qml.Displacement(inputs[i], 0.0, wires=i + reg * dim)

@qml.qnode(dev, interface='tf', diff_method='backprop')
def Circuit(inputs, params):
    encode_data(inputs[:dim], params[:dim], 0)

    encode_data(inputs[dim:num_modes], params[dim:2*dim], 1)

    for i in range(dim):
        qml.Beamsplitter(params[2*dim + i],0, wires=[i, i + dim])

    return qml.expval(qml.X(wires=num_modes - 1)) 

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

train_filter = (y_train == 0) | (y_train == 1)
test_filter = (y_test == 0) | (y_test == 1)
x_train, y_train = x_train[train_filter], y_train[train_filter]
x_test, y_test = x_test[test_filter], y_test[test_filter]
x_train = x_train[:500]
y_train = y_train[:500]
x_test = x_test[:100]
y_test = y_test[:100]

x_train = x_train.astype('float64') / 255.0
x_test = x_test.astype('float64') / 255.0
x_train = x_train.reshape((-1, 28 * 28))
x_test = x_test.reshape((-1, 28 * 28))

pca = PCA(n_components=num_modes)
x_train_pca = pca.fit_transform(x_train)
x_test_pca = pca.transform(x_test)

x_train_pca = x_train_pca.astype('float64')
x_test_pca = x_test_pca.astype('float64')


clayer1 = layers.InputLayer(input_shape=(4,))

qlayer = qml.qnn.KerasLayer(Circuit, weight_shapes={"params": [3 * dim,]}, output_dim=1)

#clayer2 = layers.Reshape((1,))
clayer3 = layers.Dense(1, activation='sigmoid')

# Add quantum layer to your model
model = tf.keras.models.Sequential([clayer1, qlayer, clayer3])

model.add(clayer1)

model.add(qlayer)

model.add(clayer3)
                         

for layer in model.layers:
    print(layer.name, layer.trainable)

model.summary()

Hi @RX1 .

The error you’re getting is because you’re missing the actual execution of the model. So something like model(x_train_pca) before you print the model summary. That’s what I meant before.

However upon trying to add it for you I noticed that I got some package conflicts. Even the code in the link I shared doesn’t work anymore. It looks like PennyLane, the PennyLane-SF plugin and TensorFlow can’t agree on versions of some other package in my environment. So unfortunately I don’t have any ideas on how to fix it but you can test running the model in your environment and if it runs then you know you have the right combination of libraries.

If someone else in the community knows how to get these libraries to agree please post a suggestion here!