Shape error after concat operation in qlayer keras layer model

import numpy as np
from tensorflow.keras.datasets import fashion_mnist
from sklearn.model_selection import train_test_split
import pennylane as qml
import tensorflow as tf
#from pennylane import numpy as np
import pandas as pd
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau
from tensorflow.keras.models import load_model
from tensorflow.keras.metrics import AUC
from os import path
# Load Fashion MNIST dataset
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()

# Split the data into training and testing sets
x_train, _, y_train, _ = train_test_split(x_train, y_train, train_size=0.8, random_state=42)

# Initialize variables
samples_per_class = 25
num_classes = 10
x_test_samples = []
y_test_samples = []

# Create x_test and y_test with 100 samples from each class
for class_label in range(num_classes):
    # Get indices of samples for the current class
    class_indices = np.where(y_test == class_label)[0]
    
    # Take the first 100 samples for the current class
    class_indices = class_indices[:samples_per_class]
    
    # Append the samples to x_test_samples and y_test_samples
    x_test_samples.append(x_test[class_indices])
    y_test_samples.extend([class_label] * samples_per_class)

# Concatenate the samples to create the final x_test and y_test
x_test = np.concatenate(x_test_samples, axis=0)
y_test = np.array(y_test_samples)

# Print the shapes of x_test and y_test
print("Shape of x_test:", x_test.shape)
print("Shape of y_test:", y_test.shape)

x_train = x_train.reshape(x_train.shape[0],28,28,1)
x_test = x_test.reshape(x_test.shape[0],28,28,1)

x_train= tf.image.resize(x_train, (4,4))
x_test= tf.image.resize(x_test, (4,4))
x_train= np.array(x_train)
x_test= np.array(x_test)

x_train=x_train/255.0
x_test=x_test/255.0

x_train= x_train.reshape(x_train.shape[0],16)
x_test= x_test.reshape(x_test.shape[0], 16)

x_train.max()

l=np.random.permutation(len(y_train))
x_train=x_train[l]
y_train=y_train[l]
l=np.random.permutation(len(y_test))
x_test=x_test[l]
y_test=y_test[l]

y_train=tf.keras.utils.to_categorical(y_train, num_classes=16)
y_test=tf.keras.utils.to_categorical(y_test, num_classes=16)
print(x_test.max(), x_train.max())

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

@qml.qnode(dev)
def qnode(inputs, weights):
    for i in range(4):
        qml.RY(inputs[i], wires=i)
        
    for j in range(1):
        for i in range(4):
            qml.RY(weights[j][i], wires=i)
        
        qml.CNOT(wires=[0,1])
        qml.CNOT(wires=[1,2])
        qml.CNOT(wires=[2,3])
    
    return [qml.probs(3)]

@qml.qnode(dev)
def qnodex(inputs, weights):
    for i in range(4):
        qml.RY(inputs[i], wires=i)
        
    for j in range(1):
        for i in range(4):
           
            qml.RY(weights[j][i], wires=i)
        
        qml.CNOT(wires=[0,1])
        qml.CNOT(wires=[1,2])
        qml.CNOT(wires=[2,3])
    
    return [qml.probs(wires=[0,1,2,3])]


n_layers = 1
weight_shapes = {"weights": (n_layers, n_qubits)}

qlayer_1 = qml.qnn.KerasLayer(qnode, weight_shapes, output_dim=2)
qlayer_2 = qml.qnn.KerasLayer(qnode, weight_shapes, output_dim=2)
qlayer_3 = qml.qnn.KerasLayer(qnode, weight_shapes, output_dim=2)
qlayer_4 = qml.qnn.KerasLayer(qnode, weight_shapes, output_dim=2)
qlayer_5 = qml.qnn.KerasLayer(qnode, weight_shapes, output_dim=2)
qlayer_6 = qml.qnn.KerasLayer(qnode, weight_shapes, output_dim=2)
qlayer_7 = qml.qnn.KerasLayer(qnodex, weight_shapes, output_dim=16)


