Hi @Muhammad_Kashif,
I believe there’s still some confusion as to what a data point is, what a weight is and how the embedding and templates work. I’ll revert to a basic example. Another very good explanation is detailed in this blog post on how to start learning quantum machine learning (I strongly encourage you to read the blog post.)
I want to predict the change in value of a house based on the distance to the city centre. I have this information for a few houses that are at X = 0, 1, 2, 3, 4, and 5 km from the city centre. Their respective change in value are Y = 0, 0.84, 0.91, 0.14, -0.76 and -0.96.
I want to use a quantum circuit to predict the change in value located at any distance from the city centre. What do I do?
I first create a qnode
@qml.qnode(dev)
def circuit(some inputs):
#I'll add something here
return something
What inputs will my circuit need? It will need the distance from the city centre, which is my datapoint. Notice that this data is fixed, I don’t train over it. I will also need some parameters that I can put into my circuit, and which I can modify after each iteration, hoping to get a better model for my data.
My return value will be an expectation value, which will give me a prediction for the change in value of a house at the particular distance specified by the input datapoint.
This is how the qnode will be looking:
@qml.qnode(dev)
def circuit(distance, parameters):
# something that takes the distance
# something that takes some trainable parameters
return qml.expval(qml.PauliZ(0))
Now how do we put a distance into a quantum circuit? We put the classical data points into the quantum circuit by using an embedding. In this case we can use the angle embedding to plug my data into my circuit. This will basically create a rotation for every one of my features. In this case I only have one feature which is distance. But I could have had other features such as area of the house, number of bedrooms, and others.
And where do the trainable parameters go? I can put them into my circuit as angles in rotation gates, where these angles can in fact change. I can also add other gates such as CNOTs and Hadamards to add more complexity to my circuit. I can use BasicEntanglerLayers to do this in an easy way. But what about the weights? My parameters are the weights!
So now we have
@qml.qnode(dev)
def circuit(distance, parameters):
qml.AngleEmbedding(distance, wires=range(n_qubits))
qml.BasicEntanglerLayers(parameters, wires=range(n_qubits))
return qml.expval(qml.PauliZ(0))
Now lets get some initial values for the distance and parameters and draw the circuit:
n_qubits = 2
dev = qml.device('lightning.qubit',wires=n_qubits)
@qml.qnode(dev)
def circuit(distance, parameters):
qml.AngleEmbedding(distance, wires=range(n_qubits))
qml.BasicEntanglerLayers(parameters, wires=range(n_qubits))
return qml.expval(qml.PauliZ(0))
n_layers = 6
weights = np.random.random([n_layers, n_qubits])
X = [1.5]
qml.draw_mpl(circuit,expansion_strategy="device",decimals=1)(X,weights)
As you can see I have a 2-qubit circuit where the first RX rotation is the embedding or encoding of my data (the distance) and then I have 6 layers of parametrized rotations and CNOTs.
I encourage you to first try out variational circuits without using Keras and then you can try adding Keras Layers into the mix.
Please let me know if this explanation was helpful or if you have other questions.