import pennylane as qml
import tensorflow as tf
import numpy as np
def blockshaped(arr, nrows, ncols):
if arr.ndim == 2:
h, w = arr.shape
assert h % nrows == 0, f"{h} rows is not evenly divisible by {nrows}"
assert w % ncols == 0, f"{w} cols is not evenly divisible by {ncols}"
return (arr.reshape(-1, nrows, ncols)
.swapaxes(1, 2)
.reshape(-1, nrows, ncols))
elif arr.ndim == 3:
d, h, w = arr.shape
assert h % nrows == 0, f"{h} rows is not evenly divisible by {nrows}"
assert w % ncols == 0, f"{w} cols is not evenly divisible by {ncols}"
return (arr.reshape(d, -1, nrows, ncols)
.swapaxes(2, 3)
.reshape(d, -1, nrows, ncols))
else:
raise ValueError("Input array must be 2D or 3D")
dev = qml.device("default.qubit", wires=4)
@qml.qnode(dev)
def quantum_circuit(patch, weights):
flat_patch = tf.reshape(patch, (tf.shape(patch)[0], -1))
qml.templates.AngleEmbedding(flat_patch, wires=range(4), rotation='Y')
qml.templates.BasicEntanglerLayers(weights, wires=range(4))
return [qml.expval(qml.PauliZ(0))]
class QuantumLayer(tf.keras.layers.Layer):
def __init__(self, num_layers, patch_size, output_dim, **kwargs):
super(QuantumLayer, self).__init__(**kwargs)
self.num_layers = num_layers
self.patch_size = patch_size
self.output_dim = output_dim
self.weights_var = self.add_weight("quantum_weights", shape=(num_layers, 4), initializer="random_normal", trainable=True)
@tf.function
def quantum_function(self, patch_element):
patch_element = tf.convert_to_tensor(patch_element, dtype=tf.float64)
result = quantum_circuit(patch_element, self.weights_var)
return result
def call(self, inputs):
quantum_outputs = []
for patch in tf.unstack(inputs, axis=1):
patch = tf.cast(patch, dtype=tf.float64)
patch_outputs = tf.map_fn(self.quantum_function, patch)
quantum_outputs.append(tf.reshape(patch_outputs, (-1, 1)))
stacked_outputs = tf.concat(quantum_outputs, axis=1)
return stacked_outputs
# Step 1: Prepare Data and Labels
data = np.random.rand(200, 4, 4)
labels = np.random.randint(2, size=200)
# Preprocess data outside the quantum layer
data_reshaped = blockshaped(data, 2, 2)
# Step 2: Define Quantum Layer
quantum_layer = QuantumLayer(num_layers=1, patch_size=2, output_dim=4, input_shape=(4, 2, 2))
# Step 3: Classical Processing
model = tf.keras.Sequential([
quantum_layer,
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(8, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
# Explicitly set the input shape for the Dense layer
model.build(input_shape=(None, 4, 2, 2)) # Explicitly set the input shape
# Compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# Step 4: Training
model.fit(data_reshaped, labels, epochs=100)
here i am trying to run quantum circuit over different blocks of a data. then concatenating outcomes from circuit of each sample and pass through dense layer. trying to make all as one model trainable. But not getting which symbolic error coming out to a numpy call between quantum and classical layer.