qlayer_1.build((None, n_qubits))
qlayer_2.build((None, n_qubits))
qlayer_3.build((None, n_qubits))
qlayer_4.build((None, n_qubits))
qlayer_5.build((None, n_qubits))
qlayer_6.build((None, n_qubits))
qlayer_7.build((None, n_qubits))

input_tensor1 = tf.keras.Input(shape=(16,))

part1x = tf.concat([input_tensor1[:, :2], input_tensor1[:, 4:6]], axis=1)
part2x = tf.concat([input_tensor1[:, 2:4], input_tensor1[:, 6:8]], axis=1)
part3x = tf.concat([input_tensor1[:, 4:6], input_tensor1[:, 12:14]], axis=1)
part4x = tf.concat([input_tensor1[:, 10:12], input_tensor1[:, 14:]], axis=1)

x1 = qlayer_1(part1x)
x2 = qlayer_2(part2x)
x3 = qlayer_3(part3x)
x4 = qlayer_4(part4x)

print(x1.shape, x2.shape, x3.shape, x4.shape)

first = tf.concat([x1, x3], axis=-1)
print(first.shape)

second = tf.concat([x2, x4], axis=-1)
print(second.shape)

x5 = qlayer_5(first)
x6 = qlayer_6(second)

xz = tf.concat([x5, x6], axis=-1)

print(xz.shape)

outputs = qlayer_7(xz)

model = tf.keras.Model(inputs=input_tensor1, outputs=outputs)

opt = tf.keras.optimizers.Adam(learning_rate=0.01, beta_1=0.5, beta_2=0.999)
model.compile(opt, loss="categorical_crossentropy", metrics=['accuracy'])

model.summary()

hist=model.fit(x_train, y_train,epochs=20, batch_size=8, verbose=1, validation_data=(x_test, y_test))

the output of qml.about()

Name: PennyLane
Version: 0.28.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: c:\users\amand\anaconda3\envs\final\lib\site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, retworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning

Platform info:           Windows-10-10.0.22621-SP0
Python version:          3.8.0
Numpy version:           1.21.2
Scipy version:           1.10.1
Installed devices:
- default.gaussian (PennyLane-0.28.0)
- default.mixed (PennyLane-0.28.0)
- default.qubit (PennyLane-0.28.0)
- default.qubit.autograd (PennyLane-0.28.0)
- default.qubit.jax (PennyLane-0.28.0)
- default.qubit.tf (PennyLane-0.28.0)
- default.qubit.torch (PennyLane-0.28.0)
- default.qutrit (PennyLane-0.28.0)
- null.qubit (PennyLane-0.28.0)
- lightning.qubit (PennyLane-Lightning-0.30.0)

When i try to fit the model. the error came with invalid argument. although model prints the summary and works fine if i use classical layer. but i want to keep it only qlayers. The error is InvalidArgumentError: Exception encountered when calling layer ‘keras_layer_220’ (type KerasLayer).

{{function_node __wrapped__StridedSlice_device_/job:localhost/replica:0/task:0/device:CPU:0}} slice index 2 of dimension 0 out of bounds. [Op:StridedSlice] name: model_31/keras_layer_220/strided_slice/

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

One more thing if the code works fine it only works with custom categorical loss and custom categorical accuracy. but not worked with the inbuilt tensorflow loss acurracy.

Hey @Amandeep!

Can you reduce your code down to something smaller that still produces the error that you’re seeing? It’ll help us get to the bottom of this!

@isaacdevlugt The only thing is that the quantum circuit is not working with inbuilt tensorflow loss and accuracy. I have to write custom code then it works. But I want it to work with tensorflow loss/accuracy also.

@isaacdevlugt here the quantum circuit which i train with data. I am not getting it gives an error of shape when i use tensorflow loss and accuracy. But If i use custom loss/accuracy, then only it works. Can you please look into it.

I am not getting it gives an error of shape when i use tensorflow loss and accuracy. But If i use custom loss/accuracy, then only it works.

It might be worth installing pennylane from source to get the latest changes. There were some changes to how we broadcast parameters in Tensorflow that should be out next release, but aren’t available right now. You can install pennylane from source by cloning our repository and then doing pip install -e . in the root directory :slight_smile:. Let me know if that works, otherwise we’ll look into it further!