Batch Size error while using pennylane-qiskit for image classification

I was doing a simple image classification with the help of pennylane quantum library.
this code used to work properly but now its not working from June 2023.

!pip install pennylane-qiskit

from qiskit.providers.fake_provider import FakeQuitoV2
import qiskit.providers.aer.noise as noise
import pennylane as qml
import pandas as pd
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from matplotlib import pyplot as plt

from pennylane import numpy as np
random_seed=5
np.random.seed(random_seed)
tf.random.set_seed(random_seed)
tf.keras.backend.set_floatx('float64')

t=[0,1]
(X_train,Y_train),(X_test,Y_test)=keras.datasets.mnist.load_data()
print(t)
binary_index=[i for i in range(len(Y_train)) if Y_train[i] in t]
X_train=X_train[binary_index]
Y_train=Y_train[binary_index]
binary_index=[i for i in range(len(Y_test)) if Y_test[i] in t]
X_test=X_test[binary_index]
Y_test=Y_test[binary_index]


n_train=200
n_test=50


X_train=X_train[:n_train]
Y_train=Y_train[:n_train]
X_test=X_test[:n_test]
Y_test=Y_test[:n_test]
X_train=X_train/255*np.pi
X_test =X_test/255*np.pi
X_train = np.array(X_train[...,tf.newaxis],requires_grad=False,dtype=np.float64)
X_test  = np.array( X_test[...,tf.newaxis],requires_grad=False,dtype=np.float64)


n_epochs=30
batch_size=5
m=4
w1={"weights": (4,4)}

encoder_1= qml.device("qiskit.aer",wires=m,backend="aer_simulator_statevector")

@qml.qnode(encoder_1)

def encoderl(inputs,weights):
  for i in range(m):
    qml.RY(inputs[i],wires=i)
  for i in range(m):
    qml.RZ(inputs[m+i],wires=i)
  for i in range(m):
    qml.RX(inputs[2*m+i],wires=i)
  for i in range(m):
    qml.RY(inputs[3*m+i],wires=i)

  qml.BasicEntanglerLayers(weights, wires=range(m))

  return [qml.expval(qml.PauliZ(i)) for i in range(m)]

Encoding_layer=qml.qnn.KerasLayer(encoderl,w1,output_dim=m)
from keras.models import Sequential

model = Sequential([
          keras.layers.Cropping2D(cropping=((2, 2), (2, 2))),
          keras.layers.AveragePooling2D(pool_size=(6,6),strides=(6, 6)),
          keras.layers.Flatten(),
          Encoding_layer,
          # keras.layers.Normalization(mean=0,variance=1,axis=None),
          keras.layers.Dense(2,activation="softmax"),
      ])
model.compile(optimizer='adam', loss = 'sparse_categorical_crossentropy', metrics =['accuracy'])

print("Test training")

model.fit(X_train, Y_train,epochs = 1,batch_size = batch_size,validation_data=(X_test,Y_test),shuffle = True)

I am getting this error message now.

InvalidArgumentError                      Traceback (most recent call last)
<ipython-input-15-2257bd784bfb> in <cell line: 82>()
     80 print("Test training")
     81 
---> 82 model.fit(X_train, Y_train,epochs = 1,batch_size = batch_size,validation_data=(X_test,Y_test),shuffle = True)
     83 
     84 

6 frames
/usr/local/lib/python3.10/dist-packages/keras/utils/traceback_utils.py in error_handler(*args, **kwargs)
     68             # To get the full stack trace, call:
     69             # `tf.debugging.disable_traceback_filtering()`
---> 70             raise e.with_traceback(filtered_tb) from None
     71         finally:
     72             del filtered_tb

/usr/local/lib/python3.10/dist-packages/pennylane/qnn/keras.py in call(self, inputs)
    394         else:
    395             # calculate the forward pass as usual
--> 396             results = self._evaluate_qnode(inputs)
    397 
    398         # reshape to the correct number of batch dims

/usr/local/lib/python3.10/dist-packages/pennylane/qnn/keras.py in _evaluate_qnode(self, x)
    416             **{k: 1.0 * w for k, w in self.qnode_weights.items()},
    417         }
--> 418         res = self.qnode(**kwargs)
    419 
    420         if isinstance(res, (list, tuple)):

/usr/local/lib/python3.10/dist-packages/pennylane/qnode.py in __call__(self, *args, **kwargs)
    934 
    935         # construct the tape
--> 936         self.construct(args, kwargs)
    937 
    938         cache = self.execute_kwargs.get("cache", False)

/usr/local/lib/python3.10/dist-packages/pennylane/qnode.py in construct(self, args, kwargs)
    825             self.interface = qml.math.get_interface(*args, *list(kwargs.values()))
    826 
--> 827         self._tape = make_qscript(self.func, shots)(*args, **kwargs)
    828         self._qfunc_output = self.tape._qfunc_output
    829 

/usr/local/lib/python3.10/dist-packages/pennylane/tape/qscript.py in wrapper(*args, **kwargs)
   1480     def wrapper(*args, **kwargs):
   1481         with AnnotatedQueue() as q:
-> 1482             result = fn(*args, **kwargs)
   1483 
   1484         qscript = QuantumScript.from_queue(q, shots)

<ipython-input-15-2257bd784bfb> in encoderl(inputs, weights)
     55     qml.RY(inputs[i],wires=i)
     56   for i in range(m):
---> 57     qml.RZ(inputs[m+i],wires=i)
     58   for i in range(m):
     59     qml.RX(inputs[2*m+i],wires=i)

InvalidArgumentError: Exception encountered when calling layer 'keras_layer_6' (type KerasLayer).

