How to Use qml.GradientDescentOptimizer with AngleEmbedding Template

Hi @Hemant_Gahankari,

A couple of thoughts here:

  1. The definition of the quantum function would require an update so that the non-differentiable parameter (X) has a default parameter: def qnode(weights, X=None). This is required when defining the QNode (included a bit more context in this answer).
  2. The quantum function that you’ve defined currently returns an array with 4 (n_qubits) scalars. Therefore optimization will happen as described for Vector-valued QNodes:
for e in range(epochs):
    for i in range(len(X)):
        weights = opt.step(lambda weights: cost(weights, X=X[i]), weights, grad_fn=lambda weights: qml.jacobian(qnode, argnum=0)(weights, X=X[i]))

As convenience, defined a cost function:

def cost(weights, X):
    res = qnode(weights, X=X)
    return res

Breaking this down a bit:

  • lambda weights: cost(weights, X=X[i]): this helps to pass the current batch of features (X[i]) to the QNode
  • lambda weights: qml.jacobian(qnode, argnum=0)(weights, X=X[i]): this has to be defined so that Autograd can compute the gradient of the cost function. argnum=0 is specified as the first argument is differentiable, and we need to pass X[i] as keyword argument.

  1. A small adjustment would be required for looping through the extracted features (for i in range(len(X)) loop definition):
for e in range(epochs):
    for i in range(len(X)):
        weights = opt.step(lambda weights: cost(weights, X=X[i]), weights, grad_fn=lambda weights: qml.jacobian(qnode, argnum=0)(weights, X=X[i]))
  1. A possible way of creating batches for each step is defining a batch_size and selecting a random batch for each epoch:
batch_size = 4
for e in range(epochs):
    batch_index = np.random.randint(0, len(X), (batch_size))
    X_batch = X[batch_index,0]
    weights = opt.step(lambda weights: cost(weights, X=X_batch), weights, grad_fn=lambda weights: qml.jacobian(qnode, argnum=0)(weights, X=X_batch))

Hopefully, this gives a bit of direction! :slight_smile:

(Note: edited this answer as on the first read didn’t consider the solution as a vector-valued QNode, but rather a QNode that has a tensor product observable as measurement and returns a single scalar. Let us know if specifying a tensor product observable would be desired here, and can provide further pointers!)