|
a |
|
b/Code/All Qiskit, PennyLane QML Nov 23/24a1 Kernels 100% No Train kkawchak.ipynb |
|
|
1 |
{ |
|
|
2 |
"cells": [ |
|
|
3 |
{ |
|
|
4 |
"cell_type": "code", |
|
|
5 |
"execution_count": 102, |
|
|
6 |
"metadata": { |
|
|
7 |
"id": "IZi5TUAp-1Lt", |
|
|
8 |
"colab": { |
|
|
9 |
"base_uri": "https://localhost:8080/", |
|
|
10 |
"height": 0 |
|
|
11 |
}, |
|
|
12 |
"outputId": "78cb9e7d-6215-4978-c1ca-2d0fa4d9c311" |
|
|
13 |
}, |
|
|
14 |
"outputs": [ |
|
|
15 |
{ |
|
|
16 |
"output_type": "stream", |
|
|
17 |
"name": "stdout", |
|
|
18 |
"text": [ |
|
|
19 |
"Time in seconds since beginning of run: 1700543496.4327478\n", |
|
|
20 |
"Tue Nov 21 05:11:36 2023\n" |
|
|
21 |
] |
|
|
22 |
} |
|
|
23 |
], |
|
|
24 |
"source": [ |
|
|
25 |
"# This cell is added by sphinx-gallery\n", |
|
|
26 |
"# It can be customized to whatever you like\n", |
|
|
27 |
"%matplotlib inline\n", |
|
|
28 |
"# !pip install pennylane\n", |
|
|
29 |
"import time\n", |
|
|
30 |
"seconds = time.time()\n", |
|
|
31 |
"print(\"Time in seconds since beginning of run:\", seconds)\n", |
|
|
32 |
"local_time = time.ctime(seconds)\n", |
|
|
33 |
"print(local_time)" |
|
|
34 |
] |
|
|
35 |
}, |
|
|
36 |
{ |
|
|
37 |
"cell_type": "markdown", |
|
|
38 |
"metadata": { |
|
|
39 |
"id": "yx4UlxKp-1Lu" |
|
|
40 |
}, |
|
|
41 |
"source": [ |
|
|
42 |
"Training and evaluating quantum kernels\n", |
|
|
43 |
"=======================================\n", |
|
|
44 |
"\n", |
|
|
45 |
"::: {.meta}\n", |
|
|
46 |
":property=\\\"og:description\\\": Kernels and alignment training with\n", |
|
|
47 |
"Pennylane. :property=\\\"og:image\\\":\n", |
|
|
48 |
"<https://pennylane.ai/qml/_images/QEK_thumbnail.png>\n", |
|
|
49 |
":::\n", |
|
|
50 |
"\n", |
|
|
51 |
"::: {.related}\n", |
|
|
52 |
"tutorial\\_kernel\\_based\\_training Kernel-based training with\n", |
|
|
53 |
"scikit-learn tutorial\\_data\\_reuploading\\_classifier Data-reuploading\n", |
|
|
54 |
"classifier\n", |
|
|
55 |
":::\n", |
|
|
56 |
"\n", |
|
|
57 |
"*Authors: Peter-Jan Derks, Paul K. Faehrmann, Elies Gil-Fuster, Tom\n", |
|
|
58 |
"Hubregtsen, Johannes Jakob Meyer and David Wierichs --- Posted: 24 June\n", |
|
|
59 |
"2021. Last updated: 18 November 2021.*\n", |
|
|
60 |
"\n", |
|
|
61 |
"Kernel methods are one of the cornerstones of classical machine\n", |
|
|
62 |
"learning. Here we are concerned with kernels that can be evaluated on\n", |
|
|
63 |
"quantum computers, *quantum kernels* for short. In this tutorial you\n", |
|
|
64 |
"will learn how to evaluate kernels, use them for classification and\n", |
|
|
65 |
"train them with gradient-based optimization, and all that using the\n", |
|
|
66 |
"functionality of PennyLane\\'s [kernels\n", |
|
|
67 |
"module](https://pennylane.readthedocs.io/en/latest/code/qml_kernels.html).\n", |
|
|
68 |
"The demo is based on Ref., a project from Xanadu\\'s own\n", |
|
|
69 |
"[QHack](https://qhack.ai/) hackathon.\n", |
|
|
70 |
"\n", |
|
|
71 |
"What are kernel methods?\n", |
|
|
72 |
"------------------------\n", |
|
|
73 |
"\n", |
|
|
74 |
"To understand what a kernel method does, let\\'s first revisit one of the\n", |
|
|
75 |
"simplest methods to assign binary labels to datapoints: linear\n", |
|
|
76 |
"classification.\n", |
|
|
77 |
"\n", |
|
|
78 |
"Imagine we want to discern two different classes of points that lie in\n", |
|
|
79 |
"different corners of the plane. A linear classifier corresponds to\n", |
|
|
80 |
"drawing a line and assigning different labels to the regions on opposing\n", |
|
|
81 |
"sides of the line:\n", |
|
|
82 |
"\n", |
|
|
83 |
"{.align-center\n", |
|
|
84 |
"width=\"30.0%\"}\n", |
|
|
85 |
"\n", |
|
|
86 |
"We can mathematically formalize this by assigning the label $y$ via\n", |
|
|
87 |
"\n", |
|
|
88 |
"$$y(\\boldsymbol{x}) = \\operatorname{sgn}(\\langle \\boldsymbol{w}, \\boldsymbol{x}\\rangle + b).$$\n", |
|
|
89 |
"\n", |
|
|
90 |
"The vector $\\boldsymbol{w}$ points perpendicular to the line and thus\n", |
|
|
91 |
"determine its slope. The independent term $b$ specifies the position on\n", |
|
|
92 |
"the plane. In this form, linear classification can also be extended to\n", |
|
|
93 |
"higher dimensional vectors $\\boldsymbol{x}$, where a line does not\n", |
|
|
94 |
"divide the entire space into two regions anymore. Instead one needs a\n", |
|
|
95 |
"*hyperplane*. It is immediately clear that this method is not very\n", |
|
|
96 |
"powerful, as datasets that are not separable by a hyperplane can\\'t be\n", |
|
|
97 |
"classified without error.\n", |
|
|
98 |
"\n", |
|
|
99 |
"We can actually sneak around this limitation by performing a neat trick:\n", |
|
|
100 |
"if we define some map $\\phi(\\boldsymbol{x})$ that *embeds* our\n", |
|
|
101 |
"datapoints into a larger *feature space* and then perform linear\n", |
|
|
102 |
"classification there, we could actually realise non-linear\n", |
|
|
103 |
"classification in our original space!\n", |
|
|
104 |
"\n", |
|
|
105 |
"{.align-center\n", |
|
|
106 |
"width=\"65.0%\"}\n", |
|
|
107 |
"\n", |
|
|
108 |
"If we go back to the expression for our prediction and include the\n", |
|
|
109 |
"embedding, we get\n", |
|
|
110 |
"\n", |
|
|
111 |
"$$y(\\boldsymbol{x}) = \\operatorname{sgn}(\\langle \\boldsymbol{w}, \\phi(\\boldsymbol{x})\\rangle + b).$$\n", |
|
|
112 |
"\n", |
|
|
113 |
"We will forgo one tiny step, but it can be shown that for the purpose of\n", |
|
|
114 |
"optimal classification, we can choose the vector defining the decision\n", |
|
|
115 |
"boundary as a linear combination of the embedded datapoints\n", |
|
|
116 |
"$\\boldsymbol{w} = \\sum_i \\alpha_i \\phi(\\boldsymbol{x}_i)$. Putting this\n", |
|
|
117 |
"into the formula yields\n", |
|
|
118 |
"\n", |
|
|
119 |
"$$y(\\boldsymbol{x}) = \\operatorname{sgn}\\left(\\sum_i \\alpha_i \\langle \\phi(\\boldsymbol{x}_i), \\phi(\\boldsymbol{x})\\rangle + b\\right).$$\n", |
|
|
120 |
"\n", |
|
|
121 |
"This rewriting might not seem useful at first, but notice the above\n", |
|
|
122 |
"formula only contains inner products between vectors in the embedding\n", |
|
|
123 |
"space:\n", |
|
|
124 |
"\n", |
|
|
125 |
"$$k(\\boldsymbol{x}_i, \\boldsymbol{x}_j) = \\langle \\phi(\\boldsymbol{x}_i), \\phi(\\boldsymbol{x}_j)\\rangle.$$\n", |
|
|
126 |
"\n", |
|
|
127 |
"We call this function the *kernel*. It provides the advantage that we\n", |
|
|
128 |
"can often find an explicit formula for the kernel $k$ that makes it\n", |
|
|
129 |
"superfluous to actually perform the (potentially expensive) embedding\n", |
|
|
130 |
"$\\phi$. Consider for example the following embedding and the associated\n", |
|
|
131 |
"kernel:\n", |
|
|
132 |
"\n", |
|
|
133 |
"$$\\begin{aligned}\n", |
|
|
134 |
"\\phi((x_1, x_2)) &= (x_1^2, \\sqrt{2} x_1 x_2, x_2^2) \\\\\n", |
|
|
135 |
"k(\\boldsymbol{x}, \\boldsymbol{y}) &= x_1^2 y_1^2 + 2 x_1 x_2 y_1 y_2 + x_2^2 y_2^2 = \\langle \\boldsymbol{x}, \\boldsymbol{y} \\rangle^2.\n", |
|
|
136 |
"\\end{aligned}$$\n", |
|
|
137 |
"\n", |
|
|
138 |
"This means by just replacing the regular scalar product in our linear\n", |
|
|
139 |
"classification with the map $k$, we can actually express much more\n", |
|
|
140 |
"intricate decision boundaries!\n", |
|
|
141 |
"\n", |
|
|
142 |
"This is very important, because in many interesting cases the embedding\n", |
|
|
143 |
"$\\phi$ will be much costlier to compute than the kernel $k$.\n", |
|
|
144 |
"\n", |
|
|
145 |
"In this demo, we will explore one particular kind of kernel that can be\n", |
|
|
146 |
"realized on near-term quantum computers, namely *Quantum Embedding\n", |
|
|
147 |
"Kernels (QEKs)*. These are kernels that arise from embedding data into\n", |
|
|
148 |
"the space of quantum states. We formalize this by considering a\n", |
|
|
149 |
"parameterised quantum circuit $U(\\boldsymbol{x})$ that maps a datapoint\n", |
|
|
150 |
"$\\boldsymbol{x}$ to the state\n", |
|
|
151 |
"\n", |
|
|
152 |
"$$|\\psi(\\boldsymbol{x})\\rangle = U(\\boldsymbol{x}) |0 \\rangle.$$\n", |
|
|
153 |
"\n", |
|
|
154 |
"The kernel value is then given by the *overlap* of the associated\n", |
|
|
155 |
"embedded quantum states\n", |
|
|
156 |
"\n", |
|
|
157 |
"$$k(\\boldsymbol{x}_i, \\boldsymbol{x}_j) = | \\langle\\psi(\\boldsymbol{x}_i)|\\psi(\\boldsymbol{x}_j)\\rangle|^2.$$\n" |
|
|
158 |
] |
|
|
159 |
}, |
|
|
160 |
{ |
|
|
161 |
"cell_type": "markdown", |
|
|
162 |
"metadata": { |
|
|
163 |
"id": "YFfhnwX7-1Lv" |
|
|
164 |
}, |
|
|
165 |
"source": [ |
|
|
166 |
"A toy problem\n", |
|
|
167 |
"=============\n", |
|
|
168 |
"\n", |
|
|
169 |
"In this demo, we will treat a toy problem that showcases the inner\n", |
|
|
170 |
"workings of classification with quantum embedding kernels, training\n", |
|
|
171 |
"variational embedding kernels and the available functionalities to do\n", |
|
|
172 |
"both in PennyLane. We of course need to start with some imports:\n" |
|
|
173 |
] |
|
|
174 |
}, |
|
|
175 |
{ |
|
|
176 |
"cell_type": "code", |
|
|
177 |
"execution_count": 103, |
|
|
178 |
"metadata": { |
|
|
179 |
"id": "_0dLIZDi-1Lv" |
|
|
180 |
}, |
|
|
181 |
"outputs": [], |
|
|
182 |
"source": [ |
|
|
183 |
"from pennylane import numpy as np\n", |
|
|
184 |
"import matplotlib as mpl\n", |
|
|
185 |
"\n", |
|
|
186 |
"np.random.seed(1359)" |
|
|
187 |
] |
|
|
188 |
}, |
|
|
189 |
{ |
|
|
190 |
"cell_type": "markdown", |
|
|
191 |
"metadata": { |
|
|
192 |
"id": "rxY0RHIl-1Lv" |
|
|
193 |
}, |
|
|
194 |
"source": [ |
|
|
195 |
"And we proceed right away to create a dataset to work with, the\n", |
|
|
196 |
"`DoubleCake` dataset. Firstly, we define two functions to enable us to\n", |
|
|
197 |
"generate the data. The details of these functions are not essential for\n", |
|
|
198 |
"understanding the demo, so don\\'t mind them if they are confusing.\n" |
|
|
199 |
] |
|
|
200 |
}, |
|
|
201 |
{ |
|
|
202 |
"cell_type": "code", |
|
|
203 |
"execution_count": 104, |
|
|
204 |
"metadata": { |
|
|
205 |
"id": "-MlPehLl-1Lw" |
|
|
206 |
}, |
|
|
207 |
"outputs": [], |
|
|
208 |
"source": [ |
|
|
209 |
"def _make_circular_data(num_sectors):\n", |
|
|
210 |
" \"\"\"Generate datapoints arranged in an even circle.\"\"\"\n", |
|
|
211 |
" center_indices = np.array(range(0, 2 * num_sectors))\n", |
|
|
212 |
" sector_angle = 2 * np.pi / (2 * num_sectors)\n", |
|
|
213 |
" angles = (center_indices + 0.5) * sector_angle\n", |
|
|
214 |
" x = 0.7 * np.cos(angles)\n", |
|
|
215 |
" y = 0.7 * np.sin(angles)\n", |
|
|
216 |
" labels = 2 * np.remainder(np.floor_divide(angles, sector_angle), 2) - 1\n", |
|
|
217 |
"\n", |
|
|
218 |
" return x, y, labels\n", |
|
|
219 |
"\n", |
|
|
220 |
"\n", |
|
|
221 |
"def make_double_cake_data(num_sectors):\n", |
|
|
222 |
" x1, y1, labels1 = _make_circular_data(num_sectors)\n", |
|
|
223 |
" x2, y2, labels2 = _make_circular_data(num_sectors)\n", |
|
|
224 |
"\n", |
|
|
225 |
" # x and y coordinates of the datapoints\n", |
|
|
226 |
" x = np.hstack([x1, 0.5 * x2])\n", |
|
|
227 |
" y = np.hstack([y1, 0.5 * y2])\n", |
|
|
228 |
"\n", |
|
|
229 |
" # Canonical form of dataset\n", |
|
|
230 |
" X = np.vstack([x, y]).T\n", |
|
|
231 |
"\n", |
|
|
232 |
" labels = np.hstack([labels1, -1 * labels2])\n", |
|
|
233 |
"\n", |
|
|
234 |
" # Canonical form of labels\n", |
|
|
235 |
" Y = labels.astype(int)\n", |
|
|
236 |
"\n", |
|
|
237 |
" return X, Y" |
|
|
238 |
] |
|
|
239 |
}, |
|
|
240 |
{ |
|
|
241 |
"cell_type": "markdown", |
|
|
242 |
"metadata": { |
|
|
243 |
"id": "sE-g9OvE-1Lw" |
|
|
244 |
}, |
|
|
245 |
"source": [ |
|
|
246 |
"Next, we define a function to help plot the `DoubleCake` data:\n" |
|
|
247 |
] |
|
|
248 |
}, |
|
|
249 |
{ |
|
|
250 |
"cell_type": "code", |
|
|
251 |
"execution_count": 105, |
|
|
252 |
"metadata": { |
|
|
253 |
"id": "dTzNJQG2-1Lw" |
|
|
254 |
}, |
|
|
255 |
"outputs": [], |
|
|
256 |
"source": [ |
|
|
257 |
"def plot_double_cake_data(X, Y, ax, num_sectors=None):\n", |
|
|
258 |
" \"\"\"Plot double cake data and corresponding sectors.\"\"\"\n", |
|
|
259 |
" x, y = X.T\n", |
|
|
260 |
" cmap = mpl.colors.ListedColormap([\"#FF0000\", \"#0000FF\"])\n", |
|
|
261 |
" ax.scatter(x, y, c=Y, cmap=cmap, s=25, marker=\"s\")\n", |
|
|
262 |
"\n", |
|
|
263 |
" if num_sectors is not None:\n", |
|
|
264 |
" sector_angle = 360 / num_sectors\n", |
|
|
265 |
" for i in range(num_sectors):\n", |
|
|
266 |
" color = [\"#FF0000\", \"#0000FF\"][(i % 2)]\n", |
|
|
267 |
" other_color = [\"#FF0000\", \"#0000FF\"][((i + 1) % 2)]\n", |
|
|
268 |
" ax.add_artist(\n", |
|
|
269 |
" mpl.patches.Wedge(\n", |
|
|
270 |
" (0, 0),\n", |
|
|
271 |
" 1,\n", |
|
|
272 |
" i * sector_angle,\n", |
|
|
273 |
" (i + 1) * sector_angle,\n", |
|
|
274 |
" lw=0,\n", |
|
|
275 |
" color=color,\n", |
|
|
276 |
" alpha=0.1,\n", |
|
|
277 |
" width=0.5,\n", |
|
|
278 |
" )\n", |
|
|
279 |
" )\n", |
|
|
280 |
" ax.add_artist(\n", |
|
|
281 |
" mpl.patches.Wedge(\n", |
|
|
282 |
" (0, 0),\n", |
|
|
283 |
" 0.5,\n", |
|
|
284 |
" i * sector_angle,\n", |
|
|
285 |
" (i + 1) * sector_angle,\n", |
|
|
286 |
" lw=0,\n", |
|
|
287 |
" color=other_color,\n", |
|
|
288 |
" alpha=0.1,\n", |
|
|
289 |
" )\n", |
|
|
290 |
" )\n", |
|
|
291 |
" ax.set_xlim(-1, 1)\n", |
|
|
292 |
"\n", |
|
|
293 |
" ax.set_ylim(-1, 1)\n", |
|
|
294 |
" ax.set_aspect(\"equal\")\n", |
|
|
295 |
" ax.axis(\"off\")\n", |
|
|
296 |
"\n", |
|
|
297 |
" return ax" |
|
|
298 |
] |
|
|
299 |
}, |
|
|
300 |
{ |
|
|
301 |
"cell_type": "markdown", |
|
|
302 |
"metadata": { |
|
|
303 |
"id": "5W9DtU_s-1Lw" |
|
|
304 |
}, |
|
|
305 |
"source": [ |
|
|
306 |
"Let\\'s now have a look at our dataset. In our example, we will work with\n", |
|
|
307 |
"3 sectors:\n" |
|
|
308 |
] |
|
|
309 |
}, |
|
|
310 |
{ |
|
|
311 |
"cell_type": "code", |
|
|
312 |
"execution_count": 106, |
|
|
313 |
"metadata": { |
|
|
314 |
"colab": { |
|
|
315 |
"base_uri": "https://localhost:8080/", |
|
|
316 |
"height": 406 |
|
|
317 |
}, |
|
|
318 |
"id": "9fVgxo-2-1Lw", |
|
|
319 |
"outputId": "7a1cadb3-d727-4eb2-a9e3-257b63fcad2f" |
|
|
320 |
}, |
|
|
321 |
"outputs": [ |
|
|
322 |
{ |
|
|
323 |
"output_type": "display_data", |
|
|
324 |
"data": { |
|
|
325 |
"text/plain": [ |
|
|
326 |
"<Figure size 640x480 with 1 Axes>" |
|
|
327 |
], |
|
|
328 |
"image/png": "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\n" |
|
|
329 |
}, |
|
|
330 |
"metadata": {} |
|
|
331 |
} |
|
|
332 |
], |
|
|
333 |
"source": [ |
|
|
334 |
"import matplotlib.pyplot as plt\n", |
|
|
335 |
"\n", |
|
|
336 |
"num_sectors = 3\n", |
|
|
337 |
"X, Y = make_double_cake_data(num_sectors)\n", |
|
|
338 |
"\n", |
|
|
339 |
"ax = plot_double_cake_data(X, Y, plt.gca(), num_sectors=num_sectors)" |
|
|
340 |
] |
|
|
341 |
}, |
|
|
342 |
{ |
|
|
343 |
"cell_type": "markdown", |
|
|
344 |
"metadata": { |
|
|
345 |
"id": "YiOE-Kte-1Lw" |
|
|
346 |
}, |
|
|
347 |
"source": [ |
|
|
348 |
"Defining a Quantum Embedding Kernel\n", |
|
|
349 |
"===================================\n", |
|
|
350 |
"\n", |
|
|
351 |
"PennyLane\\'s [kernels\n", |
|
|
352 |
"module](https://pennylane.readthedocs.io/en/latest/code/qml_kernels.html)\n", |
|
|
353 |
"allows for a particularly simple implementation of Quantum Embedding\n", |
|
|
354 |
"Kernels. The first ingredient we need for this is an *ansatz*, which we\n", |
|
|
355 |
"will construct by repeating a layer as building block. Let\\'s start by\n", |
|
|
356 |
"defining this layer:\n" |
|
|
357 |
] |
|
|
358 |
}, |
|
|
359 |
{ |
|
|
360 |
"cell_type": "code", |
|
|
361 |
"execution_count": 107, |
|
|
362 |
"metadata": { |
|
|
363 |
"id": "HoxftykS-1Lw" |
|
|
364 |
}, |
|
|
365 |
"outputs": [], |
|
|
366 |
"source": [ |
|
|
367 |
"import pennylane as qml\n", |
|
|
368 |
"\n", |
|
|
369 |
"\n", |
|
|
370 |
"def layer(x, params, wires, i0=0, inc=1):\n", |
|
|
371 |
" \"\"\"Building block of the embedding ansatz\"\"\"\n", |
|
|
372 |
" i = i0\n", |
|
|
373 |
" for j, wire in enumerate(wires):\n", |
|
|
374 |
" qml.Hadamard(wires=[wire])\n", |
|
|
375 |
" qml.RZ(x[i % len(x)], wires=[wire])\n", |
|
|
376 |
" i += inc\n", |
|
|
377 |
" qml.RY(params[0, j], wires=[wire])\n", |
|
|
378 |
"\n", |
|
|
379 |
" qml.broadcast(unitary=qml.CNOT, pattern=\"ring\", wires=wires) #, parameters=params[1])" |
|
|
380 |
] |
|
|
381 |
}, |
|
|
382 |
{ |
|
|
383 |
"cell_type": "markdown", |
|
|
384 |
"metadata": { |
|
|
385 |
"id": "Vz-Xc85B-1Lx" |
|
|
386 |
}, |
|
|
387 |
"source": [ |
|
|
388 |
"To construct the ansatz, this layer is repeated multiple times, reusing\n", |
|
|
389 |
"the datapoint `x` but feeding different variational parameters `params`\n", |
|
|
390 |
"into each of them. Together, the datapoint and the variational\n", |
|
|
391 |
"parameters fully determine the embedding ansatz $U(\\boldsymbol{x})$. In\n", |
|
|
392 |
"order to construct the full kernel circuit, we also require its adjoint\n", |
|
|
393 |
"$U(\\boldsymbol{x})^\\dagger$, which we can obtain via `qml.adjoint`.\n" |
|
|
394 |
] |
|
|
395 |
}, |
|
|
396 |
{ |
|
|
397 |
"cell_type": "code", |
|
|
398 |
"execution_count": 108, |
|
|
399 |
"metadata": { |
|
|
400 |
"id": "0u3Ie4pX-1Lx" |
|
|
401 |
}, |
|
|
402 |
"outputs": [], |
|
|
403 |
"source": [ |
|
|
404 |
"def ansatz(x, params, wires):\n", |
|
|
405 |
" \"\"\"The embedding ansatz\"\"\"\n", |
|
|
406 |
" for j, layer_params in enumerate(params):\n", |
|
|
407 |
" layer(x, layer_params, wires, i0=j * len(wires))\n", |
|
|
408 |
"\n", |
|
|
409 |
"\n", |
|
|
410 |
"adjoint_ansatz = qml.adjoint(ansatz)\n", |
|
|
411 |
"\n", |
|
|
412 |
"\n", |
|
|
413 |
"def random_params(num_wires, num_layers):\n", |
|
|
414 |
" \"\"\"Generate random variational parameters in the shape for the ansatz.\"\"\"\n", |
|
|
415 |
" return np.random.uniform(0, 2 * np.pi, (num_layers, 2, num_wires), requires_grad=True)" |
|
|
416 |
] |
|
|
417 |
}, |
|
|
418 |
{ |
|
|
419 |
"cell_type": "markdown", |
|
|
420 |
"metadata": { |
|
|
421 |
"id": "-3A0BtiZ-1Lx" |
|
|
422 |
}, |
|
|
423 |
"source": [ |
|
|
424 |
"Together with the ansatz we only need a device to run the quantum\n", |
|
|
425 |
"circuit on. For the purpose of this tutorial we will use PennyLane\\'s\n", |
|
|
426 |
"`default.qubit` device with 5 wires in analytic mode.\n" |
|
|
427 |
] |
|
|
428 |
}, |
|
|
429 |
{ |
|
|
430 |
"cell_type": "code", |
|
|
431 |
"execution_count": 109, |
|
|
432 |
"metadata": { |
|
|
433 |
"id": "VajRrjnM-1Lx" |
|
|
434 |
}, |
|
|
435 |
"outputs": [], |
|
|
436 |
"source": [ |
|
|
437 |
"dev = qml.device(\"lightning.qubit\", wires=5, shots=None)\n", |
|
|
438 |
"wires = dev.wires.tolist()" |
|
|
439 |
] |
|
|
440 |
}, |
|
|
441 |
{ |
|
|
442 |
"cell_type": "markdown", |
|
|
443 |
"metadata": { |
|
|
444 |
"id": "LBQiS_k5-1Lx" |
|
|
445 |
}, |
|
|
446 |
"source": [ |
|
|
447 |
"Let us now define the quantum circuit that realizes the kernel. We will\n", |
|
|
448 |
"compute the overlap of the quantum states by first applying the\n", |
|
|
449 |
"embedding of the first datapoint and then the adjoint of the embedding\n", |
|
|
450 |
"of the second datapoint. We finally extract the probabilities of\n", |
|
|
451 |
"observing each basis state.\n" |
|
|
452 |
] |
|
|
453 |
}, |
|
|
454 |
{ |
|
|
455 |
"cell_type": "code", |
|
|
456 |
"execution_count": 110, |
|
|
457 |
"metadata": { |
|
|
458 |
"id": "YUoDYzxl-1Lx" |
|
|
459 |
}, |
|
|
460 |
"outputs": [], |
|
|
461 |
"source": [ |
|
|
462 |
"@qml.qnode(dev, interface=\"autograd\")\n", |
|
|
463 |
"def kernel_circuit(x1, x2, params):\n", |
|
|
464 |
" ansatz(x1, params, wires=wires)\n", |
|
|
465 |
" adjoint_ansatz(x2, params, wires=wires)\n", |
|
|
466 |
" return qml.probs(wires=wires)" |
|
|
467 |
] |
|
|
468 |
}, |
|
|
469 |
{ |
|
|
470 |
"cell_type": "markdown", |
|
|
471 |
"metadata": { |
|
|
472 |
"id": "vp3JMl6k-1Lx" |
|
|
473 |
}, |
|
|
474 |
"source": [ |
|
|
475 |
"The kernel function itself is now obtained by looking at the probability\n", |
|
|
476 |
"of observing the all-zero state at the end of the kernel circuit --\n", |
|
|
477 |
"because of the ordering in `qml.probs`, this is the first entry:\n" |
|
|
478 |
] |
|
|
479 |
}, |
|
|
480 |
{ |
|
|
481 |
"cell_type": "code", |
|
|
482 |
"execution_count": 111, |
|
|
483 |
"metadata": { |
|
|
484 |
"id": "FzkdR5rH-1Lx" |
|
|
485 |
}, |
|
|
486 |
"outputs": [], |
|
|
487 |
"source": [ |
|
|
488 |
"def kernel(x1, x2, params):\n", |
|
|
489 |
" return kernel_circuit(x1, x2, params)[0]" |
|
|
490 |
] |
|
|
491 |
}, |
|
|
492 |
{ |
|
|
493 |
"cell_type": "markdown", |
|
|
494 |
"metadata": { |
|
|
495 |
"id": "v8d7TzEV-1Lx" |
|
|
496 |
}, |
|
|
497 |
"source": [ |
|
|
498 |
"::: {.note}\n", |
|
|
499 |
"::: {.title}\n", |
|
|
500 |
"Note\n", |
|
|
501 |
":::\n", |
|
|
502 |
"\n", |
|
|
503 |
"An alternative way to set up the kernel circuit in PennyLane would be to\n", |
|
|
504 |
"use the observable type\n", |
|
|
505 |
"[Projector](https://pennylane.readthedocs.io/en/latest/code/api/pennylane.Projector.html).\n", |
|
|
506 |
"This is shown in the [demo on kernel-based training of quantum\n", |
|
|
507 |
"models](https://pennylane.ai/qml/demos/tutorial_kernel_based_training.html),\n", |
|
|
508 |
"where you will also find more background information on the kernel\n", |
|
|
509 |
"circuit structure itself.\n", |
|
|
510 |
":::\n", |
|
|
511 |
"\n", |
|
|
512 |
"Before focusing on the kernel values we have to provide values for the\n", |
|
|
513 |
"variational parameters. At this point we fix the number of layers in the\n", |
|
|
514 |
"ansatz circuit to $6$.\n" |
|
|
515 |
] |
|
|
516 |
}, |
|
|
517 |
{ |
|
|
518 |
"cell_type": "code", |
|
|
519 |
"execution_count": 112, |
|
|
520 |
"metadata": { |
|
|
521 |
"id": "XND4t8Re-1Lx" |
|
|
522 |
}, |
|
|
523 |
"outputs": [], |
|
|
524 |
"source": [ |
|
|
525 |
"init_params = random_params(num_wires=5, num_layers=18)" |
|
|
526 |
] |
|
|
527 |
}, |
|
|
528 |
{ |
|
|
529 |
"cell_type": "markdown", |
|
|
530 |
"metadata": { |
|
|
531 |
"id": "D13009dA-1Lx" |
|
|
532 |
}, |
|
|
533 |
"source": [ |
|
|
534 |
"Now we can have a look at the kernel value between the first and the\n", |
|
|
535 |
"second datapoint:\n" |
|
|
536 |
] |
|
|
537 |
}, |
|
|
538 |
{ |
|
|
539 |
"cell_type": "code", |
|
|
540 |
"execution_count": 113, |
|
|
541 |
"metadata": { |
|
|
542 |
"colab": { |
|
|
543 |
"base_uri": "https://localhost:8080/", |
|
|
544 |
"height": 0 |
|
|
545 |
}, |
|
|
546 |
"id": "EPIxD8tx-1Lx", |
|
|
547 |
"outputId": "c6d1b2da-5640-440d-eb96-90db0ac7135a" |
|
|
548 |
}, |
|
|
549 |
"outputs": [ |
|
|
550 |
{ |
|
|
551 |
"output_type": "stream", |
|
|
552 |
"name": "stdout", |
|
|
553 |
"text": [ |
|
|
554 |
"The kernel value between the first and second datapoint is 0.006\n" |
|
|
555 |
] |
|
|
556 |
} |
|
|
557 |
], |
|
|
558 |
"source": [ |
|
|
559 |
"kernel_value = kernel(X[0], X[1], init_params)\n", |
|
|
560 |
"print(f\"The kernel value between the first and second datapoint is {kernel_value:.3f}\")" |
|
|
561 |
] |
|
|
562 |
}, |
|
|
563 |
{ |
|
|
564 |
"cell_type": "markdown", |
|
|
565 |
"metadata": { |
|
|
566 |
"id": "zftXzrUX-1Lx" |
|
|
567 |
}, |
|
|
568 |
"source": [ |
|
|
569 |
"The mutual kernel values between all elements of the dataset form the\n", |
|
|
570 |
"*kernel matrix*. We can inspect it via the\n", |
|
|
571 |
"`qml.kernels.square_kernel_matrix` method, which makes use of symmetry\n", |
|
|
572 |
"of the kernel,\n", |
|
|
573 |
"$k(\\boldsymbol{x}_i,\\boldsymbol{x}_j) = k(\\boldsymbol{x}_j, \\boldsymbol{x}_i)$.\n", |
|
|
574 |
"In addition, the option `assume_normalized_kernel=True` ensures that we\n", |
|
|
575 |
"do not calculate the entries between the same datapoints, as we know\n", |
|
|
576 |
"them to be 1 for our noiseless simulation. Overall this means that we\n", |
|
|
577 |
"compute $\\frac{1}{2}(N^2-N)$ kernel values for $N$ datapoints. To\n", |
|
|
578 |
"include the variational parameters, we construct a `lambda` function\n", |
|
|
579 |
"that fixes them to the values we sampled above.\n" |
|
|
580 |
] |
|
|
581 |
}, |
|
|
582 |
{ |
|
|
583 |
"cell_type": "code", |
|
|
584 |
"execution_count": 114, |
|
|
585 |
"metadata": { |
|
|
586 |
"colab": { |
|
|
587 |
"base_uri": "https://localhost:8080/", |
|
|
588 |
"height": 0 |
|
|
589 |
}, |
|
|
590 |
"id": "EJ6j5XF1-1Lx", |
|
|
591 |
"outputId": "d7e85836-319c-4c16-b44a-5ea11ad2a259" |
|
|
592 |
}, |
|
|
593 |
"outputs": [ |
|
|
594 |
{ |
|
|
595 |
"output_type": "stream", |
|
|
596 |
"name": "stdout", |
|
|
597 |
"text": [ |
|
|
598 |
"[[1. 0.006 0.048 0.017 0.012 0.018 0.141 0.007 0.007 0.018 0.001 0.012]\n", |
|
|
599 |
" [0.006 1. 0.047 0.012 0.071 0.002 0.013 0.369 0.057 0.001 0.017 0.007]\n", |
|
|
600 |
" [0.048 0.047 1. 0.018 0.002 0.056 0.012 0.022 0.286 0.098 0.015 0.013]\n", |
|
|
601 |
" [0.017 0.012 0.018 1. 0.006 0.048 0.018 0.001 0.012 0.141 0.007 0.007]\n", |
|
|
602 |
" [0.012 0.071 0.002 0.006 1. 0.047 0.001 0.017 0.007 0.013 0.369 0.057]\n", |
|
|
603 |
" [0.018 0.002 0.056 0.048 0.047 1. 0.098 0.015 0.013 0.012 0.022 0.286]\n", |
|
|
604 |
" [0.141 0.013 0.012 0.018 0.001 0.098 1. 0.312 0.018 0.006 0.038 0.303]\n", |
|
|
605 |
" [0.007 0.369 0.022 0.001 0.017 0.015 0.312 1. 0.208 0.038 0.016 0.069]\n", |
|
|
606 |
" [0.007 0.057 0.286 0.012 0.007 0.013 0.018 0.208 1. 0.303 0.069 0.008]\n", |
|
|
607 |
" [0.018 0.001 0.098 0.141 0.013 0.012 0.006 0.038 0.303 1. 0.312 0.018]\n", |
|
|
608 |
" [0.001 0.017 0.015 0.007 0.369 0.022 0.038 0.016 0.069 0.312 1. 0.208]\n", |
|
|
609 |
" [0.012 0.007 0.013 0.007 0.057 0.286 0.303 0.069 0.008 0.018 0.208 1. ]]\n" |
|
|
610 |
] |
|
|
611 |
} |
|
|
612 |
], |
|
|
613 |
"source": [ |
|
|
614 |
"init_kernel = lambda x1, x2: kernel(x1, x2, init_params)\n", |
|
|
615 |
"K_init = qml.kernels.square_kernel_matrix(X, init_kernel, assume_normalized_kernel=True)\n", |
|
|
616 |
"\n", |
|
|
617 |
"with np.printoptions(precision=3, suppress=True):\n", |
|
|
618 |
" print(K_init)" |
|
|
619 |
] |
|
|
620 |
}, |
|
|
621 |
{ |
|
|
622 |
"cell_type": "markdown", |
|
|
623 |
"metadata": { |
|
|
624 |
"id": "nRfsymWl-1Lx" |
|
|
625 |
}, |
|
|
626 |
"source": [ |
|
|
627 |
"Using the Quantum Embedding Kernel for predictions\n", |
|
|
628 |
"==================================================\n", |
|
|
629 |
"\n", |
|
|
630 |
"The quantum kernel alone can not be used to make predictions on a\n", |
|
|
631 |
"dataset, becaues it is essentially just a tool to measure the similarity\n", |
|
|
632 |
"between two datapoints. To perform an actual prediction we will make use\n", |
|
|
633 |
"of scikit-learn\\'s Support Vector Classifier (SVC).\n" |
|
|
634 |
] |
|
|
635 |
}, |
|
|
636 |
{ |
|
|
637 |
"cell_type": "code", |
|
|
638 |
"execution_count": 115, |
|
|
639 |
"metadata": { |
|
|
640 |
"id": "k6YZKy7J-1Lx" |
|
|
641 |
}, |
|
|
642 |
"outputs": [], |
|
|
643 |
"source": [ |
|
|
644 |
"from sklearn.svm import SVC" |
|
|
645 |
] |
|
|
646 |
}, |
|
|
647 |
{ |
|
|
648 |
"cell_type": "markdown", |
|
|
649 |
"metadata": { |
|
|
650 |
"id": "s3GDnc3R-1Ly" |
|
|
651 |
}, |
|
|
652 |
"source": [ |
|
|
653 |
"To construct the SVM, we need to supply `sklearn.svm.SVC` with a\n", |
|
|
654 |
"function that takes two sets of datapoints and returns the associated\n", |
|
|
655 |
"kernel matrix. We can make use of the function\n", |
|
|
656 |
"`qml.kernels.kernel_matrix` that provides this functionality. It expects\n", |
|
|
657 |
"the kernel to not have additional parameters besides the datapoints,\n", |
|
|
658 |
"which is why we again supply the variational parameters via the `lambda`\n", |
|
|
659 |
"function from above. Once we have this, we can let scikit-learn adjust\n", |
|
|
660 |
"the SVM from our Quantum Embedding Kernel.\n", |
|
|
661 |
"\n", |
|
|
662 |
"::: {.note}\n", |
|
|
663 |
"::: {.title}\n", |
|
|
664 |
"Note\n", |
|
|
665 |
":::\n", |
|
|
666 |
"\n", |
|
|
667 |
"This step does *not* modify the variational parameters in our circuit\n", |
|
|
668 |
"ansatz. What it does is solving a different optimization task for the\n", |
|
|
669 |
"$\\alpha$ and $b$ vectors we introduced in the beginning.\n", |
|
|
670 |
":::\n" |
|
|
671 |
] |
|
|
672 |
}, |
|
|
673 |
{ |
|
|
674 |
"cell_type": "code", |
|
|
675 |
"execution_count": 116, |
|
|
676 |
"metadata": { |
|
|
677 |
"id": "irVOPzix-1Ly" |
|
|
678 |
}, |
|
|
679 |
"outputs": [], |
|
|
680 |
"source": [ |
|
|
681 |
"svm = SVC(kernel=lambda X1, X2: qml.kernels.kernel_matrix(X1, X2, init_kernel)).fit(X, Y)" |
|
|
682 |
] |
|
|
683 |
}, |
|
|
684 |
{ |
|
|
685 |
"cell_type": "markdown", |
|
|
686 |
"metadata": { |
|
|
687 |
"id": "I4xR2Txu-1Ly" |
|
|
688 |
}, |
|
|
689 |
"source": [ |
|
|
690 |
"To see how well our classifier performs we will measure which percentage\n", |
|
|
691 |
"of the dataset it classifies correctly.\n" |
|
|
692 |
] |
|
|
693 |
}, |
|
|
694 |
{ |
|
|
695 |
"cell_type": "code", |
|
|
696 |
"execution_count": 117, |
|
|
697 |
"metadata": { |
|
|
698 |
"colab": { |
|
|
699 |
"base_uri": "https://localhost:8080/", |
|
|
700 |
"height": 0 |
|
|
701 |
}, |
|
|
702 |
"id": "ZDX6Qvwk-1Ly", |
|
|
703 |
"outputId": "53ef9f62-b094-4e10-d18f-5fbf6d46b984" |
|
|
704 |
}, |
|
|
705 |
"outputs": [ |
|
|
706 |
{ |
|
|
707 |
"output_type": "stream", |
|
|
708 |
"name": "stdout", |
|
|
709 |
"text": [ |
|
|
710 |
"The accuracy of the kernel with random parameters is 1.000\n" |
|
|
711 |
] |
|
|
712 |
} |
|
|
713 |
], |
|
|
714 |
"source": [ |
|
|
715 |
"def accuracy(classifier, X, Y_target):\n", |
|
|
716 |
" return 1 - np.count_nonzero(classifier.predict(X) - Y_target) / len(Y_target)\n", |
|
|
717 |
"\n", |
|
|
718 |
"\n", |
|
|
719 |
"accuracy_init = accuracy(svm, X, Y)\n", |
|
|
720 |
"print(f\"The accuracy of the kernel with random parameters is {accuracy_init:.3f}\")" |
|
|
721 |
] |
|
|
722 |
}, |
|
|
723 |
{ |
|
|
724 |
"cell_type": "markdown", |
|
|
725 |
"metadata": { |
|
|
726 |
"id": "PPB_3tDn-1Ly" |
|
|
727 |
}, |
|
|
728 |
"source": [ |
|
|
729 |
"We are also interested in seeing what the decision boundaries in this\n", |
|
|
730 |
"classification look like. This could help us spotting overfitting issues\n", |
|
|
731 |
"visually in more complex data sets. To this end we will introduce a\n", |
|
|
732 |
"second helper method.\n" |
|
|
733 |
] |
|
|
734 |
}, |
|
|
735 |
{ |
|
|
736 |
"cell_type": "code", |
|
|
737 |
"execution_count": 118, |
|
|
738 |
"metadata": { |
|
|
739 |
"id": "EQZNfZjQ-1Ly" |
|
|
740 |
}, |
|
|
741 |
"outputs": [], |
|
|
742 |
"source": [ |
|
|
743 |
"def plot_decision_boundaries(classifier, ax, N_gridpoints=14):\n", |
|
|
744 |
" _xx, _yy = np.meshgrid(np.linspace(-1, 1, N_gridpoints), np.linspace(-1, 1, N_gridpoints))\n", |
|
|
745 |
"\n", |
|
|
746 |
" _zz = np.zeros_like(_xx)\n", |
|
|
747 |
" for idx in np.ndindex(*_xx.shape):\n", |
|
|
748 |
" _zz[idx] = classifier.predict(np.array([_xx[idx], _yy[idx]])[np.newaxis, :])\n", |
|
|
749 |
"\n", |
|
|
750 |
" plot_data = {\"_xx\": _xx, \"_yy\": _yy, \"_zz\": _zz}\n", |
|
|
751 |
" ax.contourf(\n", |
|
|
752 |
" _xx,\n", |
|
|
753 |
" _yy,\n", |
|
|
754 |
" _zz,\n", |
|
|
755 |
" cmap=mpl.colors.ListedColormap([\"#FF0000\", \"#0000FF\"]),\n", |
|
|
756 |
" alpha=0.2,\n", |
|
|
757 |
" levels=[-1, 0, 1],\n", |
|
|
758 |
" )\n", |
|
|
759 |
" plot_double_cake_data(X, Y, ax)\n", |
|
|
760 |
"\n", |
|
|
761 |
" return plot_data" |
|
|
762 |
] |
|
|
763 |
}, |
|
|
764 |
{ |
|
|
765 |
"cell_type": "markdown", |
|
|
766 |
"metadata": { |
|
|
767 |
"id": "26F1Bqg9-1Ly" |
|
|
768 |
}, |
|
|
769 |
"source": [ |
|
|
770 |
"With that done, let\\'s have a look at the decision boundaries for our\n", |
|
|
771 |
"initial classifier:\n" |
|
|
772 |
] |
|
|
773 |
}, |
|
|
774 |
{ |
|
|
775 |
"cell_type": "code", |
|
|
776 |
"execution_count": 119, |
|
|
777 |
"metadata": { |
|
|
778 |
"colab": { |
|
|
779 |
"base_uri": "https://localhost:8080/", |
|
|
780 |
"height": 406 |
|
|
781 |
}, |
|
|
782 |
"id": "JQ33viIF-1Ly", |
|
|
783 |
"outputId": "daf49e6b-3d32-4604-a5b8-d2deab11cda1" |
|
|
784 |
}, |
|
|
785 |
"outputs": [ |
|
|
786 |
{ |
|
|
787 |
"output_type": "display_data", |
|
|
788 |
"data": { |
|
|
789 |
"text/plain": [ |
|
|
790 |
"<Figure size 640x480 with 1 Axes>" |
|
|
791 |
], |
|
|
792 |
"image/png": "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\n" |
|
|
793 |
}, |
|
|
794 |
"metadata": {} |
|
|
795 |
} |
|
|
796 |
], |
|
|
797 |
"source": [ |
|
|
798 |
"init_plot_data = plot_decision_boundaries(svm, plt.gca())" |
|
|
799 |
] |
|
|
800 |
}, |
|
|
801 |
{ |
|
|
802 |
"cell_type": "markdown", |
|
|
803 |
"metadata": { |
|
|
804 |
"id": "TLeU4kMX-1Ly" |
|
|
805 |
}, |
|
|
806 |
"source": [ |
|
|
807 |
"We see the outer points in the dataset can be correctly classified, but\n", |
|
|
808 |
"we still struggle with the inner circle. But remember we have a circuit\n", |
|
|
809 |
"with many free parameters! It is reasonable to believe we can give\n", |
|
|
810 |
"values to those variational parameters which improve the overall\n", |
|
|
811 |
"accuracy of our SVC.\n", |
|
|
812 |
"\n", |
|
|
813 |
"Training the Quantum Embedding Kernel\n", |
|
|
814 |
"=====================================\n", |
|
|
815 |
"\n", |
|
|
816 |
"To be able to train the Quantum Embedding Kernel we need some measure of\n", |
|
|
817 |
"how well it fits the dataset in question. Performing an exhaustive\n", |
|
|
818 |
"search in parameter space is not a good solution because it is very\n", |
|
|
819 |
"resource intensive, and since the accuracy is a discrete quantity we\n", |
|
|
820 |
"would not be able to detect small improvements.\n", |
|
|
821 |
"\n", |
|
|
822 |
"We can, however, resort to a more specialized measure, the\n", |
|
|
823 |
"*kernel-target alignment*. The kernel-target alignment compares the\n", |
|
|
824 |
"similarity predicted by the quantum kernel to the actual labels of the\n", |
|
|
825 |
"training data. It is based on *kernel alignment*, a similiarity measure\n", |
|
|
826 |
"between two kernels with given kernel matrices $K_1$ and $K_2$:\n", |
|
|
827 |
"\n", |
|
|
828 |
"$$\\operatorname{KA}(K_1, K_2) = \\frac{\\operatorname{Tr}(K_1 K_2)}{\\sqrt{\\operatorname{Tr}(K_1^2)\\operatorname{Tr}(K_2^2)}}.$$\n", |
|
|
829 |
"\n", |
|
|
830 |
"::: {.note}\n", |
|
|
831 |
"::: {.title}\n", |
|
|
832 |
"Note\n", |
|
|
833 |
":::\n", |
|
|
834 |
"\n", |
|
|
835 |
"Seen from a more theoretical side, $\\operatorname{KA}$ is nothing else\n", |
|
|
836 |
"than the cosine of the angle between the kernel matrices $K_1$ and $K_2$\n", |
|
|
837 |
"if we see them as vectors in the space of matrices with the\n", |
|
|
838 |
"Hilbert-Schmidt (or Frobenius) scalar product\n", |
|
|
839 |
"$\\langle A, B \\rangle = \\operatorname{Tr}(A^T B)$. This reinforces the\n", |
|
|
840 |
"geometric picture of how this measure relates to objects, namely two\n", |
|
|
841 |
"kernels, being aligned in a vector space.\n", |
|
|
842 |
":::\n", |
|
|
843 |
"\n", |
|
|
844 |
"The training data enters the picture by defining an *ideal* kernel\n", |
|
|
845 |
"function that expresses the original labelling in the vector\n", |
|
|
846 |
"$\\boldsymbol{y}$ by assigning to two datapoints the product of the\n", |
|
|
847 |
"corresponding labels:\n", |
|
|
848 |
"\n", |
|
|
849 |
"$$k_{\\boldsymbol{y}}(\\boldsymbol{x}_i, \\boldsymbol{x}_j) = y_i y_j.$$\n", |
|
|
850 |
"\n", |
|
|
851 |
"The assigned kernel is thus $+1$ if both datapoints lie in the same\n", |
|
|
852 |
"class and $-1$ otherwise and its kernel matrix is simply given by the\n", |
|
|
853 |
"outer product $\\boldsymbol{y}\\boldsymbol{y}^T$. The kernel-target\n", |
|
|
854 |
"alignment is then defined as the kernel alignment of the kernel matrix\n", |
|
|
855 |
"$K$ generated by the quantum kernel and\n", |
|
|
856 |
"$\\boldsymbol{y}\\boldsymbol{y}^T$:\n", |
|
|
857 |
"\n", |
|
|
858 |
"$$\\operatorname{KTA}_{\\boldsymbol{y}}(K)\n", |
|
|
859 |
"= \\frac{\\operatorname{Tr}(K \\boldsymbol{y}\\boldsymbol{y}^T)}{\\sqrt{\\operatorname{Tr}(K^2)\\operatorname{Tr}((\\boldsymbol{y}\\boldsymbol{y}^T)^2)}}\n", |
|
|
860 |
"= \\frac{\\boldsymbol{y}^T K \\boldsymbol{y}}{\\sqrt{\\operatorname{Tr}(K^2)} N}$$\n", |
|
|
861 |
"\n", |
|
|
862 |
"where $N$ is the number of elements in $\\boldsymbol{y}$, that is the\n", |
|
|
863 |
"number of datapoints in the dataset.\n", |
|
|
864 |
"\n", |
|
|
865 |
"In summary, the kernel-target alignment effectively captures how well\n", |
|
|
866 |
"the kernel you chose reproduces the actual similarities of the data. It\n", |
|
|
867 |
"does have one drawback, however: having a high kernel-target alignment\n", |
|
|
868 |
"is only a necessary but not a sufficient condition for a good\n", |
|
|
869 |
"performance of the kernel. This means having good alignment is\n", |
|
|
870 |
"guaranteed for good performance, but optimal alignment will not always\n", |
|
|
871 |
"bring optimal training accuracy with it.\n", |
|
|
872 |
"\n", |
|
|
873 |
"Let\\'s now come back to the actual implementation. PennyLane\\'s\n", |
|
|
874 |
"`kernels` module allows you to easily evaluate the kernel target\n", |
|
|
875 |
"alignment:\n" |
|
|
876 |
] |
|
|
877 |
}, |
|
|
878 |
{ |
|
|
879 |
"cell_type": "code", |
|
|
880 |
"execution_count": 120, |
|
|
881 |
"metadata": { |
|
|
882 |
"colab": { |
|
|
883 |
"base_uri": "https://localhost:8080/", |
|
|
884 |
"height": 0 |
|
|
885 |
}, |
|
|
886 |
"id": "N1sKPuO3-1Ly", |
|
|
887 |
"outputId": "e9623cb5-fdde-42fd-c64b-f8d046443613" |
|
|
888 |
}, |
|
|
889 |
"outputs": [ |
|
|
890 |
{ |
|
|
891 |
"output_type": "stream", |
|
|
892 |
"name": "stdout", |
|
|
893 |
"text": [ |
|
|
894 |
"The kernel-target alignment for our dataset and random parameters is 0.145\n" |
|
|
895 |
] |
|
|
896 |
} |
|
|
897 |
], |
|
|
898 |
"source": [ |
|
|
899 |
"kta_init = qml.kernels.target_alignment(X, Y, init_kernel, assume_normalized_kernel=True)\n", |
|
|
900 |
"\n", |
|
|
901 |
"print(f\"The kernel-target alignment for our dataset and random parameters is {kta_init:.3f}\")" |
|
|
902 |
] |
|
|
903 |
}, |
|
|
904 |
{ |
|
|
905 |
"cell_type": "markdown", |
|
|
906 |
"metadata": { |
|
|
907 |
"id": "eOZMWm-p-1Ly" |
|
|
908 |
}, |
|
|
909 |
"source": [ |
|
|
910 |
"Now let\\'s code up an optimization loop and improve the kernel-target\n", |
|
|
911 |
"alignment!\n", |
|
|
912 |
"\n", |
|
|
913 |
"We will make use of regular gradient descent optimization. To speed up\n", |
|
|
914 |
"the optimization we will not use the entire training set to compute\n", |
|
|
915 |
"$\\operatorname{KTA}$ but rather sample smaller subsets of the data at\n", |
|
|
916 |
"each step, we choose $4$ datapoints at random. Remember that\n", |
|
|
917 |
"PennyLane\\'s built-in optimizer works to *minimize* the cost function\n", |
|
|
918 |
"that is given to it, which is why we have to multiply the kernel target\n", |
|
|
919 |
"alignment by $-1$ to actually *maximize* it in the process.\n", |
|
|
920 |
"\n", |
|
|
921 |
"::: {.note}\n", |
|
|
922 |
"::: {.title}\n", |
|
|
923 |
"Note\n", |
|
|
924 |
":::\n", |
|
|
925 |
"\n", |
|
|
926 |
"Currently, the function `qml.kernels.target_alignment` is not\n", |
|
|
927 |
"differentiable yet, making it unfit for gradient descent optimization.\n", |
|
|
928 |
"We therefore first define a differentiable version of this function.\n", |
|
|
929 |
":::\n" |
|
|
930 |
] |
|
|
931 |
}, |
|
|
932 |
{ |
|
|
933 |
"cell_type": "code", |
|
|
934 |
"execution_count": 121, |
|
|
935 |
"metadata": { |
|
|
936 |
"colab": { |
|
|
937 |
"base_uri": "https://localhost:8080/", |
|
|
938 |
"height": 314 |
|
|
939 |
}, |
|
|
940 |
"id": "o8BNL8bP-1Ly", |
|
|
941 |
"outputId": "443ee150-320a-4fd1-f828-fd1c79ba431e" |
|
|
942 |
}, |
|
|
943 |
"outputs": [ |
|
|
944 |
{ |
|
|
945 |
"output_type": "error", |
|
|
946 |
"ename": "KeyboardInterrupt", |
|
|
947 |
"evalue": "ignored", |
|
|
948 |
"traceback": [ |
|
|
949 |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
|
|
950 |
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", |
|
|
951 |
"\u001b[0;32m<ipython-input-121-2d12ece3dd74>\u001b[0m in \u001b[0;36m<cell line: 34>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 43\u001b[0m )\n\u001b[1;32m 44\u001b[0m \u001b[0;31m# Optimization step\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 45\u001b[0;31m \u001b[0mparams\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mopt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcost\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 46\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[0;31m# Report the alignment on the full dataset every 50 steps.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
952 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/optimize/gradient_descent.py\u001b[0m in \u001b[0;36mstep\u001b[0;34m(self, objective_fn, grad_fn, *args, **kwargs)\u001b[0m\n\u001b[1;32m 86\u001b[0m \"\"\"\n\u001b[1;32m 87\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 88\u001b[0;31m \u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompute_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobjective_fn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgrad_fn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mgrad_fn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 89\u001b[0m \u001b[0mnew_args\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 90\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
953 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/optimize/gradient_descent.py\u001b[0m in \u001b[0;36mcompute_grad\u001b[0;34m(objective_fn, args, kwargs, grad_fn)\u001b[0m\n\u001b[1;32m 115\u001b[0m \"\"\"\n\u001b[1;32m 116\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_gradient\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobjective_fn\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mgrad_fn\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0mgrad_fn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 117\u001b[0;31m \u001b[0mgrad\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 118\u001b[0m \u001b[0mforward\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"forward\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 119\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
954 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/_grad.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 117\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 118\u001b[0;31m \u001b[0mgrad_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mans\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgrad_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# pylint: disable=not-callable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 119\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_forward\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mans\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 120\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
955 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36mnary_f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0munary_operator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0munary_f\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mnary_op_args\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mnary_op_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_f\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_operator\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
956 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/_grad.py\u001b[0m in \u001b[0;36m_grad_with_forward\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 142\u001b[0m )\n\u001b[1;32m 143\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 144\u001b[0;31m \u001b[0mgrad_value\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mans\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mones\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 145\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mgrad_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mans\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 146\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
957 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/autograd/core.py\u001b[0m in \u001b[0;36mvjp\u001b[0;34m(g)\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m \u001b[0;32mdef\u001b[0m \u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mbackward_pass\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_node\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 15\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvjp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_value\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
958 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/autograd/core.py\u001b[0m in \u001b[0;36mbackward_pass\u001b[0;34m(g, end_node)\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mnode\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtoposort\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mend_node\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0moutgrad\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0moutgrads\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnode\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 21\u001b[0;31m \u001b[0mingrads\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0moutgrad\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 22\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mingrad\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparents\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mingrads\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0moutgrads\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0madd_outgrads\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0moutgrads\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mingrad\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
959 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/autograd/core.py\u001b[0m in \u001b[0;36m<lambda>\u001b[0;34m(g)\u001b[0m\n\u001b[1;32m 65\u001b[0m \"VJP of {} wrt argnum 0 not defined\".format(fun.__name__))\n\u001b[1;32m 66\u001b[0m \u001b[0mvjp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvjpfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mans\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 67\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 68\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mL\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 69\u001b[0m \u001b[0margnum_0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margnum_1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margnums\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
960 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/interfaces/autograd.py\u001b[0m in \u001b[0;36mgrad_fn\u001b[0;34m(dy)\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 232\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mgradient_fn\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mgradient_fn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__name__\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"param_shift\"\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mcomputing_jacobian\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 233\u001b[0;31m \u001b[0mjacs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_get_jac_with_caching\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 234\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 235\u001b[0m \u001b[0mjacs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mans\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
961 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/interfaces/autograd.py\u001b[0m in \u001b[0;36m_get_jac_with_caching\u001b[0;34m()\u001b[0m\n\u001b[1;32m 203\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[0mg_tapes\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mqml\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtransforms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmap_batch_transform\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpartial_gradient_fn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtapes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 205\u001b[0;31m \u001b[0mres\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mexecute_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg_tapes\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mgradient_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 206\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 207\u001b[0m \u001b[0mjacs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mres\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
962 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/interfaces/execution.py\u001b[0m in \u001b[0;36minner_execute_with_empty_jac\u001b[0;34m(tapes, **_)\u001b[0m\n\u001b[1;32m 586\u001b[0m \u001b[0;31m# moved to its own explicit step so it will be easier to remove\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 587\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0minner_execute_with_empty_jac\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtapes\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0m_\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 588\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0minner_execute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtapes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 589\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 590\u001b[0m \u001b[0mexecute_fn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minner_execute_with_empty_jac\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
963 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/interfaces/execution.py\u001b[0m in \u001b[0;36minner_execute\u001b[0;34m(tapes, **_)\u001b[0m\n\u001b[1;32m 244\u001b[0m \"\"\"\n\u001b[1;32m 245\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mexpand_fn\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 246\u001b[0;31m \u001b[0mtapes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexpand_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtapes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 247\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnumpy_only\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 248\u001b[0m \u001b[0mtapes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mqml\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtransforms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconvert_to_numpy_parameters\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtapes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
964 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/interfaces/execution.py\u001b[0m in \u001b[0;36m<genexpr>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 244\u001b[0m \"\"\"\n\u001b[1;32m 245\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mexpand_fn\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 246\u001b[0;31m \u001b[0mtapes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexpand_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtapes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 247\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnumpy_only\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 248\u001b[0m \u001b[0mtapes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mqml\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtransforms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconvert_to_numpy_parameters\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtapes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
965 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/interfaces/execution.py\u001b[0m in \u001b[0;36mdevice_expansion_function\u001b[0;34m(tape)\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdevice_expansion_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtape\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# pylint: disable=function-redefined\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[0;34m\"\"\"A wrapper around the device ``expand_fn``.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 206\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mdevice\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexpand_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtape\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax_expansion\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmax_expansion\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 207\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 208\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mdevice_expansion_function\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
966 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/_device.py\u001b[0m in \u001b[0;36mexpand_fn\u001b[0;34m(self, circuit, max_expansion)\u001b[0m\n\u001b[1;32m 716\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcustom_expand_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax_expansion\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmax_expansion\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 717\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 718\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_expand_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax_expansion\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmax_expansion\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 719\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 720\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mbatch_transform\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcircuit\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mQuantumTape\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
967 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/_device.py\u001b[0m in \u001b[0;36mdefault_expand_fn\u001b[0;34m(self, circuit, max_expansion)\u001b[0m\n\u001b[1;32m 687\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 688\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mops_not_supported\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 689\u001b[0;31m circuit = _local_tape_expand(\n\u001b[0m\u001b[1;32m 690\u001b[0m \u001b[0mcircuit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdepth\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmax_expansion\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstop_at\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstopping_condition\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 691\u001b[0m )\n", |
|
|
968 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/_device.py\u001b[0m in \u001b[0;36m_local_tape_expand\u001b[0;34m(tape, depth, stop_at)\u001b[0m\n\u001b[1;32m 82\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mobj\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhas_decomposition\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 83\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mQueuingManager\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstop_recording\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 84\u001b[0;31m \u001b[0mobj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mQuantumScript\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecomposition\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_update\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 85\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 86\u001b[0m \u001b[0mnew_queue\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
969 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/ops/op_math/adjoint.py\u001b[0m in \u001b[0;36mdecomposition\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 273\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecomposition\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 274\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbase\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhas_adjoint\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 275\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbase\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madjoint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 276\u001b[0m \u001b[0mbase_decomp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbase\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecomposition\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 277\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mAdjoint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mop\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mop\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mreversed\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbase_decomp\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
970 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/ops/qubit/parametric_ops_single_qubit.py\u001b[0m in \u001b[0;36madjoint\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0madjoint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 206\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mRY\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwires\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwires\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 207\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 208\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mpow\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mz\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
971 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/ops/qubit/parametric_ops_single_qubit.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, phi, wires, id)\u001b[0m\n\u001b[1;32m 168\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 169\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mphi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwires\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mid\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 170\u001b[0;31m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mphi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwires\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwires\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mid\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mid\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 171\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 172\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mstaticmethod\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
972 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/operation.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, wires, id, *params)\u001b[0m\n\u001b[1;32m 1745\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1746\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwires\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mid\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1747\u001b[0;31m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwires\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwires\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mid\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mid\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1748\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1749\u001b[0m \u001b[0;31m# check the grad_recipe validity\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
973 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/operation.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, wires, id, *params)\u001b[0m\n\u001b[1;32m 1050\u001b[0m )\n\u001b[1;32m 1051\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1052\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_batching\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1053\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1054\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0mp\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mp\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
974 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/operation.py\u001b[0m in \u001b[0;36m_check_batching\u001b[0;34m(self, params)\u001b[0m\n\u001b[1;32m 1070\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1071\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1072\u001b[0;31m \u001b[0mndims\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mqml\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mp\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1073\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mValueError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1074\u001b[0m \u001b[0;31m# TODO:[dwierichs] When using tf.function with an input_signature that contains\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
975 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/operation.py\u001b[0m in \u001b[0;36m<genexpr>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 1070\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1071\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1072\u001b[0;31m \u001b[0mndims\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mqml\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mp\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1073\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mValueError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1074\u001b[0m \u001b[0;31m# TODO:[dwierichs] When using tf.function with an input_signature that contains\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
976 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/autoray/autoray.py\u001b[0m in \u001b[0;36mdo\u001b[0;34m(fn, like, *args, **kwargs)\u001b[0m\n\u001b[1;32m 78\u001b[0m \"\"\"\n\u001b[1;32m 79\u001b[0m \u001b[0mbackend\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mchoose_backend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlike\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlike\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 80\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mget_lib_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbackend\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 81\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 82\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
977 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/math/single_dispatch.py\u001b[0m in \u001b[0;36m<lambda>\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 125\u001b[0m \u001b[0mar\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautoray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_MODULE_ALIASES\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"autograd\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"pennylane.numpy\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 126\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 127\u001b[0;31m \u001b[0mar\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregister_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"autograd\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"ndim\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0m_i\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"autograd\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumpy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 128\u001b[0m \u001b[0mar\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregister_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"autograd\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"shape\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0m_i\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"autograd\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumpy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 129\u001b[0m \u001b[0mar\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregister_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"autograd\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"flatten\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflatten\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
978 |
"\u001b[0;32m/usr/local/lib/python3.10/dist-packages/pennylane/math/single_dispatch.py\u001b[0m in \u001b[0;36m_i\u001b[0;34m(name)\u001b[0m\n\u001b[1;32m 34\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mimport_module\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"pennylane\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 36\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mimport_module\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 37\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
979 |
"\u001b[0;32m/usr/lib/python3.10/importlib/__init__.py\u001b[0m in \u001b[0;36mimport_module\u001b[0;34m(name, package)\u001b[0m\n\u001b[1;32m 124\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 125\u001b[0m \u001b[0mlevel\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 126\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_bootstrap\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_gcd_import\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mlevel\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpackage\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlevel\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 127\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 128\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
|
|
980 |
"\u001b[0;32m/usr/lib/python3.10/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_gcd_import\u001b[0;34m(name, package, level)\u001b[0m\n", |
|
|
981 |
"\u001b[0;32m/usr/lib/python3.10/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load\u001b[0;34m(name, import_)\u001b[0m\n", |
|
|
982 |
"\u001b[0;32m/usr/lib/python3.10/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m__enter__\u001b[0;34m(self)\u001b[0m\n", |
|
|
983 |
"\u001b[0;32m/usr/lib/python3.10/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m_get_module_lock\u001b[0;34m(name)\u001b[0m\n", |
|
|
984 |
"\u001b[0;32m/usr/lib/python3.10/importlib/_bootstrap.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, name)\u001b[0m\n", |
|
|
985 |
"\u001b[0;31mKeyboardInterrupt\u001b[0m: " |
|
|
986 |
] |
|
|
987 |
} |
|
|
988 |
], |
|
|
989 |
"source": [ |
|
|
990 |
"def target_alignment(\n", |
|
|
991 |
" X,\n", |
|
|
992 |
" Y,\n", |
|
|
993 |
" kernel,\n", |
|
|
994 |
" assume_normalized_kernel=False,\n", |
|
|
995 |
" rescale_class_labels=True,\n", |
|
|
996 |
"):\n", |
|
|
997 |
" \"\"\"Kernel-target alignment between kernel and labels.\"\"\"\n", |
|
|
998 |
"\n", |
|
|
999 |
" K = qml.kernels.square_kernel_matrix(\n", |
|
|
1000 |
" X,\n", |
|
|
1001 |
" kernel,\n", |
|
|
1002 |
" assume_normalized_kernel=assume_normalized_kernel,\n", |
|
|
1003 |
" )\n", |
|
|
1004 |
"\n", |
|
|
1005 |
" if rescale_class_labels:\n", |
|
|
1006 |
" nplus = np.count_nonzero(np.array(Y) == 1)\n", |
|
|
1007 |
" nminus = len(Y) - nplus\n", |
|
|
1008 |
" _Y = np.array([y / nplus if y == 1 else y / nminus for y in Y])\n", |
|
|
1009 |
" else:\n", |
|
|
1010 |
" _Y = np.array(Y)\n", |
|
|
1011 |
"\n", |
|
|
1012 |
" T = np.outer(_Y, _Y)\n", |
|
|
1013 |
" inner_product = np.sum(K * T)\n", |
|
|
1014 |
" norm = np.sqrt(np.sum(K * K) * np.sum(T * T))\n", |
|
|
1015 |
" inner_product = inner_product / norm\n", |
|
|
1016 |
"\n", |
|
|
1017 |
" return inner_product\n", |
|
|
1018 |
"\n", |
|
|
1019 |
"\n", |
|
|
1020 |
"params = init_params\n", |
|
|
1021 |
"opt = qml.GradientDescentOptimizer(0.2)\n", |
|
|
1022 |
"\n", |
|
|
1023 |
"for i in range(500):\n", |
|
|
1024 |
" # Choose subset of datapoints to compute the KTA on.\n", |
|
|
1025 |
" subset = np.random.choice(list(range(len(X))), 4)\n", |
|
|
1026 |
" # Define the cost function for optimization\n", |
|
|
1027 |
" cost = lambda _params: -target_alignment(\n", |
|
|
1028 |
" X[subset],\n", |
|
|
1029 |
" Y[subset],\n", |
|
|
1030 |
" lambda x1, x2: kernel(x1, x2, _params),\n", |
|
|
1031 |
" assume_normalized_kernel=True,\n", |
|
|
1032 |
" )\n", |
|
|
1033 |
" # Optimization step\n", |
|
|
1034 |
" params = opt.step(cost, params)\n", |
|
|
1035 |
"\n", |
|
|
1036 |
" # Report the alignment on the full dataset every 50 steps.\n", |
|
|
1037 |
" if (i + 1) % 50 == 0:\n", |
|
|
1038 |
" current_alignment = target_alignment(\n", |
|
|
1039 |
" X,\n", |
|
|
1040 |
" Y,\n", |
|
|
1041 |
" lambda x1, x2: kernel(x1, x2, params),\n", |
|
|
1042 |
" assume_normalized_kernel=True,\n", |
|
|
1043 |
" )\n", |
|
|
1044 |
" print(f\"Step {i+1} - Alignment = {current_alignment:.3f}\")" |
|
|
1045 |
] |
|
|
1046 |
}, |
|
|
1047 |
{ |
|
|
1048 |
"cell_type": "markdown", |
|
|
1049 |
"metadata": { |
|
|
1050 |
"id": "lhbr4YTr-1Lz" |
|
|
1051 |
}, |
|
|
1052 |
"source": [ |
|
|
1053 |
"We want to assess the impact of training the parameters of the quantum\n", |
|
|
1054 |
"kernel. Thus, let\\'s build a second support vector classifier with the\n", |
|
|
1055 |
"trained kernel:\n" |
|
|
1056 |
] |
|
|
1057 |
}, |
|
|
1058 |
{ |
|
|
1059 |
"cell_type": "code", |
|
|
1060 |
"execution_count": null, |
|
|
1061 |
"metadata": { |
|
|
1062 |
"id": "vUg8wNDJ-1Lz" |
|
|
1063 |
}, |
|
|
1064 |
"outputs": [], |
|
|
1065 |
"source": [ |
|
|
1066 |
"# First create a kernel with the trained parameter baked into it.\n", |
|
|
1067 |
"trained_kernel = lambda x1, x2: kernel(x1, x2, params)\n", |
|
|
1068 |
"\n", |
|
|
1069 |
"# Second create a kernel matrix function using the trained kernel.\n", |
|
|
1070 |
"trained_kernel_matrix = lambda X1, X2: qml.kernels.kernel_matrix(X1, X2, trained_kernel)\n", |
|
|
1071 |
"\n", |
|
|
1072 |
"# Note that SVC expects the kernel argument to be a kernel matrix function.\n", |
|
|
1073 |
"svm_trained = SVC(kernel=trained_kernel_matrix).fit(X, Y)" |
|
|
1074 |
] |
|
|
1075 |
}, |
|
|
1076 |
{ |
|
|
1077 |
"cell_type": "markdown", |
|
|
1078 |
"metadata": { |
|
|
1079 |
"id": "LgE9Tcmn-1Lz" |
|
|
1080 |
}, |
|
|
1081 |
"source": [ |
|
|
1082 |
"We expect to see an accuracy improvement vs. the SVM with random\n", |
|
|
1083 |
"parameters:\n" |
|
|
1084 |
] |
|
|
1085 |
}, |
|
|
1086 |
{ |
|
|
1087 |
"cell_type": "code", |
|
|
1088 |
"execution_count": null, |
|
|
1089 |
"metadata": { |
|
|
1090 |
"id": "SGUIEF1X-1Lz" |
|
|
1091 |
}, |
|
|
1092 |
"outputs": [], |
|
|
1093 |
"source": [ |
|
|
1094 |
"accuracy_trained = accuracy(svm_trained, X, Y)\n", |
|
|
1095 |
"print(f\"The accuracy of a kernel with trained parameters is {accuracy_trained:.3f}\")" |
|
|
1096 |
] |
|
|
1097 |
}, |
|
|
1098 |
{ |
|
|
1099 |
"cell_type": "markdown", |
|
|
1100 |
"metadata": { |
|
|
1101 |
"id": "N5tAagq1-1Lz" |
|
|
1102 |
}, |
|
|
1103 |
"source": [ |
|
|
1104 |
"We have now achieved perfect classification! 🎆\n", |
|
|
1105 |
"\n", |
|
|
1106 |
"Following on the results that SVM\\'s have proven good generalisation\n", |
|
|
1107 |
"behavior, it will be interesting to inspect the decision boundaries of\n", |
|
|
1108 |
"our classifier:\n" |
|
|
1109 |
] |
|
|
1110 |
}, |
|
|
1111 |
{ |
|
|
1112 |
"cell_type": "code", |
|
|
1113 |
"execution_count": null, |
|
|
1114 |
"metadata": { |
|
|
1115 |
"id": "CHXRBR7p-1Lz" |
|
|
1116 |
}, |
|
|
1117 |
"outputs": [], |
|
|
1118 |
"source": [ |
|
|
1119 |
"trained_plot_data = plot_decision_boundaries(svm_trained, plt.gca())" |
|
|
1120 |
] |
|
|
1121 |
}, |
|
|
1122 |
{ |
|
|
1123 |
"cell_type": "markdown", |
|
|
1124 |
"metadata": { |
|
|
1125 |
"id": "71P66YVn-1Lz" |
|
|
1126 |
}, |
|
|
1127 |
"source": [ |
|
|
1128 |
"Indeed, we see that now not only every data instance falls within the\n", |
|
|
1129 |
"correct class, but also that there are no strong artifacts that would\n", |
|
|
1130 |
"make us distrust the model. In this sense, our approach benefits from\n", |
|
|
1131 |
"both: on one hand it can adjust itself to the dataset, and on the other\n", |
|
|
1132 |
"hand is not expected to suffer from bad generalisation.\n", |
|
|
1133 |
"\n", |
|
|
1134 |
"References\n", |
|
|
1135 |
"==========\n", |
|
|
1136 |
"\n", |
|
|
1137 |
"About the authors\n", |
|
|
1138 |
"=================\n" |
|
|
1139 |
] |
|
|
1140 |
}, |
|
|
1141 |
{ |
|
|
1142 |
"cell_type": "code", |
|
|
1143 |
"source": [ |
|
|
1144 |
"seconds = time.time()\n", |
|
|
1145 |
"print(\"Time in seconds since end of run:\", seconds)\n", |
|
|
1146 |
"local_time = time.ctime(seconds)\n", |
|
|
1147 |
"print(local_time)" |
|
|
1148 |
], |
|
|
1149 |
"metadata": { |
|
|
1150 |
"id": "e8dvgrE6Ktzf" |
|
|
1151 |
}, |
|
|
1152 |
"execution_count": null, |
|
|
1153 |
"outputs": [] |
|
|
1154 |
} |
|
|
1155 |
], |
|
|
1156 |
"metadata": { |
|
|
1157 |
"kernelspec": { |
|
|
1158 |
"display_name": "Python 3", |
|
|
1159 |
"name": "python3" |
|
|
1160 |
}, |
|
|
1161 |
"language_info": { |
|
|
1162 |
"codemirror_mode": { |
|
|
1163 |
"name": "ipython", |
|
|
1164 |
"version": 3 |
|
|
1165 |
}, |
|
|
1166 |
"file_extension": ".py", |
|
|
1167 |
"mimetype": "text/x-python", |
|
|
1168 |
"name": "python", |
|
|
1169 |
"nbconvert_exporter": "python", |
|
|
1170 |
"pygments_lexer": "ipython3", |
|
|
1171 |
"version": "3.9.17" |
|
|
1172 |
}, |
|
|
1173 |
"colab": { |
|
|
1174 |
"provenance": [], |
|
|
1175 |
"machine_shape": "hm" |
|
|
1176 |
} |
|
|
1177 |
}, |
|
|
1178 |
"nbformat": 4, |
|
|
1179 |
"nbformat_minor": 0 |
|
|
1180 |
} |