{{function_node __wrapped__StridedSlice_device_/job:localhost/replica:0/task:0/device:GPU:0}} slice index 5 of dimension 0 out of bounds. [Op:StridedSlice] name: sequential_6/keras_layer_6/strided_slice/

Call arguments received by layer 'keras_layer_6' (type KerasLayer):
  • inputs=tf.Tensor(shape=(5, 16), dtype=float64)

Hi @Abhijeet_Panihar ! I have checked and it turns out that you are accessing indexes that do not exist. In this case, within encoder1 we get that:

m: 4
len(inputs): 5

Therefore, an error will be thrown since you are trying to access inputs[m + i] and m + i > 5
I hope this helps!

Welcome to the community, @Abhijeet_Panihar.

This quantum transfer learning model is also good to start with if you are having issues. Many high resolution images can be used and the hyper-parameters can be easily optimized. Be sure to change data_dir = “…/_data/hymenoptera_data” to your directory. Best regards, Kevin.

Source:

Thanks for replying @Guillermo_Alonso. Could you suggest what type of changes I should do so that it process one image at a time instead of whole batch.

Hey @Abhijeet_Panihar , did you manage to fix your indexing error, like Guillermo suggested?

To answer your second question, in the part of your code where you’re defining variable values, you could change your setup. For example, if you really wanted to reduce your batch size to 1, you could set batch_size = 1.

Not Sure how but now this code is working with specific version

!pip install qiskit==0.24.0
!pip install pennylane==0.30
!pip install pennylane-qiskit==0.31.0

And

from qiskit.providers.fake_provider import FakeQuitoV2
# import qiskit_aer.noise as noise
import qiskit.providers.aer.noise as noise
import pennylane as qml
import pandas as pd
import tensorflow as tf
from tensorflow import keras
import numpy as np
from matplotlib import pyplot as plt
random_seed=5
np.random.seed(random_seed)
tf.random.set_seed(random_seed)
tf.keras.backend.set_floatx('float64')

from pennylane import numpy as np

t=[0,1]
(X_train,Y_train),(X_test,Y_test)=keras.datasets.mnist.load_data()
# print(t)
binary_index=[i for i in range(len(Y_train)) if Y_train[i] in t]
X_train=X_train[binary_index]
Y_train=Y_train[binary_index]
binary_index=[i for i in range(len(Y_test)) if Y_test[i] in t]
X_test=X_test[binary_index]
Y_test=Y_test[binary_index]

n_train=200
n_test=50


X_train=X_train[:n_train]
Y_train=Y_train[:n_train]
X_test=X_test[:n_test]
Y_test=Y_test[:n_test]
X_train=X_train/255*np.pi
X_test =X_test/255*np.pi
X_train = np.array(X_train[...,tf.newaxis],requires_grad=False,dtype=np.float64)
X_test  = np.array( X_test[...,tf.newaxis],requires_grad=False,dtype=np.float64)

n_epochs=30
batch_size=5
m=4
w1={"weights": (4,4)}

encoder_1= qml.device("qiskit.aer",wires=m,backend="aer_simulator_statevector")
# encoder_1= qml.device('default.mixed',wires=m)
# training_layer= qml.device("qiskit.aer",wires=m,backend="aer_simulator_statevector")

@qml.qnode(encoder_1)

def encoderl(inputs,weights):

  for i in range(m):
    qml.RY(inputs[i],wires=i)
  for i in range(m):
    qml.RZ(inputs[m+i],wires=i)
  for i in range(m):
    qml.RY(inputs[2*m+i],wires=i)
  for i in range(m):
    qml.RZ(inputs[3*m+i],wires=i)

  qml.BasicEntanglerLayers(weights, wires=range(m))

  return [qml.expval(qml.PauliZ(i)) for i in range(m)]

Encoding_layer=qml.qnn.KerasLayer(encoderl,w1,output_dim=m)
from keras.models import Sequential

model = Sequential([
          keras.layers.Cropping2D(cropping=((2, 2), (2, 2))),
          keras.layers.AveragePooling2D(pool_size=(6,6),strides=(6, 6)),
          keras.layers.Flatten(),
          Encoding_layer,
          keras.layers.Normalization(mean=0,variance=1,axis=None),
          keras.layers.Dense(2,activation="softmax"),
      ])
model.compile(optimizer='adam', loss = 'sparse_categorical_crossentropy', metrics =['accuracy'])
model.fit(X_train, Y_train,epochs = 1,batch_size = 1,validation_data=(X_test,Y_test),shuffle = True)

Which is weird, as workings related to batch training should be version independent.

Okay, so you’re using qnn.KerasLayer, with encoderl as your QNode. Your QNode has the necessary inputs argument, as expected, but the error seems to be part of the Keras workflow and has to do with how you define your inputs. When you call inputs[m+i] in the Keras model, the inputs index reports as out of bounds.

I would really recommend that you update your packages (e.g., you’re using a version of Qiskit that’s more than two years old) and also tell us which version of TensorFlow you’re using. It might be that you stumbled across a bug, but compatibility across several years of package and plugin updates can’t be guaranteed… :sweat_smile: It might be that you also need to upgrade your TensorFlow version and that fixes it.

If you still have a problem when you use the current versions of all packages, could you please share a minimal self-contained version of the code that reproduces the problem? That way we can see which package is causing you trouble. :smiley:

I am working on google colab, so I am using latest version of tensorflow. For rest, in case of error I am using what ever version,

!pip install penylane-qiskit

Installs on the system. And in case of no errors I am using the above mentioned version

Could you please share a minimal (not using Aer, reducing the number of Keras layers that still reproduce the error, etc.) self-contained (all information needed to reproduce the issue included) code example and error output that you get when using updated packages?

That way we can best help you diagnose the exact problem. :slight_smile: On first glance, it looks like a problem in your code, not a problem with PennyLane.

Thanks! :smiley: