My input shape is 80,2 . During 2nd epoch, layer is getting input 10,4. how the features are 4 when only 2 features are given

Hello! If applicable, put your complete code example down below. Make sure that your code:

  • is 100% self-contained — someone can copy-paste exactly what is here and run it to
    reproduce the behaviour you are observing
  • includes comments
# Put code here
import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import pennylane as qml

# Perform label encoding on y_train
le = LabelEncoder()

# Load and preprocess the dataset
X = dataset.iloc[:, 0:-1]
y = dataset['Churn']
scaler = StandardScaler()
X = scaler.fit_transform(X)
y = le.fit_transform(y)

# Split the dataset into training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Perform PCA on the training and test sets
pca = PCA(n_components=2)
X_train = pca.fit_transform(X_train)
X_test = pca.transform(X_test)

n_classes = len(np.unique(y))
n_qubits = X_train.shape[1]
n_layers = 3
n_wires=2

print("X_train shape:", X_train.shape)
print("X_test shape:", X_test.shape)
print("y_train shape:", y_train.shape)
print("y_test shape:", y_test.shape)
print("n_classes:", n_classes)
print("n_qubits:", n_qubits)

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

@qml.qnode(dev)
def quantum_model(inputs, weights):
  reshaped_inputs = tf.reshape(inputs, (-1, n_qubits))  # Reshape inputs to (batch_size, n_qubits)
  print("Shape of inputs:", reshaped_inputs.shape)
  qml.templates.AngleEmbedding(reshaped_inputs, wires=range(n_qubits))
  qml.templates.StronglyEntanglingLayers(weights, wires=range(n_qubits))
  return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]


weight_shapes = {"weights": (n_layers, n_wires, 3)}
quantum_layer = qml.qnn.KerasLayer(quantum_model, weight_shapes=weight_shapes, output_dim=n_qubits)

classical_model = tf.keras.Sequential([
    tf.keras.layers.Dense(4, activation='relu', input_dim=n_qubits, trainable=False),
    tf.keras.layers.Dense(n_classes, activation='softmax')
])
# Build the hybrid model
model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(4, activation='relu', input_dim=n_qubits, trainable=False),
    quantum_layer,
    classical_model
])

# Add print statements to check the shape of inputs at different stages
print("Shape of inputs before quantum layer:", model.layers[1].input_shape)
print("Shape of inputs after quantum layer:", model.layers[1].output_shape)


model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

history = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3, batch_size=10)

loss, accuracy = model.evaluate(X_test, y_test)
print("Loss:", loss)
print("Accuracy:", accuracy)

If you want help with diagnosing an error, please put the full error message below:

# Put full error message here
X_train shape: (80, 2)
X_test shape: (20, 2)
y_train shape: (80,)
y_test shape: (20,)
n_classes: 2
n_qubits: 2
Shape of inputs before quantum layer: (None, 4)
Shape of inputs after quantum layer: (None, 2)
Epoch 1/3
Shape of inputs: (20, 2)
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-5-c909f42750cc> in <cell line: 71>()
     69 model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
     70 
---> 71 history = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3, batch_size=10)
     72 
     73 loss, accuracy = model.evaluate(X_test, y_test)

7 frames
/usr/local/lib/python3.10/dist-packages/pennylane/math/utils.py in requires_grad(tensor, interface)
    456             from tensorflow.python.eager.tape import should_record_backprop
    457         except ImportError:  # pragma: no cover
--> 458             from tensorflow.python.eager.tape import should_record as should_record_backprop
    459 
    460         return should_record_backprop([tf.convert_to_tensor(tensor)])

ImportError: Exception encountered when calling layer 'keras_layer' (type KerasLayer).

cannot import name 'should_record' from 'tensorflow.python.eager.tape' (/usr/local/lib/python3.10/dist-packages/tensorflow/python/eager/tape.py)

Call arguments received by layer 'keras_layer' (type KerasLayer):
  • inputs=tf.Tensor(shape=(10, 4), dtype=float32)

And, finally, make sure to include the versions of your packages. Specifically, show us the output of qml.about().

Name: PennyLane
Version: 0.31.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: GitHub - PennyLaneAI/pennylane: PennyLane is a cross-platform Python library for differentiable programming of quantum computers. Train a quantum computer the same way as a neural network.
Author:
Author-email:
License: Apache License 2.0
Location: /usr/local/lib/python3.10/dist-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning, PennyLane-qiskit

