Qml.kernels.kernel_matrix not working

Hi everyone, I am going through the documentation of the pennylane : qml.kernels.kernel_matrix — PennyLane 0.31.1 documentation
I am new to pennylane and I have quite a lot of questions regarding syntax and basic fundamentals.

import pennylane as qml
import numpy as np

dev = qml.device("default.qubit", wires = 2, shots =None)   

Why you have chosen 2. Is this is chosen because you are using a data of features = 2 or due to some other reasons?

@qml.qnode(dev)
def circuit(x1, x2):
    qml.templates.AngleEmbedding(x1, wires, dev.wires) 
    qml.adjoint(qml.templates.AngleEmbedding)(x2, wires= dev.wires) 
    return qml.probs(wires= dev.wires)

What exactly is AngleEmbedding?
What is qml.adjoint and what are the arguments you are putting in to this adjoint function? What I understand is that x2 is the argument, wires= dev.wires is the argument. Is qml.templates.AngleEmbedding is also the argument?

kernel = lambda x1, x2: circuit(x1, x2)[0]

I really donot understand how is this function call working? We donot know the value of x1 and x2?

X_train = np.random.random((4,2))  
X_test = np.random.random((3,2))   
qml.kernels.kernel_matrix(X_train, X_test, kernel)

This line is not executing in the code and is giving a error. Even if it works, what exactly is the kernel_matrix how exactly do this calculation works?

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[26], line 1
----> 1 qml.kernels.kernel_matrix(X_train, X_test, kernel)

File ~/anaconda3/envs/pennylane_study/lib/python3.11/site-packages/pennylane/kernels/utils.py:132, in kernel_matrix(X1, X2, kernel)
    129 N = qml.math.shape(X1)[0]
    130 M = qml.math.shape(X2)[0]
--> 132 matrix = qml.math.stack([kernel(x, y) for x, y in product(X1, X2)])
    134 if qml.math.ndim(matrix[0]) == 0:
    135     return qml.math.reshape(matrix, (N, M))

File ~/anaconda3/envs/pennylane_study/lib/python3.11/site-packages/pennylane/kernels/utils.py:132, in (.0)
    129 N = qml.math.shape(X1)[0]
    130 M = qml.math.shape(X2)[0]
--> 132 matrix = qml.math.stack([kernel(x, y) for x, y in product(X1, X2)])
    134 if qml.math.ndim(matrix[0]) == 0:
    135     return qml.math.reshape(matrix, (N, M))

Cell In[22], line 1, in (x1, x2)
----> 1 kernel = lambda x1, x2: circuit(x1, x2)[0]
      2 kernel

File ~/anaconda3/envs/pennylane_study/lib/python3.11/site-packages/pennylane/qnode.py:936, in QNode.__call__(self, *args, **kwargs)
    933             kwargs["shots"] = None
...
---> 83         raise ValueError(f"Rotation option {rotation} not recognized.")
     85     shape = qml.math.shape(features)[-1:]
     86     n_features = shape[0]

ValueError: Rotation option  not recognized.
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

I also tried the code related to qml.kernels.square_kernel_matrix: qml.kernels.square_kernel_matrix — PennyLane 0.31.1 documentation

import pennylane as qml
import numpy as np
dev = qml.device('default.qubit', wires=2, shots=None)
@qml.qnode(dev)
def circuit(x1, x2):
    qml.templates.AngleEmbedding(x1, wires=dev.wires)
    qml.adjoint(qml.templates.AngleEmbedding)(x2, wires=dev.wires)
    return qml.probs(wires=dev.wires)

kernel = lambda x1, x2: circuit(x1, x2)[0]
X = np.random.random((4, 2))
qml.kernels.square_kernel_matrix(X, kernel)
tensor([[1.        , 0.81682562, 0.88524124, 0.86531594],
        [0.81682562, 1.        , 0.90944273, 0.9757909 ],
        [0.88524124, 0.90944273, 1.        , 0.97756667],
        [0.86531594, 0.9757909 , 0.97756667, 1.        ]], requires_grad=True)

I really do not understand exactly how is this matrix is being calculated and what exactly is its use or benefit?
Thank you for your continuous help.

Hello @Manu_Chaudhary,

wires = 2 refers to a quantum subsytem, in your case “qubits”.
The quantum circuits documentation is a great resource for your example: Quantum circuits — PennyLane 0.32.0 documentation

AngleEmbedding is a type of embedding “Template” that defaults to RX gates; a circuit is printed here: qml.AngleEmbedding — PennyLane 0.32.0 documentation

qml.adjoint “Create(s) the adjoint of an Operator or a function that applies the adjoint of the provided function.” qml.adjoint — PennyLane 0.32.0 documentation

Demos might be a better option if you’re looking for Kernel step-by-step guides:

Hi @Manu_Chaudhary :smile:

The number of qubits is determined by the size of your input but also by how you are going to encode the data. BasisEmbedding is an encoding method that uses one qubit for each dimension of the input (putting each parameter as a rotation in each qubit) but at other times the correspondence will not be 1 to 1. In this post you will find more information about the different types of embedding.

On the other hand, the lambda function you ask about is a technique for defining functions quickly. It is a feature of Python rather than PennyLane, I’m sure you can find information in Python tutorials (Let me know if you continue to have problems)

In answer to the question of the kernel matrix, it is a matrix that stores the inner products of the dataset elements two by two. Having this information is very important to use it in algorithms such as SVM.

In the code you provide, circuit is the function in charge of calculating the inner product of these two vectors.

Finally, the code seems to have an error in circuit. The first line should be:

qml.templates.AngleEmbedding(x1, wires = dev.wires)

Correcting that, the code did work on my computer. Let me know if the problem persists.

I hope all this is helpful :rocket:

Thank you @kevinkawchak and @Guillermo_Alonso for this great help. I will study all the links provided by you thoroughly.

1 Like