Issue with the set_weights in qml.qnn keras quantum layer

I am working with the hybrid version [clayer1, qlayer, clayer2] MNIST digits. There are two issues:

  1. When i print summary of the model. It shows “unused” in front of qlayer in the summary table of the model.
  2. I used get_weights, it shows len=5 in weight list. And on using set_weights, it says that model is expecting 4 weights instead of 5.

How can we have same shape and length of model weights before and after training?
code of the model is as:

n_qubits = 2
num_layers = 1

#qml.enable_tape()

dev = qml.device(“default.qubit”, wires = n_qubits)

@qml.qnode(dev, interface=“tf”, diff_method=“backprop”)
def circuit(inputs, weights):

qml.templates.AngleEmbedding(inputs, wires=range(n_qubits))
qml.templates.BasicEntanglerLayers(weights, wires=range(n_qubits))
return [qml.expval(qml.PauliZ(wires=i)) for i in range(n_qubits)]

class Simple:
@staticmethod
def build(shape):

    n_qubits = 2
    num_layers = 1

    weight_shapes = {"weights": (num_layers,n_qubits)}
 
    tf.keras.backend.set_floatx('float64')

    clayer1 = tf.keras.layers.Dense(2, input_shape=(shape,))

    qlayer = qml.qnn.KerasLayer(circuit, weight_shapes, output_dim=n_qubits)

    clayer2 = tf.keras.layers.Dense(2, activation='softmax',)

    model = tf.keras.models.Sequential([clayer1, qlayer, clayer2])

    return model

smlp = Simple()
model = smlp.build(X_train.shape[1])

Model: “sequential_1”


Layer (type) Output Shape Param #

dense_2 (Dense) (None, 2) 6

keras_layer_1 (KerasLayer) (None, 2) 0 (unused)

dense_3 (Dense) (None, 2) 6

=================================================================
Total params: 12
Trainable params: 12
Non-trainable params: 0

print(“Weights and biases of the layers BEFORE training the model: \n”)
for layer in model.layers:
print(layer.name)
print(“Weights”)
print("Shape: ",‘\n’,layer.get_weights())

weights = model.get_weights()
print(“len of weights BEFORE”, len(weights))

model.compile(optimizer, loss, metrics)

fitting = model.fit(X_train, y_train, epochs=1, batch_size=5)

weights = model.get_weights()
print(“len of weights AFTER”, len(weights))

print(“Weights and biases of the layers AFTER training the model: \n”)
for layer in model.layers:
print(layer.name)
print(“Weights”)
print("Shape: ",‘\n’,layer.get_weights())

Hi @Amandeep,

This can be fixed by doing a forward pass through the model before printing the summary, e.g:

from sklearn.datasets import make_moons

import pennylane as qml

import tensorflow as tf

X_train, y = make_moons(n_samples=200, noise=0.1)

n_qubits = 2

num_layers = 1

dev = qml.device('default.qubit', wires = n_qubits)

@qml.qnode(dev, interface='tf', diff_method='backprop')

def circuit(inputs, weights):

    qml.templates.AngleEmbedding(inputs, wires=range(n_qubits))

    qml.templates.BasicEntanglerLayers(weights, wires=range(n_qubits))

    return [qml.expval(qml.PauliZ(wires=i)) for i in range(n_qubits)]

shape = X_train.shape[1]

n_qubits = 2

num_layers = 1

weight_shapes = {"weights": (num_layers,n_qubits)}

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

clayer1 = tf.keras.layers.Dense(2, input_shape=(shape,))

qlayer = qml.qnn.KerasLayer(circuit, weight_shapes, output_dim=n_qubits)

clayer2 = tf.keras.layers.Dense(2, activation='softmax',)

model = tf.keras.models.Sequential([clayer1, qlayer, clayer2])

# Add a forward pass before printing summary

model.add(clayer1)

model.add(qlayer)

model.add(clayer2)

model(X_train[:2])

model.summary()

I hope this helps!

@CatalinaAlbornoz Yes, it worked. Thank you so much.

1 Like

@CatalinaAlbornoz

weights_shape = (5,10,2)  
tf.keras.backend.set_floatx("float64")
weight_shapes = {"weights": weights_shape}
        
opt = tf.keras.optimizers.Adam(learning_rate=lr)

qlayer = qml.qnn.KerasLayer(circuit, weight_shapes, 10)

modelh = tf.keras.models.Sequential([qlayer])

modelh.compile(opt, loss=square_loss, metrics=[CustomAccuracy()])
       
modelh.build(input_shape=X_client.shape)
        
modelh.add(qlayer)

modelh.set_weights(params)

and i used my params as params=np.load(“mnist_params01_5lyr.npy”)

my question i have only one qlyare, it worked. the thing is that i want to intialize it with my own paramters from npy file. but it gives an error ValueError: You called set_weights(weights) on layer “sequential_31” with a weight list of length 5, but the layer was expecting 0 weights. Provided weights: [[[2.56678375e-01 6.46252474e-01]
[5.11058376e-0…

Hi @Amandeep ,

It’s hard to help you with the information provided because the code you shared doesn’t include all of the information necessary to reproduce the error.

Could you please provide the following information?

  1. The output of qml.about()

  2. A minimal (but self-contained) working example
    This is the simplest version of the code that reproduces the problem. It should include all necessary imports, data, functions, etc., so that we can copy-paste the code and reproduce the problem. However it shouldn’t contain any unnecessary data, functions, …, for example gates and functions that can be removed to simplify the code.

  3. The full error traceback (or the result you get in case there’s no error).

Please make sure to check out this video to understand what we mean with each of these items.

Note: When sharing code it’s of great help when you use the code-formatting options provided here in the Forum. When you create a post here you can use the </> icon to format something as code. You can find it right at the top of the text box where you write your question. I would recommend that you try clicking this on an empty line, and then add your code where it says “type or paste code here”. Let me know if you have any questions about this!