Platform info: Linux-5.15.107±x86_64-with-glibc2.31
Python version: 3.10.12
Numpy version: 1.22.4
Scipy version: 1.10.0
Installed devices:

  • default.gaussian (PennyLane-0.31.0)
  • default.mixed (PennyLane-0.31.0)
  • default.qubit (PennyLane-0.31.0)
  • default.qubit.autograd (PennyLane-0.31.0)
  • default.qubit.jax (PennyLane-0.31.0)
  • default.qubit.tf (PennyLane-0.31.0)
  • default.qubit.torch (PennyLane-0.31.0)
  • default.qutrit (PennyLane-0.31.0)
  • null.qubit (PennyLane-0.31.0)
  • lightning.qubit (PennyLane-Lightning-0.31.0)
  • qiskit.aer (PennyLane-qiskit-0.31.0)
  • qiskit.basicaer (PennyLane-qiskit-0.31.0)
  • qiskit.ibmq (PennyLane-qiskit-0.31.0)
  • qiskit.ibmq.circuit_runner (PennyLane-qiskit-0.31.0)
  • qiskit.ibmq.sampler (PennyLane-qiskit-0.31.0)
  • qiskit.remote (PennyLane-qiskit-0.31.0)

Tensorflow version: 2.13.0
PennyLane version: 0.31.0

Hey @Codec! Welcome to the forum :grin:

I’m unable to replicate the behaviour because I don’t have access to dataset. That said, it would be helpful if you could distill your code down to something smaller that still replicates the behaviour that you’re seeing :slight_smile:.

Look forward to hearing back!

import numpy as np
import tensorflow as tf
import pennylane as qml
import pandas as pd

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

np.random.seed(42)

X = np.column_stack((np.random.rand(10), np.random.rand(10)))
y = np.random.randint(0, 2, 10)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

print("X_train shape:", X_train.shape)
print("X_test shape:", X_test.shape)
print("y_train shape:", y_train.shape)
print("y_test shape:", y_test.shape)

n_classes = 2
n_qubits = 2
n_layers = 3
n_wires = 2
dev = qml.device("default.qubit", wires=n_qubits)


@qml.qnode(dev)
def quantum_model(inputs, weights):
    reshaped_inputs = tf.reshape(
        inputs, (-1, n_qubits)
    )  # Reshape inputs to (batch_size, n_qubits)
    print("Shape of inputs:", reshaped_inputs.shape)
    qml.templates.AngleEmbedding(reshaped_inputs, wires=range(n_qubits))
    qml.templates.StronglyEntanglingLayers(weights, wires=range(n_qubits))
    return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]


weight_shapes = {"weights": (n_layers, n_wires, 3)}
quantum_layer = qml.qnn.KerasLayer(
    quantum_model, weight_shapes=weight_shapes, output_dim=n_qubits
)

classical_model = tf.keras.Sequential(
    [
        tf.keras.layers.Dense(
            4, activation="relu", input_dim=n_qubits, trainable=False
        ),
        tf.keras.layers.Dense(n_classes, activation="softmax"),
    ]
)
model = tf.keras.models.Sequential(
    [
        tf.keras.layers.Dense(
            4, activation="relu", input_dim=n_qubits, trainable=False
        ),
        quantum_layer,
        classical_model,
    ]
)
print("Shape of inputs before quantum layer:", model.layers[1].input_shape)
print("Shape of inputs after quantum layer:", model.layers[1].output_shape)

model.compile(
    loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
)
history = model.fit(
    X_train, y_train, validation_data=(X_test, y_test), epochs=3, batch_size=10
)
loss, accuracy = model.evaluate(X_test, y_test)
print("Loss:", loss)
print("Accuracy:", accuracy)

Error:

---------------------------------------------------------------------------
X_train shape: (8, 2)
X_test shape: (2, 2)
y_train shape: (8,)
y_test shape: (2,)
Shape of inputs before quantum layer: (None, 4)
Shape of inputs after quantum layer: (None, 2)
Epoch 1/3
Shape of inputs: (16, 2)
ImportError                               Traceback (most recent call last)
<ipython-input-15-8e23ca24341f> in <cell line: 52>()
     50 model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
     51 
---> 52 history = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3, batch_size=10)
     53 
     54 loss, accuracy = model.evaluate(X_test, y_test)

7 frames
/usr/local/lib/python3.10/dist-packages/pennylane/math/utils.py in requires_grad(tensor, interface)
    456             from tensorflow.python.eager.tape import should_record_backprop
    457         except ImportError:  # pragma: no cover
--> 458             from tensorflow.python.eager.tape import should_record as should_record_backprop
    459 
    460         return should_record_backprop([tf.convert_to_tensor(tensor)])

ImportError: Exception encountered when calling layer 'keras_layer_10' (type KerasLayer).

cannot import name 'should_record' from 'tensorflow.python.eager.tape' (/usr/local/lib/python3.10/dist-packages/tensorflow/python/eager/tape.py)

Call arguments received by layer 'keras_layer_10' (type KerasLayer):
  • inputs=tf.Tensor(shape=(8, 4), dtype=float32)

Ah! Your Dense layer was giving the wrong output dimension I think. This works for me:

import numpy as np
import tensorflow as tf
import pennylane as qml
import pandas as pd

from sklearn.model_selection import train_test_split

np.random.seed(42)

X = np.column_stack((np.random.rand(10), np.random.rand(10)))
y = np.random.randint(0, 2, 10)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
n_classes = 2
n_qubits = 2
n_layers = 3
n_wires = n_qubits
dev = qml.device("default.qubit", wires=n_qubits)


@qml.qnode(dev)
def quantum_model(inputs, weights):
    reshaped_inputs = tf.reshape(
        inputs, (-1, n_qubits)
    )  # Reshape inputs to (batch_size, n_qubits)
    qml.AngleEmbedding(inputs, wires=range(n_qubits))
    qml.StronglyEntanglingLayers(weights, wires=range(n_qubits))
    return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]


weight_shapes = {"weights": (n_layers, n_wires, 3)}
quantum_layer = qml.qnn.KerasLayer(
    quantum_model, weight_shapes=weight_shapes, output_dim=n_qubits
)

inputs = tf.random.uniform((4, n_qubits), 0, 1)
print(quantum_layer(inputs))
tf.Tensor(
[[0.8233045  0.80168208]
 [0.79503844 0.70124516]
 [0.71959265 0.56604748]
 [0.7649981  0.36067211]], shape=(4, 2), dtype=float64)
classical_model = tf.keras.Sequential(
    [
        tf.keras.layers.Dense(
            4, activation="relu", input_dim=n_qubits, trainable=False
        ),
        tf.keras.layers.Dense(n_classes, activation="softmax"),
    ]
)
model = tf.keras.models.Sequential(
    [
        tf.keras.layers.Dense(
            n_qubits, activation="relu", input_dim=n_qubits, trainable=False
        ),
        quantum_layer,
        classical_model,
    ]
)

model.compile(
    loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
)
classical_model.compile(
    loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
)

You can verify step-by-step:

print(X_test)
out1 = model.layers[0](X_test)
print("1:", out1)
out2 = model.layers[1](out1)
print("2:", out2)
out3 = model.layers[2](out2)
print("3:", out3)
[[0.87747201 0.77641296]
 [0.84487531 0.28203457]]
1: tf.Tensor(
[[1.1958935  0.01984999]
 [0.81852925 0.        ]], shape=(2, 2), dtype=float32)
Shape of inputs: (2, 2)
2: tf.Tensor(
[[0.69075722 0.79587207]
 [0.77382291 0.85517834]], shape=(2, 2), dtype=float64)
3: tf.Tensor(
[[0.44584155 0.55415845]
 [0.4430462  0.5569537 ]], shape=(2, 2), dtype=float32)
loss, accuracy = model.evaluate(X_test, y_test)
print("Loss:", loss)
print("Accuracy:", accuracy)
1/1 [==============================] - 0s 99ms/step - loss: 0.6965 - accuracy: 0.5000
Loss: 0.6965323686599731
Accuracy: 0.5

Hope this helps!

Thank you @isaacdevlugt :slight_smile: . Why we need to compile classical_model when we are compiling the hybrid “model”.

Hi, I’m a different user but I tried running your code because I have the same ImportError: ImportError: Exception encountered when calling layer ‘keras_layer_10’ (type KerasLayer).

cannot import name ‘should_record’ from ‘tensorflow.python.eager.tape’ . I am trying to run the code on IBM Qiskit’s online compiler. I also tried JUST the import statement that threw the error i.e. from tensorflow.python.eager.tape import should_record but that also gave me the exact same error. Please help.

Why we need to compile classical_model when we are compiling the hybrid “model”.

Oops! I was doing some debugging and wanted to just look at the classical model :sweat_smile:. Forgot to delete that in my reply :slight_smile:. You can ignore that!

1 Like

@Vignesh_Krishnan hmm… I’m not sure I can replicate what you’re seeing. Make sure your package versions are right! Here are mine:

qml.about()
Name: PennyLane
Version: 0.31.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/PennyLaneAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /Users/isaac/pennylane-tf/lib/python3.9/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning

Platform info:           macOS-13.4.1-x86_64-i386-64bit
Python version:          3.9.14
Numpy version:           1.23.5
Scipy version:           1.10.0
Installed devices:
- default.gaussian (PennyLane-0.31.0)
- default.mixed (PennyLane-0.31.0)
- default.qubit (PennyLane-0.31.0)
- default.qubit.autograd (PennyLane-0.31.0)
- default.qubit.jax (PennyLane-0.31.0)
- default.qubit.tf (PennyLane-0.31.0)
- default.qubit.torch (PennyLane-0.31.0)
- default.qutrit (PennyLane-0.31.0)
- null.qubit (PennyLane-0.31.0)
- lightning.qubit (PennyLane-Lightning-0.31.0)
tf.__version__
'2.12.0'

Name: PennyLane
Version: 0.31.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: GitHub - PennyLaneAI/pennylane: PennyLane is a cross-platform Python library for differentiable programming of quantum computers. Train a quantum computer the same way as a neural network.
Author:
Author-email:
License: Apache License 2.0
Location: /opt/conda/lib/python3.10/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning, PennyLane-qiskit

Platform info: Linux-4.15.0-212-generic-x86_64-with-glibc2.35
Python version: 3.10.8
Numpy version: 1.23.5
Scipy version: 1.9.3
Installed devices:

Hi, thanks for the quick response! This is what I have on the online qiskit compiler.
And tf.version gives me this:
‘2.13.0’

It’s not the same as yours but I think having a more recent version shouldn’t cause a breakage unless I’m missing something.

@Vignesh_Krishnan so just to clarify, you’re running this code:

import numpy as np
import tensorflow as tf
import pennylane as qml

from sklearn.model_selection import train_test_split

np.random.seed(42)

X = np.column_stack((np.random.rand(10), np.random.rand(10)))
y = np.random.randint(0, 2, 10)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
n_classes = 2
n_qubits = 2
n_layers = 3
n_wires = n_qubits
dev = qml.device("default.qubit", wires=n_qubits)


@qml.qnode(dev)
def quantum_model(inputs, weights):
    reshaped_inputs = tf.reshape(
        inputs, (-1, n_qubits)
    )  # Reshape inputs to (batch_size, n_qubits)
    qml.AngleEmbedding(inputs, wires=range(n_qubits))
    qml.StronglyEntanglingLayers(weights, wires=range(n_qubits))
    return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]


weight_shapes = {"weights": (n_layers, n_wires, 3)}
quantum_layer = qml.qnn.KerasLayer(
    quantum_model, weight_shapes=weight_shapes, output_dim=n_qubits
)

inputs = tf.random.uniform((4, n_qubits), 0, 1)
print(quantum_layer(inputs))

classical_model = tf.keras.Sequential(
    [
        tf.keras.layers.Dense(
            4, activation="relu", input_dim=n_qubits, trainable=False
        ),
        tf.keras.layers.Dense(n_classes, activation="softmax"),
    ]
)
model = tf.keras.models.Sequential(
    [
        tf.keras.layers.Dense(
            n_qubits, activation="relu", input_dim=n_qubits, trainable=False
        ),
        quantum_layer,
        classical_model,
    ]
)

model.compile(
    loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
)

loss, accuracy = model.evaluate(X_test, y_test)
print("Loss:", loss)
print("Accuracy:", accuracy)

and it’s not working for you?

Yup I copied the exact same code you posted as the solution.

It could be an issue with this. You might have to do some digging here, I’m not familiar with IBM’s online compiler :sweat_smile:. That, or try running things on your laptop or in a Google collab session!

@Vignesh_Krishnan

In the code, we are using pennylane and qml.qnn.KerasLayer with “default.qubit” as device. If you want to use qiskit device with pennylane you have to change the device type to pennylane-qiskit. It might need some more settings like IBMQ to connect to real devices.
The above code will run on colab and its simulated output, not real output from any real quantum device.

1 Like

This was an error with Tensorflow 2.13 removing that module. Reverting to Tf 2.12 fixed the problem for me

1 Like