├── LICENSE.md
├── Notebooks
├── CIFAR_Hybrid_QNN.ipynb
├── CIFAR_Hybrid_QNN_1_with_accuracy.ipynb
├── CIFAR_Hybrid_QNN_2_comparing_optimizers_Adam,_SGD,_RMSprop.ipynb
├── CIFAR_Hybrid_QNN_3_hyperparameter_tuning.ipynb
├── CIFAR_Hybrid_QNN_Checkpoint_3_comparing_optimizers_Adam,_SGD,_RMSprop.ipynb
├── CIFAR_Hybrid_QNN_till_the_training_convergence.ipynb
├── CIFAR_QNN.ipynb
├── CIFAR_QNN2.ipynb
├── CPU_Changing_QCNN_layers.ipynb
├── Changing_QCNN_layers.ipynb
├── Checkpoint2.ipynb
├── GPU_Changing_QCNN_layers.ipynb
├── Hybrid_MNIST_ZZ.ipynb
├── QCNN_using_Validation_set.ipynb
├── Using_validation.ipynb
├── Using_validation_ex1.ipynb
├── Using_validation_loss.ipynb
├── Using_validation_loss_3.ipynb
├── Using_validation_loss_4.ipynb
└── Using_validation_loss_5.ipynb
├── README.md
└── paper.md.zip
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Rita Abani
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Notebooks/CIFAR_QNN.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "CIFAR QNN.ipynb",
7 | "provenance": [],
8 | "authorship_tag": "ABX9TyNiD9H7hVIgb9AnF1ulvz94",
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | },
15 | "language_info": {
16 | "name": "python"
17 | },
18 | "widgets": {
19 | "application/vnd.jupyter.widget-state+json": {
20 | "9942406645bd4fbf9c7bfa3d79a6abd5": {
21 | "model_module": "@jupyter-widgets/controls",
22 | "model_name": "HBoxModel",
23 | "state": {
24 | "_view_name": "HBoxView",
25 | "_dom_classes": [],
26 | "_model_name": "HBoxModel",
27 | "_view_module": "@jupyter-widgets/controls",
28 | "_model_module_version": "1.5.0",
29 | "_view_count": null,
30 | "_view_module_version": "1.5.0",
31 | "box_style": "",
32 | "layout": "IPY_MODEL_cfbc065d109148b588d47238166c63c8",
33 | "_model_module": "@jupyter-widgets/controls",
34 | "children": [
35 | "IPY_MODEL_e91c1de864c846bdbd79d88aba3216d4",
36 | "IPY_MODEL_5b108a6c97ef4baebb8d0d26436ffca6"
37 | ]
38 | }
39 | },
40 | "cfbc065d109148b588d47238166c63c8": {
41 | "model_module": "@jupyter-widgets/base",
42 | "model_name": "LayoutModel",
43 | "state": {
44 | "_view_name": "LayoutView",
45 | "grid_template_rows": null,
46 | "right": null,
47 | "justify_content": null,
48 | "_view_module": "@jupyter-widgets/base",
49 | "overflow": null,
50 | "_model_module_version": "1.2.0",
51 | "_view_count": null,
52 | "flex_flow": null,
53 | "width": null,
54 | "min_width": null,
55 | "border": null,
56 | "align_items": null,
57 | "bottom": null,
58 | "_model_module": "@jupyter-widgets/base",
59 | "top": null,
60 | "grid_column": null,
61 | "overflow_y": null,
62 | "overflow_x": null,
63 | "grid_auto_flow": null,
64 | "grid_area": null,
65 | "grid_template_columns": null,
66 | "flex": null,
67 | "_model_name": "LayoutModel",
68 | "justify_items": null,
69 | "grid_row": null,
70 | "max_height": null,
71 | "align_content": null,
72 | "visibility": null,
73 | "align_self": null,
74 | "height": null,
75 | "min_height": null,
76 | "padding": null,
77 | "grid_auto_rows": null,
78 | "grid_gap": null,
79 | "max_width": null,
80 | "order": null,
81 | "_view_module_version": "1.2.0",
82 | "grid_template_areas": null,
83 | "object_position": null,
84 | "object_fit": null,
85 | "grid_auto_columns": null,
86 | "margin": null,
87 | "display": null,
88 | "left": null
89 | }
90 | },
91 | "e91c1de864c846bdbd79d88aba3216d4": {
92 | "model_module": "@jupyter-widgets/controls",
93 | "model_name": "FloatProgressModel",
94 | "state": {
95 | "_view_name": "ProgressView",
96 | "style": "IPY_MODEL_ccf7167b19cb4321bebc78eb23522af6",
97 | "_dom_classes": [],
98 | "description": "",
99 | "_model_name": "FloatProgressModel",
100 | "bar_style": "success",
101 | "max": 170498071,
102 | "_view_module": "@jupyter-widgets/controls",
103 | "_model_module_version": "1.5.0",
104 | "value": 170498071,
105 | "_view_count": null,
106 | "_view_module_version": "1.5.0",
107 | "orientation": "horizontal",
108 | "min": 0,
109 | "description_tooltip": null,
110 | "_model_module": "@jupyter-widgets/controls",
111 | "layout": "IPY_MODEL_a84646e520e64288a5ac88c051f7ea41"
112 | }
113 | },
114 | "5b108a6c97ef4baebb8d0d26436ffca6": {
115 | "model_module": "@jupyter-widgets/controls",
116 | "model_name": "HTMLModel",
117 | "state": {
118 | "_view_name": "HTMLView",
119 | "style": "IPY_MODEL_e444098210404cae8b961ff0970fb367",
120 | "_dom_classes": [],
121 | "description": "",
122 | "_model_name": "HTMLModel",
123 | "placeholder": "",
124 | "_view_module": "@jupyter-widgets/controls",
125 | "_model_module_version": "1.5.0",
126 | "value": " 170499072/? [00:18<00:00, 9314699.72it/s]",
127 | "_view_count": null,
128 | "_view_module_version": "1.5.0",
129 | "description_tooltip": null,
130 | "_model_module": "@jupyter-widgets/controls",
131 | "layout": "IPY_MODEL_48015e9c118e44b9a3780f60e2eef6f5"
132 | }
133 | },
134 | "ccf7167b19cb4321bebc78eb23522af6": {
135 | "model_module": "@jupyter-widgets/controls",
136 | "model_name": "ProgressStyleModel",
137 | "state": {
138 | "_view_name": "StyleView",
139 | "_model_name": "ProgressStyleModel",
140 | "description_width": "initial",
141 | "_view_module": "@jupyter-widgets/base",
142 | "_model_module_version": "1.5.0",
143 | "_view_count": null,
144 | "_view_module_version": "1.2.0",
145 | "bar_color": null,
146 | "_model_module": "@jupyter-widgets/controls"
147 | }
148 | },
149 | "a84646e520e64288a5ac88c051f7ea41": {
150 | "model_module": "@jupyter-widgets/base",
151 | "model_name": "LayoutModel",
152 | "state": {
153 | "_view_name": "LayoutView",
154 | "grid_template_rows": null,
155 | "right": null,
156 | "justify_content": null,
157 | "_view_module": "@jupyter-widgets/base",
158 | "overflow": null,
159 | "_model_module_version": "1.2.0",
160 | "_view_count": null,
161 | "flex_flow": null,
162 | "width": null,
163 | "min_width": null,
164 | "border": null,
165 | "align_items": null,
166 | "bottom": null,
167 | "_model_module": "@jupyter-widgets/base",
168 | "top": null,
169 | "grid_column": null,
170 | "overflow_y": null,
171 | "overflow_x": null,
172 | "grid_auto_flow": null,
173 | "grid_area": null,
174 | "grid_template_columns": null,
175 | "flex": null,
176 | "_model_name": "LayoutModel",
177 | "justify_items": null,
178 | "grid_row": null,
179 | "max_height": null,
180 | "align_content": null,
181 | "visibility": null,
182 | "align_self": null,
183 | "height": null,
184 | "min_height": null,
185 | "padding": null,
186 | "grid_auto_rows": null,
187 | "grid_gap": null,
188 | "max_width": null,
189 | "order": null,
190 | "_view_module_version": "1.2.0",
191 | "grid_template_areas": null,
192 | "object_position": null,
193 | "object_fit": null,
194 | "grid_auto_columns": null,
195 | "margin": null,
196 | "display": null,
197 | "left": null
198 | }
199 | },
200 | "e444098210404cae8b961ff0970fb367": {
201 | "model_module": "@jupyter-widgets/controls",
202 | "model_name": "DescriptionStyleModel",
203 | "state": {
204 | "_view_name": "StyleView",
205 | "_model_name": "DescriptionStyleModel",
206 | "description_width": "",
207 | "_view_module": "@jupyter-widgets/base",
208 | "_model_module_version": "1.5.0",
209 | "_view_count": null,
210 | "_view_module_version": "1.2.0",
211 | "_model_module": "@jupyter-widgets/controls"
212 | }
213 | },
214 | "48015e9c118e44b9a3780f60e2eef6f5": {
215 | "model_module": "@jupyter-widgets/base",
216 | "model_name": "LayoutModel",
217 | "state": {
218 | "_view_name": "LayoutView",
219 | "grid_template_rows": null,
220 | "right": null,
221 | "justify_content": null,
222 | "_view_module": "@jupyter-widgets/base",
223 | "overflow": null,
224 | "_model_module_version": "1.2.0",
225 | "_view_count": null,
226 | "flex_flow": null,
227 | "width": null,
228 | "min_width": null,
229 | "border": null,
230 | "align_items": null,
231 | "bottom": null,
232 | "_model_module": "@jupyter-widgets/base",
233 | "top": null,
234 | "grid_column": null,
235 | "overflow_y": null,
236 | "overflow_x": null,
237 | "grid_auto_flow": null,
238 | "grid_area": null,
239 | "grid_template_columns": null,
240 | "flex": null,
241 | "_model_name": "LayoutModel",
242 | "justify_items": null,
243 | "grid_row": null,
244 | "max_height": null,
245 | "align_content": null,
246 | "visibility": null,
247 | "align_self": null,
248 | "height": null,
249 | "min_height": null,
250 | "padding": null,
251 | "grid_auto_rows": null,
252 | "grid_gap": null,
253 | "max_width": null,
254 | "order": null,
255 | "_view_module_version": "1.2.0",
256 | "grid_template_areas": null,
257 | "object_position": null,
258 | "object_fit": null,
259 | "grid_auto_columns": null,
260 | "margin": null,
261 | "display": null,
262 | "left": null
263 | }
264 | }
265 | }
266 | }
267 | },
268 | "cells": [
269 | {
270 | "cell_type": "markdown",
271 | "metadata": {
272 | "id": "view-in-github",
273 | "colab_type": "text"
274 | },
275 | "source": [
276 | "
"
277 | ]
278 | },
279 | {
280 | "cell_type": "code",
281 | "metadata": {
282 | "colab": {
283 | "base_uri": "https://localhost:8080/"
284 | },
285 | "id": "mlYRr1NTuUCq",
286 | "outputId": "0bfcceb7-4de2-4264-f148-cf4050df60ec"
287 | },
288 | "source": [
289 | "!pip install qiskit"
290 | ],
291 | "execution_count": 2,
292 | "outputs": [
293 | {
294 | "output_type": "stream",
295 | "text": [
296 | "Collecting qiskit\n",
297 | " Downloading https://files.pythonhosted.org/packages/6f/61/cb7506e17a2566dc8a31a3e1924d91ac0bdd8ff07c71ec698c06647b6306/qiskit-0.26.2.tar.gz\n",
298 | "Collecting qiskit-terra==0.17.4\n",
299 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/b3/0c/3c7a8dd451dae0907263e9de9e3e34909e15e18c88a589b44581972c8511/qiskit_terra-0.17.4-cp37-cp37m-manylinux2010_x86_64.whl (6.0MB)\n",
300 | "\u001b[K |████████████████████████████████| 6.0MB 5.1MB/s \n",
301 | "\u001b[?25hCollecting qiskit-aer==0.8.2\n",
302 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/c2/d2/6ff15c370b5465b32529b528bf3f4ce1e01f74498be16203aa1c04b67022/qiskit_aer-0.8.2-cp37-cp37m-manylinux2010_x86_64.whl (18.0MB)\n",
303 | "\u001b[K |████████████████████████████████| 18.0MB 154kB/s \n",
304 | "\u001b[?25hCollecting qiskit-ibmq-provider==0.13.1\n",
305 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/be/99/74bbb901f88603a7d850d4889abc06d81ba702e4227151f4a5b66f2631fe/qiskit_ibmq_provider-0.13.1-py3-none-any.whl (228kB)\n",
306 | "\u001b[K |████████████████████████████████| 235kB 50.7MB/s \n",
307 | "\u001b[?25hCollecting qiskit-ignis==0.6.0\n",
308 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/54/be/a13c828e457e09d979667a61bddbd8c7246aafa94e2501b6a9154429cbea/qiskit_ignis-0.6.0-py3-none-any.whl (207kB)\n",
309 | "\u001b[K |████████████████████████████████| 215kB 51.0MB/s \n",
310 | "\u001b[?25hCollecting qiskit-aqua==0.9.1\n",
311 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/88/79/392c57b978decbb24b902344b536af52c40a751aed0ebbaefa8bc2964cb5/qiskit_aqua-0.9.1-py3-none-any.whl (2.1MB)\n",
312 | "\u001b[K |████████████████████████████████| 2.1MB 33.6MB/s \n",
313 | "\u001b[?25hRequirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (2.6.0)\n",
314 | "Collecting retworkx>=0.8.0\n",
315 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/9e/cd/70d436f170aa1ead2ac9e4c19c8838633355d48b530f09455eab0af2f98e/retworkx-0.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.4MB)\n",
316 | "\u001b[K |████████████████████████████████| 1.5MB 36.7MB/s \n",
317 | "\u001b[?25hRequirement already satisfied: psutil>=5 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (5.4.8)\n",
318 | "Requirement already satisfied: dill>=0.3 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (0.3.3)\n",
319 | "Requirement already satisfied: python-dateutil>=2.8.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (2.8.1)\n",
320 | "Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (1.19.5)\n",
321 | "Requirement already satisfied: sympy>=1.3 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (1.7.1)\n",
322 | "Collecting fastjsonschema>=2.10\n",
323 | " Downloading https://files.pythonhosted.org/packages/d1/fb/ea090e917b18320f79be31d754bbe496b715175e865603cfce1eaed2e774/fastjsonschema-2.15.1-py3-none-any.whl\n",
324 | "Collecting python-constraint>=1.4\n",
325 | " Downloading https://files.pythonhosted.org/packages/37/8b/5f1bc2734ca611943e1d6733ee244238679f6410a10cd45ede55a61a8402/python-constraint-1.4.0.tar.bz2\n",
326 | "Requirement already satisfied: scipy>=1.4 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (1.4.1)\n",
327 | "Collecting ply>=3.10\n",
328 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl (49kB)\n",
329 | "\u001b[K |████████████████████████████████| 51kB 5.8MB/s \n",
330 | "\u001b[?25hCollecting pybind11>=2.6\n",
331 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/8d/43/7339dbabbc2793718d59703aace4166f53c29ee1c202f6ff5bf8a26c4d91/pybind11-2.6.2-py2.py3-none-any.whl (191kB)\n",
332 | "\u001b[K |████████████████████████████████| 194kB 52.4MB/s \n",
333 | "\u001b[?25hRequirement already satisfied: urllib3>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.13.1->qiskit) (1.24.3)\n",
334 | "Collecting requests-ntlm>=1.1.0\n",
335 | " Downloading https://files.pythonhosted.org/packages/03/4b/8b9a1afde8072c4d5710d9fa91433d504325821b038e00237dc8d6d833dc/requests_ntlm-1.1.0-py2.py3-none-any.whl\n",
336 | "Requirement already satisfied: requests>=2.19 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.13.1->qiskit) (2.23.0)\n",
337 | "Requirement already satisfied: nest-asyncio!=1.1.0,>=1.0.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.13.1->qiskit) (1.5.1)\n",
338 | "Collecting websockets>=8\n",
339 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/84/64/78c2b3fe37730b30dca3c93d1f7f4a4286767f86e7c04cf3571b39bc2fb7/websockets-9.1-cp37-cp37m-manylinux2010_x86_64.whl (103kB)\n",
340 | "\u001b[K |████████████████████████████████| 112kB 44.4MB/s \n",
341 | "\u001b[?25hRequirement already satisfied: setuptools>=40.1.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-ignis==0.6.0->qiskit) (57.0.0)\n",
342 | "Requirement already satisfied: scikit-learn<=0.24.1,>=0.20.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.9.1->qiskit) (0.22.2.post1)\n",
343 | "Collecting docplex<=2.20.204; sys_platform != \"darwin\"\n",
344 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/87/99/6f7c219b39fd58c84688ad0713eb932bfcf6be81fc74519e43ea9c915b56/docplex-2.20.204.tar.gz (611kB)\n",
345 | "\u001b[K |████████████████████████████████| 614kB 27.2MB/s \n",
346 | "\u001b[?25hCollecting quandl<=3.6.0\n",
347 | " Downloading https://files.pythonhosted.org/packages/c2/58/9f0e69d836045e3865d263e9ed49f42b23a58526fdabb30f74c430baee3f/Quandl-3.6.0-py2.py3-none-any.whl\n",
348 | "Collecting yfinance<=0.1.55\n",
349 | " Downloading https://files.pythonhosted.org/packages/7a/e8/b9d7104d3a4bf39924799067592d9e59119fcfc900a425a12e80a3123ec8/yfinance-0.1.55.tar.gz\n",
350 | "Requirement already satisfied: pandas<=1.2.3 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.9.1->qiskit) (1.1.5)\n",
351 | "Collecting dlx<=1.0.4\n",
352 | " Downloading https://files.pythonhosted.org/packages/54/c0/b8fb5bb727e983b6f5251433ef941b48f38c65bb0bd6ec509e9185bcd406/dlx-1.0.4.tar.gz\n",
353 | "Requirement already satisfied: h5py<=3.1.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.9.1->qiskit) (3.1.0)\n",
354 | "Requirement already satisfied: fastdtw<=0.3.4 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.9.1->qiskit) (0.3.4)\n",
355 | "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.7/dist-packages (from python-dateutil>=2.8.0->qiskit-terra==0.17.4->qiskit) (1.15.0)\n",
356 | "Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy>=1.3->qiskit-terra==0.17.4->qiskit) (1.2.1)\n",
357 | "Collecting cryptography>=1.3\n",
358 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/b2/26/7af637e6a7e87258b963f1731c5982fb31cd507f0d90d91836e446955d02/cryptography-3.4.7-cp36-abi3-manylinux2014_x86_64.whl (3.2MB)\n",
359 | "\u001b[K |████████████████████████████████| 3.2MB 37.1MB/s \n",
360 | "\u001b[?25hCollecting ntlm-auth>=1.0.2\n",
361 | " Downloading https://files.pythonhosted.org/packages/ff/84/97c550164b54942b0e908c31ef09d9469f3ba4cd7332a671e2125732f63b/ntlm_auth-1.5.0-py2.py3-none-any.whl\n",
362 | "Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.13.1->qiskit) (3.0.4)\n",
363 | "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.13.1->qiskit) (2020.12.5)\n",
364 | "Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.13.1->qiskit) (2.10)\n",
365 | "Requirement already satisfied: joblib>=0.11 in /usr/local/lib/python3.7/dist-packages (from scikit-learn<=0.24.1,>=0.20.0->qiskit-aqua==0.9.1->qiskit) (1.0.1)\n",
366 | "Collecting inflection>=0.3.1\n",
367 | " Downloading https://files.pythonhosted.org/packages/59/91/aa6bde563e0085a02a435aa99b49ef75b0a4b062635e606dab23ce18d720/inflection-0.5.1-py2.py3-none-any.whl\n",
368 | "Requirement already satisfied: more-itertools in /usr/local/lib/python3.7/dist-packages (from quandl<=3.6.0->qiskit-aqua==0.9.1->qiskit) (8.7.0)\n",
369 | "Requirement already satisfied: multitasking>=0.0.7 in /usr/local/lib/python3.7/dist-packages (from yfinance<=0.1.55->qiskit-aqua==0.9.1->qiskit) (0.0.9)\n",
370 | "Collecting lxml>=4.5.1\n",
371 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/30/c0/d0526314971fc661b083ab135747dc68446a3022686da8c16d25fcf6ef07/lxml-4.6.3-cp37-cp37m-manylinux2014_x86_64.whl (6.3MB)\n",
372 | "\u001b[K |████████████████████████████████| 6.3MB 34.3MB/s \n",
373 | "\u001b[?25hRequirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.7/dist-packages (from pandas<=1.2.3->qiskit-aqua==0.9.1->qiskit) (2018.9)\n",
374 | "Requirement already satisfied: cached-property; python_version < \"3.8\" in /usr/local/lib/python3.7/dist-packages (from h5py<=3.1.0->qiskit-aqua==0.9.1->qiskit) (1.5.2)\n",
375 | "Requirement already satisfied: cffi>=1.12 in /usr/local/lib/python3.7/dist-packages (from cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.13.1->qiskit) (1.14.5)\n",
376 | "Requirement already satisfied: pycparser in /usr/local/lib/python3.7/dist-packages (from cffi>=1.12->cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.13.1->qiskit) (2.20)\n",
377 | "Building wheels for collected packages: qiskit, python-constraint, docplex, yfinance, dlx\n",
378 | " Building wheel for qiskit (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
379 | " Created wheel for qiskit: filename=qiskit-0.26.2-cp37-none-any.whl size=10506 sha256=12f51dc2d377a6044ff38d97d797ca61b1047760ecd2ce0e6114cc12c4fe2642\n",
380 | " Stored in directory: /root/.cache/pip/wheels/89/89/34/524839952d5a58a7be9789e580bfc1ca883bf6579152444568\n",
381 | " Building wheel for python-constraint (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
382 | " Created wheel for python-constraint: filename=python_constraint-1.4.0-py2.py3-none-any.whl size=24079 sha256=ae1a2e58e7f4c70f00b38333cfcc79fd765a5e41913e32f973e1dffeef67c586\n",
383 | " Stored in directory: /root/.cache/pip/wheels/34/31/15/7b070b25d0a549d20ce2e9fe6d727471c2c61ef904720fd40c\n",
384 | " Building wheel for docplex (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
385 | " Created wheel for docplex: filename=docplex-2.20.204-cp37-none-any.whl size=675396 sha256=1c65cc23e3254d87ce484b7dba5a34470bceb90614d4ff7084a3ff2465991e18\n",
386 | " Stored in directory: /root/.cache/pip/wheels/ae/2c/e2/a099ebb6fda8adeba9c5fc2e25659d195ad2f5c6cc5fb75fd4\n",
387 | " Building wheel for yfinance (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
388 | " Created wheel for yfinance: filename=yfinance-0.1.55-py2.py3-none-any.whl size=22627 sha256=35dc3ccee8d98cabcc6909a266effae76b1ad814b0836a2d8a13700998708541\n",
389 | " Stored in directory: /root/.cache/pip/wheels/04/98/cc/2702a4242d60bdc14f48b4557c427ded1fe92aedf257d4565c\n",
390 | " Building wheel for dlx (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
391 | " Created wheel for dlx: filename=dlx-1.0.4-cp37-none-any.whl size=5720 sha256=8ef543ca246bfac210870c429a104410bd89c89d602f678be6c41f2473061d1e\n",
392 | " Stored in directory: /root/.cache/pip/wheels/bb/ba/15/fdd0deb104df3254912998150ba9245668db06b00af5912d1a\n",
393 | "Successfully built qiskit python-constraint docplex yfinance dlx\n",
394 | "\u001b[31mERROR: qiskit-aqua 0.9.1 has requirement retworkx<=0.8.0,>=0.7.0, but you'll have retworkx 0.9.0 which is incompatible.\u001b[0m\n",
395 | "Installing collected packages: retworkx, fastjsonschema, python-constraint, ply, qiskit-terra, pybind11, qiskit-aer, cryptography, ntlm-auth, requests-ntlm, websockets, qiskit-ibmq-provider, qiskit-ignis, docplex, inflection, quandl, lxml, yfinance, dlx, qiskit-aqua, qiskit\n",
396 | " Found existing installation: lxml 4.2.6\n",
397 | " Uninstalling lxml-4.2.6:\n",
398 | " Successfully uninstalled lxml-4.2.6\n",
399 | "Successfully installed cryptography-3.4.7 dlx-1.0.4 docplex-2.20.204 fastjsonschema-2.15.1 inflection-0.5.1 lxml-4.6.3 ntlm-auth-1.5.0 ply-3.11 pybind11-2.6.2 python-constraint-1.4.0 qiskit-0.26.2 qiskit-aer-0.8.2 qiskit-aqua-0.9.1 qiskit-ibmq-provider-0.13.1 qiskit-ignis-0.6.0 qiskit-terra-0.17.4 quandl-3.6.0 requests-ntlm-1.1.0 retworkx-0.9.0 websockets-9.1 yfinance-0.1.55\n"
400 | ],
401 | "name": "stdout"
402 | }
403 | ]
404 | },
405 | {
406 | "cell_type": "code",
407 | "metadata": {
408 | "id": "VYBMeYOGuuN9"
409 | },
410 | "source": [
411 | "import numpy as np\n",
412 | "import matplotlib.pyplot as plt\n",
413 | "\n",
414 | "import torch\n",
415 | "from torch.autograd import Function\n",
416 | "from torchvision import datasets, transforms\n",
417 | "import torch.optim as optim\n",
418 | "import torch.nn as nn\n",
419 | "import torch.nn.functional as F\n",
420 | "\n",
421 | "import qiskit\n",
422 | "from qiskit import transpile, assemble\n",
423 | "from qiskit.visualization import *"
424 | ],
425 | "execution_count": 3,
426 | "outputs": []
427 | },
428 | {
429 | "cell_type": "code",
430 | "metadata": {
431 | "id": "zNivTot8fdU5"
432 | },
433 | "source": [
434 | "def to_numbers(tensor_list):\n",
435 | " num_list = []\n",
436 | " for tensor in tensor_list:\n",
437 | " num_list += [tensor.item()]\n",
438 | " return num_list"
439 | ],
440 | "execution_count": 4,
441 | "outputs": []
442 | },
443 | {
444 | "cell_type": "code",
445 | "metadata": {
446 | "id": "nIxXTsQp3zN_"
447 | },
448 | "source": [
449 | "class QiskitCircuit():\n",
450 | " \n",
451 | " # Specify initial parameters and the quantum circuit\n",
452 | " \n",
453 | " def __init__(self,shots):\n",
454 | " self.theta = Parameter('Theta')\n",
455 | " self.shots = shots\n",
456 | " \n",
457 | " def create_circuit():\n",
458 | " qr = QuantumRegister(1,'q')\n",
459 | " cr = ClassicalRegister(1,'c')\n",
460 | " ckt = QuantumCircuit(qr,cr)\n",
461 | " ckt.h(qr[0])\n",
462 | " ckt.barrier()\n",
463 | " ckt.ry(self.theta,qr[0])\n",
464 | " ckt.barrier()\n",
465 | " ckt.measure(qr,cr)\n",
466 | " return ckt\n",
467 | " \n",
468 | " self.circuit = create_circuit()\n",
469 | " \n",
470 | " def N_qubit_expectation_Z(self,counts, shots, nr_qubits):\n",
471 | " expects = np.zeros(nr_qubits)\n",
472 | " for key in counts.keys():\n",
473 | " perc = counts[key]/shots\n",
474 | " check = np.array([(float(key[i])-1/2)*2*perc for i in range(nr_qubits)])\n",
475 | " expects += check \n",
476 | " return expects \n",
477 | " \n",
478 | " def bind(self, parameters):\n",
479 | " [self.theta] = to_numbers(parameters)\n",
480 | " self.circuit.data[2][0]._params = to_numbers(parameters)\n",
481 | " \n",
482 | " def run(self, i):\n",
483 | " self.bind(i)\n",
484 | " backend = Aer.get_backend('qasm_simulator')\n",
485 | " job_sim = execute(self.circuit,backend,shots=self.shots)\n",
486 | " result_sim = job_sim.result()\n",
487 | " counts = result_sim.get_counts(self.circuit)\n",
488 | " return self.N_qubit_expectation_Z(counts,self.shots,1)"
489 | ],
490 | "execution_count": 5,
491 | "outputs": []
492 | },
493 | {
494 | "cell_type": "code",
495 | "metadata": {
496 | "id": "FHJQ4B-z34Yf"
497 | },
498 | "source": [
499 | "class TorchCircuit(Function): \n",
500 | "\n",
501 | " @staticmethod\n",
502 | " def forward(ctx, i):\n",
503 | " if not hasattr(ctx, 'QiskitCirc'):\n",
504 | " ctx.QiskitCirc = QiskitCircuit(shots=100)\n",
505 | " \n",
506 | " exp_value = ctx.QiskitCirc.run(i[0])\n",
507 | " \n",
508 | " result = torch.tensor([exp_value]) # store the result as a torch tensor\n",
509 | " \n",
510 | " ctx.save_for_backward(result, i)\n",
511 | " \n",
512 | " return result\n",
513 | " \n",
514 | " @staticmethod\n",
515 | " def backward(ctx, grad_output):\n",
516 | " s = np.pi/2\n",
517 | " \n",
518 | " forward_tensor, i = ctx.saved_tensors \n",
519 | " \n",
520 | " # Obtain paramaters \n",
521 | " input_numbers = to_numbers(i[0])\n",
522 | " \n",
523 | " gradient = []\n",
524 | " \n",
525 | " for k in range(len(input_numbers)):\n",
526 | " input_plus_s = input_numbers\n",
527 | " input_plus_s[k] = input_numbers[k] + s # Shift up by s\n",
528 | " \n",
529 | " exp_value_plus = ctx.QiskitCirc.run(torch.tensor(input_plus_s))[0]\n",
530 | " result_plus_s = torch.tensor([exp_value_plus])\n",
531 | " \n",
532 | " input_minus_s = input_numbers\n",
533 | " input_minus_s[k] = input_numbers[k] - s # Shift down by s\n",
534 | " \n",
535 | " exp_value_minus = ctx.QiskitCirc.run(torch.tensor(input_minus_s))[0]\n",
536 | " result_minus_s = torch.tensor([exp_value_minus])\n",
537 | "\n",
538 | " gradient_result = (result_plus_s - result_minus_s)\n",
539 | "\n",
540 | " gradient.append(gradient_result)\n",
541 | " \n",
542 | " result = torch.tensor([gradient])\n",
543 | " \n",
544 | " return result.float() * grad_output.float()"
545 | ],
546 | "execution_count": 6,
547 | "outputs": []
548 | },
549 | {
550 | "cell_type": "code",
551 | "metadata": {
552 | "colab": {
553 | "base_uri": "https://localhost:8080/",
554 | "height": 246
555 | },
556 | "id": "O0NOffGU39h7",
557 | "outputId": "f8971cec-3907-4de3-de1a-434673008b5f"
558 | },
559 | "source": [
560 | "#import torchvision\n",
561 | "#transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()]) # transform images to tensors/vectors\n",
562 | "#cifar_trainset = datasets.CIFAR10(root='./data1', train=True, download=True, transform=transform)\n",
563 | "\n",
564 | "#labels = cifar_trainset.targets # get the labels for the data\n",
565 | "#labels = labels.numpy()\n",
566 | "\n",
567 | "#idx1 = np.where(labels == 0) # filter on aeroplanes\n",
568 | "#idx2 = np.where(labels == 1) # filter on automobiles\n",
569 | "\n",
570 | "# Specify number of datapoints per class (i.e. there will be n pictures of automobiles and n pictures of aeroplanes in the training set)\n",
571 | "#n=100\n",
572 | "\n",
573 | "# concatenate the data indices\n",
574 | "#idx = np.concatenate((idx1[0][0:n],idx2[0][0:n])) \n",
575 | "\n",
576 | "# create the filtered dataset for our training set\n",
577 | "#cifar_trainset.targets = labels[idx] \n",
578 | "#cifar_trainset.data = cifar_trainset.data[idx]\n",
579 | "\n",
580 | "#train_loader = torch.utils.data.DataLoader(cifar_trainset, batch_size=1, shuffle=True)"
581 | ],
582 | "execution_count": 25,
583 | "outputs": [
584 | {
585 | "output_type": "stream",
586 | "text": [
587 | "Files already downloaded and verified\n"
588 | ],
589 | "name": "stdout"
590 | },
591 | {
592 | "output_type": "error",
593 | "ename": "AttributeError",
594 | "evalue": "ignored",
595 | "traceback": [
596 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
597 | "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
598 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mlabels\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcifar_trainset\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtargets\u001b[0m \u001b[0;31m# get the labels for the data\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mlabels\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlabels\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumpy\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 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0midx1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwhere\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlabels\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# filter on aeroplanes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
599 | "\u001b[0;31mAttributeError\u001b[0m: 'list' object has no attribute 'numpy'"
600 | ]
601 | }
602 | ]
603 | },
604 | {
605 | "cell_type": "code",
606 | "metadata": {
607 | "id": "Rpb9LrNzhVMW"
608 | },
609 | "source": [
610 | "import tensorflow\n",
611 | "import torchvision"
612 | ],
613 | "execution_count": 15,
614 | "outputs": []
615 | },
616 | {
617 | "cell_type": "code",
618 | "metadata": {
619 | "id": "MXdFx30u5PwY"
620 | },
621 | "source": [
622 | "def to_numbers(tensor_list):\n",
623 | " num_list = []\n",
624 | " for tensor in tensor_list:\n",
625 | " num_list += [tensor.item()]\n",
626 | " return num_list"
627 | ],
628 | "execution_count": 26,
629 | "outputs": []
630 | },
631 | {
632 | "cell_type": "code",
633 | "metadata": {
634 | "colab": {
635 | "base_uri": "https://localhost:8080/",
636 | "height": 99,
637 | "referenced_widgets": [
638 | "9942406645bd4fbf9c7bfa3d79a6abd5",
639 | "cfbc065d109148b588d47238166c63c8",
640 | "e91c1de864c846bdbd79d88aba3216d4",
641 | "5b108a6c97ef4baebb8d0d26436ffca6",
642 | "ccf7167b19cb4321bebc78eb23522af6",
643 | "a84646e520e64288a5ac88c051f7ea41",
644 | "e444098210404cae8b961ff0970fb367",
645 | "48015e9c118e44b9a3780f60e2eef6f5"
646 | ]
647 | },
648 | "id": "C8GWLzXk5Q-i",
649 | "outputId": "9bbcf3d0-8649-4cba-85a1-98ed2e2a6ac0"
650 | },
651 | "source": [
652 | "\n",
653 | "import torchvision\n",
654 | "transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()]) # transform images to tensors/vectors\n",
655 | "cifar_trainset = datasets.CIFAR10(root='./data1', train=True, download=True, transform=transform)\n",
656 | "\n",
657 | "labels = cifar_trainset.targets # get the labels for the data\n",
658 | "labels = np.array(labels)\n",
659 | "\n",
660 | "idx1 = np.where(labels == 0) # filter on aeroplanes\n",
661 | "idx2 = np.where(labels == 1) # filter on automobiles\n",
662 | "\n",
663 | "# Specify number of datapoints per class (i.e. there will be n pictures of automobiles and n pictures of aeroplanes in the training set)\n",
664 | "n=100\n",
665 | "\n",
666 | "# concatenate the data indices\n",
667 | "idx = np.concatenate((idx1[0][0:n],idx2[0][0:n])) \n",
668 | "\n",
669 | "# create the filtered dataset for our training set\n",
670 | "cifar_trainset.targets = labels[idx] \n",
671 | "cifar_trainset.data = cifar_trainset.data[idx]\n",
672 | "\n",
673 | "train_loader = torch.utils.data.DataLoader(cifar_trainset, batch_size=1, shuffle=True)"
674 | ],
675 | "execution_count": 8,
676 | "outputs": [
677 | {
678 | "output_type": "stream",
679 | "text": [
680 | "Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data1/cifar-10-python.tar.gz\n"
681 | ],
682 | "name": "stdout"
683 | },
684 | {
685 | "output_type": "display_data",
686 | "data": {
687 | "application/vnd.jupyter.widget-view+json": {
688 | "model_id": "9942406645bd4fbf9c7bfa3d79a6abd5",
689 | "version_minor": 0,
690 | "version_major": 2
691 | },
692 | "text/plain": [
693 | "HBox(children=(FloatProgress(value=0.0, max=170498071.0), HTML(value='')))"
694 | ]
695 | },
696 | "metadata": {
697 | "tags": []
698 | }
699 | },
700 | {
701 | "output_type": "stream",
702 | "text": [
703 | "\n",
704 | "Extracting ./data1/cifar-10-python.tar.gz to ./data1\n"
705 | ],
706 | "name": "stdout"
707 | }
708 | ]
709 | },
710 | {
711 | "cell_type": "markdown",
712 | "metadata": {
713 | "id": "9wxOOuQQDjDP"
714 | },
715 | "source": [
716 | "Now creating the hybrid neural network."
717 | ]
718 | },
719 | {
720 | "cell_type": "code",
721 | "metadata": {
722 | "id": "7Chcmm8xem-5"
723 | },
724 | "source": [
725 | "\n",
726 | "qc = TorchCircuit.apply \n",
727 | "\n",
728 | "class Net(nn.Module):\n",
729 | " def __init__(self):\n",
730 | " super(Net, self).__init__()\n",
731 | " self.conv1 = nn.Conv2d(3, 10, kernel_size=5)\n",
732 | " self.conv2 = nn.Conv2d(10, 20, kernel_size=5)\n",
733 | " self.conv2_drop = nn.Dropout2d()\n",
734 | " self.h1 = nn.Linear(500, 500)\n",
735 | " self.h2 = nn.Linear(500, 1)\n",
736 | "\n",
737 | " def forward(self,x):\n",
738 | " x = F.relu(F.max_pool2d(self.conv1(x), 2))\n",
739 | " x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))\n",
740 | " x = x.view(-1, 500)\n",
741 | " x = F.relu(self.h1(x))\n",
742 | " x = F.dropout(x, training=self.training)\n",
743 | " x = self.h2(x)\n",
744 | " x = qc(x)\n",
745 | " x = (x+1)/2 # Normalise the inputs to 1 or 0\n",
746 | " x = torch.cat((x, 1-x), -1)\n",
747 | " return x"
748 | ],
749 | "execution_count": 31,
750 | "outputs": []
751 | },
752 | {
753 | "cell_type": "code",
754 | "metadata": {
755 | "colab": {
756 | "base_uri": "https://localhost:8080/",
757 | "height": 450
758 | },
759 | "id": "41oqcpbJe2W5",
760 | "outputId": "042a47a2-bddd-4246-fa80-dd30104edec3"
761 | },
762 | "source": [
763 | "network = Net()\n",
764 | "#input = input.permute(1,0,2,3)\n",
765 | "optimizer = optim.Adam(network.parameters(), lr=0.001)\n",
766 | "\n",
767 | "epochs = 10\n",
768 | "loss_list = []\n",
769 | "for epoch in range(epochs):\n",
770 | " total_loss = []\n",
771 | " target_list = []\n",
772 | " for batch_idx, (data, target) in enumerate(train_loader):\n",
773 | " target_list.append(target.item())\n",
774 | " optimizer.zero_grad()\n",
775 | " output = network(data)\n",
776 | " loss = F.nll_loss(output, target)\n",
777 | " loss.backward()\n",
778 | " optimizer.step()\n",
779 | " total_loss.append(loss.item())\n",
780 | " loss_list.append(sum(total_loss)/len(total_loss))\n",
781 | " print(loss_list[-1])\n",
782 | "\n",
783 | "# Normalise the loss between 0 and 1\n",
784 | "for i in range(len(loss_list)):\n",
785 | " loss_list[i] += 1\n",
786 | "\n",
787 | "# Plot the loss per epoch\n",
788 | "plt.plot(loss_list)"
789 | ],
790 | "execution_count": 32,
791 | "outputs": [
792 | {
793 | "output_type": "stream",
794 | "text": [
795 | "-0.5160500000000002\n",
796 | "-0.5147499999999998\n",
797 | "-0.4957500000000001\n",
798 | "-0.5060999999999997\n",
799 | "-0.5278\n",
800 | "-0.5152499999999998\n",
801 | "-0.5463500000000002\n",
802 | "-0.6112999999999998\n",
803 | "-0.6389999999999998\n",
804 | "-0.6592499999999994\n"
805 | ],
806 | "name": "stdout"
807 | },
808 | {
809 | "output_type": "execute_result",
810 | "data": {
811 | "text/plain": [
812 | "[]"
813 | ]
814 | },
815 | "metadata": {
816 | "tags": []
817 | },
818 | "execution_count": 32
819 | },
820 | {
821 | "output_type": "display_data",
822 | "data": {
823 | "image/png": "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\n",
824 | "text/plain": [
825 | ""
826 | ]
827 | },
828 | "metadata": {
829 | "tags": [],
830 | "needs_background": "light"
831 | }
832 | }
833 | ]
834 | },
835 | {
836 | "cell_type": "code",
837 | "metadata": {
838 | "id": "Ve0YtqV2REFJ"
839 | },
840 | "source": [
841 | "\n",
842 | "import numpy as np\n",
843 | "import torch\n",
844 | "from torch.autograd import Function\n",
845 | "import torch.optim as optim\n",
846 | "import torch.nn as nn\n",
847 | "import torch.nn.functional as F\n",
848 | "import torchvision\n",
849 | "from torchvision import datasets, transforms\n",
850 | "from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister, execute\n",
851 | "from qiskit.circuit import Parameter\n",
852 | "from qiskit import Aer\n",
853 | "from tqdm import tqdm\n",
854 | "from matplotlib import pyplot as plt\n",
855 | "%matplotlib inline"
856 | ],
857 | "execution_count": 18,
858 | "outputs": []
859 | }
860 | ]
861 | }
862 |
--------------------------------------------------------------------------------
/Notebooks/Using_validation_loss.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "Using validation loss.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "authorship_tag": "ABX9TyMpLt2O9bHGcU7CHCM7h8Ef",
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | },
16 | "language_info": {
17 | "name": "python"
18 | },
19 | "widgets": {
20 | "application/vnd.jupyter.widget-state+json": {
21 | "6b21baa29bbf408d96883c52c578d25e": {
22 | "model_module": "@jupyter-widgets/controls",
23 | "model_name": "HBoxModel",
24 | "state": {
25 | "_view_name": "HBoxView",
26 | "_dom_classes": [],
27 | "_model_name": "HBoxModel",
28 | "_view_module": "@jupyter-widgets/controls",
29 | "_model_module_version": "1.5.0",
30 | "_view_count": null,
31 | "_view_module_version": "1.5.0",
32 | "box_style": "",
33 | "layout": "IPY_MODEL_c0afc2958d7f4cb6ad5fa7df3127b838",
34 | "_model_module": "@jupyter-widgets/controls",
35 | "children": [
36 | "IPY_MODEL_97126e60fd414c0ca90bcf1090f159e0",
37 | "IPY_MODEL_61bcf60fe4cc4dc7bebc1215bf6c27f7"
38 | ]
39 | }
40 | },
41 | "c0afc2958d7f4cb6ad5fa7df3127b838": {
42 | "model_module": "@jupyter-widgets/base",
43 | "model_name": "LayoutModel",
44 | "state": {
45 | "_view_name": "LayoutView",
46 | "grid_template_rows": null,
47 | "right": null,
48 | "justify_content": null,
49 | "_view_module": "@jupyter-widgets/base",
50 | "overflow": null,
51 | "_model_module_version": "1.2.0",
52 | "_view_count": null,
53 | "flex_flow": null,
54 | "width": null,
55 | "min_width": null,
56 | "border": null,
57 | "align_items": null,
58 | "bottom": null,
59 | "_model_module": "@jupyter-widgets/base",
60 | "top": null,
61 | "grid_column": null,
62 | "overflow_y": null,
63 | "overflow_x": null,
64 | "grid_auto_flow": null,
65 | "grid_area": null,
66 | "grid_template_columns": null,
67 | "flex": null,
68 | "_model_name": "LayoutModel",
69 | "justify_items": null,
70 | "grid_row": null,
71 | "max_height": null,
72 | "align_content": null,
73 | "visibility": null,
74 | "align_self": null,
75 | "height": null,
76 | "min_height": null,
77 | "padding": null,
78 | "grid_auto_rows": null,
79 | "grid_gap": null,
80 | "max_width": null,
81 | "order": null,
82 | "_view_module_version": "1.2.0",
83 | "grid_template_areas": null,
84 | "object_position": null,
85 | "object_fit": null,
86 | "grid_auto_columns": null,
87 | "margin": null,
88 | "display": null,
89 | "left": null
90 | }
91 | },
92 | "97126e60fd414c0ca90bcf1090f159e0": {
93 | "model_module": "@jupyter-widgets/controls",
94 | "model_name": "FloatProgressModel",
95 | "state": {
96 | "_view_name": "ProgressView",
97 | "style": "IPY_MODEL_2fe1f152bcf7413cae42224d18d44fd7",
98 | "_dom_classes": [],
99 | "description": "",
100 | "_model_name": "FloatProgressModel",
101 | "bar_style": "success",
102 | "max": 170498071,
103 | "_view_module": "@jupyter-widgets/controls",
104 | "_model_module_version": "1.5.0",
105 | "value": 170498071,
106 | "_view_count": null,
107 | "_view_module_version": "1.5.0",
108 | "orientation": "horizontal",
109 | "min": 0,
110 | "description_tooltip": null,
111 | "_model_module": "@jupyter-widgets/controls",
112 | "layout": "IPY_MODEL_20cfd8834a4548e993b60bce5a119264"
113 | }
114 | },
115 | "61bcf60fe4cc4dc7bebc1215bf6c27f7": {
116 | "model_module": "@jupyter-widgets/controls",
117 | "model_name": "HTMLModel",
118 | "state": {
119 | "_view_name": "HTMLView",
120 | "style": "IPY_MODEL_755a675c4f374bd0a427143b783eb6b7",
121 | "_dom_classes": [],
122 | "description": "",
123 | "_model_name": "HTMLModel",
124 | "placeholder": "",
125 | "_view_module": "@jupyter-widgets/controls",
126 | "_model_module_version": "1.5.0",
127 | "value": " 170499072/? [00:02<00:00, 58654212.03it/s]",
128 | "_view_count": null,
129 | "_view_module_version": "1.5.0",
130 | "description_tooltip": null,
131 | "_model_module": "@jupyter-widgets/controls",
132 | "layout": "IPY_MODEL_661d394b279547e197586c2e7ed91993"
133 | }
134 | },
135 | "2fe1f152bcf7413cae42224d18d44fd7": {
136 | "model_module": "@jupyter-widgets/controls",
137 | "model_name": "ProgressStyleModel",
138 | "state": {
139 | "_view_name": "StyleView",
140 | "_model_name": "ProgressStyleModel",
141 | "description_width": "initial",
142 | "_view_module": "@jupyter-widgets/base",
143 | "_model_module_version": "1.5.0",
144 | "_view_count": null,
145 | "_view_module_version": "1.2.0",
146 | "bar_color": null,
147 | "_model_module": "@jupyter-widgets/controls"
148 | }
149 | },
150 | "20cfd8834a4548e993b60bce5a119264": {
151 | "model_module": "@jupyter-widgets/base",
152 | "model_name": "LayoutModel",
153 | "state": {
154 | "_view_name": "LayoutView",
155 | "grid_template_rows": null,
156 | "right": null,
157 | "justify_content": null,
158 | "_view_module": "@jupyter-widgets/base",
159 | "overflow": null,
160 | "_model_module_version": "1.2.0",
161 | "_view_count": null,
162 | "flex_flow": null,
163 | "width": null,
164 | "min_width": null,
165 | "border": null,
166 | "align_items": null,
167 | "bottom": null,
168 | "_model_module": "@jupyter-widgets/base",
169 | "top": null,
170 | "grid_column": null,
171 | "overflow_y": null,
172 | "overflow_x": null,
173 | "grid_auto_flow": null,
174 | "grid_area": null,
175 | "grid_template_columns": null,
176 | "flex": null,
177 | "_model_name": "LayoutModel",
178 | "justify_items": null,
179 | "grid_row": null,
180 | "max_height": null,
181 | "align_content": null,
182 | "visibility": null,
183 | "align_self": null,
184 | "height": null,
185 | "min_height": null,
186 | "padding": null,
187 | "grid_auto_rows": null,
188 | "grid_gap": null,
189 | "max_width": null,
190 | "order": null,
191 | "_view_module_version": "1.2.0",
192 | "grid_template_areas": null,
193 | "object_position": null,
194 | "object_fit": null,
195 | "grid_auto_columns": null,
196 | "margin": null,
197 | "display": null,
198 | "left": null
199 | }
200 | },
201 | "755a675c4f374bd0a427143b783eb6b7": {
202 | "model_module": "@jupyter-widgets/controls",
203 | "model_name": "DescriptionStyleModel",
204 | "state": {
205 | "_view_name": "StyleView",
206 | "_model_name": "DescriptionStyleModel",
207 | "description_width": "",
208 | "_view_module": "@jupyter-widgets/base",
209 | "_model_module_version": "1.5.0",
210 | "_view_count": null,
211 | "_view_module_version": "1.2.0",
212 | "_model_module": "@jupyter-widgets/controls"
213 | }
214 | },
215 | "661d394b279547e197586c2e7ed91993": {
216 | "model_module": "@jupyter-widgets/base",
217 | "model_name": "LayoutModel",
218 | "state": {
219 | "_view_name": "LayoutView",
220 | "grid_template_rows": null,
221 | "right": null,
222 | "justify_content": null,
223 | "_view_module": "@jupyter-widgets/base",
224 | "overflow": null,
225 | "_model_module_version": "1.2.0",
226 | "_view_count": null,
227 | "flex_flow": null,
228 | "width": null,
229 | "min_width": null,
230 | "border": null,
231 | "align_items": null,
232 | "bottom": null,
233 | "_model_module": "@jupyter-widgets/base",
234 | "top": null,
235 | "grid_column": null,
236 | "overflow_y": null,
237 | "overflow_x": null,
238 | "grid_auto_flow": null,
239 | "grid_area": null,
240 | "grid_template_columns": null,
241 | "flex": null,
242 | "_model_name": "LayoutModel",
243 | "justify_items": null,
244 | "grid_row": null,
245 | "max_height": null,
246 | "align_content": null,
247 | "visibility": null,
248 | "align_self": null,
249 | "height": null,
250 | "min_height": null,
251 | "padding": null,
252 | "grid_auto_rows": null,
253 | "grid_gap": null,
254 | "max_width": null,
255 | "order": null,
256 | "_view_module_version": "1.2.0",
257 | "grid_template_areas": null,
258 | "object_position": null,
259 | "object_fit": null,
260 | "grid_auto_columns": null,
261 | "margin": null,
262 | "display": null,
263 | "left": null
264 | }
265 | }
266 | }
267 | },
268 | "accelerator": "GPU"
269 | },
270 | "cells": [
271 | {
272 | "cell_type": "markdown",
273 | "metadata": {
274 | "id": "view-in-github",
275 | "colab_type": "text"
276 | },
277 | "source": [
278 | "
"
279 | ]
280 | },
281 | {
282 | "cell_type": "code",
283 | "metadata": {
284 | "colab": {
285 | "base_uri": "https://localhost:8080/"
286 | },
287 | "id": "4BE4HL0SJrYa",
288 | "outputId": "6614b473-7668-4c7f-f46d-fc9f8b427e93"
289 | },
290 | "source": [
291 | "!pip install qiskit"
292 | ],
293 | "execution_count": 1,
294 | "outputs": [
295 | {
296 | "output_type": "stream",
297 | "text": [
298 | "Collecting qiskit\n",
299 | " Downloading https://files.pythonhosted.org/packages/79/19/44f002f6633c64b4ab88d274dd036857624e4ba8b701cd90a408103a3791/qiskit-0.27.0.tar.gz\n",
300 | "Collecting qiskit-terra==0.17.4\n",
301 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/b3/0c/3c7a8dd451dae0907263e9de9e3e34909e15e18c88a589b44581972c8511/qiskit_terra-0.17.4-cp37-cp37m-manylinux2010_x86_64.whl (6.0MB)\n",
302 | "\u001b[K |████████████████████████████████| 6.0MB 5.1MB/s \n",
303 | "\u001b[?25hCollecting qiskit-aer==0.8.2\n",
304 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/c2/d2/6ff15c370b5465b32529b528bf3f4ce1e01f74498be16203aa1c04b67022/qiskit_aer-0.8.2-cp37-cp37m-manylinux2010_x86_64.whl (18.0MB)\n",
305 | "\u001b[K |████████████████████████████████| 18.0MB 120kB/s \n",
306 | "\u001b[?25hCollecting qiskit-ibmq-provider==0.14.0\n",
307 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/83/2f/6f3b53b633cc477dbe601728c8c3fc8674441cb9554d14517254a52d0c8a/qiskit_ibmq_provider-0.14.0-py3-none-any.whl (229kB)\n",
308 | "\u001b[K |████████████████████████████████| 235kB 24.2MB/s \n",
309 | "\u001b[?25hCollecting qiskit-ignis==0.6.0\n",
310 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/54/be/a13c828e457e09d979667a61bddbd8c7246aafa94e2501b6a9154429cbea/qiskit_ignis-0.6.0-py3-none-any.whl (207kB)\n",
311 | "\u001b[K |████████████████████████████████| 215kB 47.6MB/s \n",
312 | "\u001b[?25hCollecting qiskit-aqua==0.9.2\n",
313 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/81/00/1f71631bbc3fd24537d7ec1c52adfcf4fa0851c13fefc05d6babcb11a1f8/qiskit_aqua-0.9.2-py3-none-any.whl (2.1MB)\n",
314 | "\u001b[K |████████████████████████████████| 2.1MB 34.2MB/s \n",
315 | "\u001b[?25hRequirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (2.6.0)\n",
316 | "Collecting python-constraint>=1.4\n",
317 | " Downloading https://files.pythonhosted.org/packages/37/8b/5f1bc2734ca611943e1d6733ee244238679f6410a10cd45ede55a61a8402/python-constraint-1.4.0.tar.bz2\n",
318 | "Requirement already satisfied: dill>=0.3 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (0.3.4)\n",
319 | "Requirement already satisfied: psutil>=5 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (5.4.8)\n",
320 | "Collecting retworkx>=0.8.0\n",
321 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/9e/cd/70d436f170aa1ead2ac9e4c19c8838633355d48b530f09455eab0af2f98e/retworkx-0.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.4MB)\n",
322 | "\u001b[K |████████████████████████████████| 1.5MB 35.3MB/s \n",
323 | "\u001b[?25hRequirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (1.19.5)\n",
324 | "Collecting ply>=3.10\n",
325 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl (49kB)\n",
326 | "\u001b[K |████████████████████████████████| 51kB 6.6MB/s \n",
327 | "\u001b[?25hRequirement already satisfied: python-dateutil>=2.8.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (2.8.1)\n",
328 | "Collecting fastjsonschema>=2.10\n",
329 | " Downloading https://files.pythonhosted.org/packages/d1/fb/ea090e917b18320f79be31d754bbe496b715175e865603cfce1eaed2e774/fastjsonschema-2.15.1-py3-none-any.whl\n",
330 | "Requirement already satisfied: scipy>=1.4 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (1.4.1)\n",
331 | "Requirement already satisfied: sympy>=1.3 in /usr/local/lib/python3.7/dist-packages (from qiskit-terra==0.17.4->qiskit) (1.7.1)\n",
332 | "Collecting pybind11>=2.6\n",
333 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/8d/43/7339dbabbc2793718d59703aace4166f53c29ee1c202f6ff5bf8a26c4d91/pybind11-2.6.2-py2.py3-none-any.whl (191kB)\n",
334 | "\u001b[K |████████████████████████████████| 194kB 46.1MB/s \n",
335 | "\u001b[?25hCollecting websocket-client>=1.0.1\n",
336 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/ca/5f/3c211d168b2e9f9342cfb53bcfc26aab0eac63b998015e7af7bcae66119d/websocket_client-1.1.0-py2.py3-none-any.whl (68kB)\n",
337 | "\u001b[K |████████████████████████████████| 71kB 9.8MB/s \n",
338 | "\u001b[?25hCollecting requests-ntlm>=1.1.0\n",
339 | " Downloading https://files.pythonhosted.org/packages/03/4b/8b9a1afde8072c4d5710d9fa91433d504325821b038e00237dc8d6d833dc/requests_ntlm-1.1.0-py2.py3-none-any.whl\n",
340 | "Requirement already satisfied: requests>=2.19 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.14.0->qiskit) (2.23.0)\n",
341 | "Requirement already satisfied: urllib3>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from qiskit-ibmq-provider==0.14.0->qiskit) (1.24.3)\n",
342 | "Requirement already satisfied: setuptools>=40.1.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-ignis==0.6.0->qiskit) (57.0.0)\n",
343 | "Requirement already satisfied: pandas in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.9.2->qiskit) (1.1.5)\n",
344 | "Collecting quandl\n",
345 | " Downloading https://files.pythonhosted.org/packages/8b/2b/feefb36015beaecc5c0f9f2533e815b409621d9fa7b50b2aac621796f828/Quandl-3.6.1-py2.py3-none-any.whl\n",
346 | "Requirement already satisfied: scikit-learn>=0.20.0 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.9.2->qiskit) (0.22.2.post1)\n",
347 | "Collecting docplex<=2.20.204; sys_platform != \"darwin\"\n",
348 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/87/99/6f7c219b39fd58c84688ad0713eb932bfcf6be81fc74519e43ea9c915b56/docplex-2.20.204.tar.gz (611kB)\n",
349 | "\u001b[K |████████████████████████████████| 614kB 34.3MB/s \n",
350 | "\u001b[?25hCollecting dlx<=1.0.4\n",
351 | " Downloading https://files.pythonhosted.org/packages/54/c0/b8fb5bb727e983b6f5251433ef941b48f38c65bb0bd6ec509e9185bcd406/dlx-1.0.4.tar.gz\n",
352 | "Collecting yfinance\n",
353 | " Downloading https://files.pythonhosted.org/packages/a7/ee/315752b9ef281ba83c62aa7ec2e2074f85223da6e7e74efb4d3e11c0f510/yfinance-0.1.59.tar.gz\n",
354 | "Requirement already satisfied: fastdtw<=0.3.4 in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.9.2->qiskit) (0.3.4)\n",
355 | "Requirement already satisfied: h5py in /usr/local/lib/python3.7/dist-packages (from qiskit-aqua==0.9.2->qiskit) (3.1.0)\n",
356 | "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.7/dist-packages (from python-dateutil>=2.8.0->qiskit-terra==0.17.4->qiskit) (1.15.0)\n",
357 | "Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy>=1.3->qiskit-terra==0.17.4->qiskit) (1.2.1)\n",
358 | "Collecting ntlm-auth>=1.0.2\n",
359 | " Downloading https://files.pythonhosted.org/packages/ff/84/97c550164b54942b0e908c31ef09d9469f3ba4cd7332a671e2125732f63b/ntlm_auth-1.5.0-py2.py3-none-any.whl\n",
360 | "Collecting cryptography>=1.3\n",
361 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/b2/26/7af637e6a7e87258b963f1731c5982fb31cd507f0d90d91836e446955d02/cryptography-3.4.7-cp36-abi3-manylinux2014_x86_64.whl (3.2MB)\n",
362 | "\u001b[K |████████████████████████████████| 3.2MB 38.7MB/s \n",
363 | "\u001b[?25hRequirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.14.0->qiskit) (2.10)\n",
364 | "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.14.0->qiskit) (2021.5.30)\n",
365 | "Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.14.0->qiskit) (3.0.4)\n",
366 | "Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.7/dist-packages (from pandas->qiskit-aqua==0.9.2->qiskit) (2018.9)\n",
367 | "Collecting inflection>=0.3.1\n",
368 | " Downloading https://files.pythonhosted.org/packages/59/91/aa6bde563e0085a02a435aa99b49ef75b0a4b062635e606dab23ce18d720/inflection-0.5.1-py2.py3-none-any.whl\n",
369 | "Requirement already satisfied: more-itertools in /usr/local/lib/python3.7/dist-packages (from quandl->qiskit-aqua==0.9.2->qiskit) (8.8.0)\n",
370 | "Requirement already satisfied: joblib>=0.11 in /usr/local/lib/python3.7/dist-packages (from scikit-learn>=0.20.0->qiskit-aqua==0.9.2->qiskit) (1.0.1)\n",
371 | "Requirement already satisfied: multitasking>=0.0.7 in /usr/local/lib/python3.7/dist-packages (from yfinance->qiskit-aqua==0.9.2->qiskit) (0.0.9)\n",
372 | "Collecting lxml>=4.5.1\n",
373 | "\u001b[?25l Downloading https://files.pythonhosted.org/packages/30/c0/d0526314971fc661b083ab135747dc68446a3022686da8c16d25fcf6ef07/lxml-4.6.3-cp37-cp37m-manylinux2014_x86_64.whl (6.3MB)\n",
374 | "\u001b[K |████████████████████████████████| 6.3MB 37.0MB/s \n",
375 | "\u001b[?25hRequirement already satisfied: cached-property; python_version < \"3.8\" in /usr/local/lib/python3.7/dist-packages (from h5py->qiskit-aqua==0.9.2->qiskit) (1.5.2)\n",
376 | "Requirement already satisfied: cffi>=1.12 in /usr/local/lib/python3.7/dist-packages (from cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.14.0->qiskit) (1.14.5)\n",
377 | "Requirement already satisfied: pycparser in /usr/local/lib/python3.7/dist-packages (from cffi>=1.12->cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.14.0->qiskit) (2.20)\n",
378 | "Building wheels for collected packages: qiskit, python-constraint, docplex, dlx, yfinance\n",
379 | " Building wheel for qiskit (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
380 | " Created wheel for qiskit: filename=qiskit-0.27.0-cp37-none-any.whl size=10505 sha256=10f30fdea9e877bba66706286d60e00ce2419baec4b6a3d13cb59ef21c70de7e\n",
381 | " Stored in directory: /root/.cache/pip/wheels/c6/54/d9/f0f711dc20aff31947456951374132d0e23ec527da8c15295d\n",
382 | " Building wheel for python-constraint (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
383 | " Created wheel for python-constraint: filename=python_constraint-1.4.0-py2.py3-none-any.whl size=24079 sha256=f0142898cfdc812b42ff7a8b39c4d0900e5ecc9ab1b8f6edd4ab543330a3cbad\n",
384 | " Stored in directory: /root/.cache/pip/wheels/34/31/15/7b070b25d0a549d20ce2e9fe6d727471c2c61ef904720fd40c\n",
385 | " Building wheel for docplex (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
386 | " Created wheel for docplex: filename=docplex-2.20.204-cp37-none-any.whl size=675396 sha256=cef4ea2bfe0d0fed41c12d081c9d51081851ed7e458abca71fad98df682e0b89\n",
387 | " Stored in directory: /root/.cache/pip/wheels/ae/2c/e2/a099ebb6fda8adeba9c5fc2e25659d195ad2f5c6cc5fb75fd4\n",
388 | " Building wheel for dlx (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
389 | " Created wheel for dlx: filename=dlx-1.0.4-cp37-none-any.whl size=5720 sha256=2c9ed4f40018720ce9d87f03b00e6d73db9e9a4d9bfb80ef53ba1539b080bfc8\n",
390 | " Stored in directory: /root/.cache/pip/wheels/bb/ba/15/fdd0deb104df3254912998150ba9245668db06b00af5912d1a\n",
391 | " Building wheel for yfinance (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
392 | " Created wheel for yfinance: filename=yfinance-0.1.59-py2.py3-none-any.whl size=23455 sha256=ce19493c31bc6d04244cdfe9f90530568180522ef682e39cdde433f60513cf40\n",
393 | " Stored in directory: /root/.cache/pip/wheels/f8/2a/0f/4b5a86e1d52e451757eb6bc17fd899629f0925c777741b6d04\n",
394 | "Successfully built qiskit python-constraint docplex dlx yfinance\n",
395 | "Installing collected packages: python-constraint, retworkx, ply, fastjsonschema, qiskit-terra, pybind11, qiskit-aer, websocket-client, ntlm-auth, cryptography, requests-ntlm, qiskit-ibmq-provider, qiskit-ignis, inflection, quandl, docplex, dlx, lxml, yfinance, qiskit-aqua, qiskit\n",
396 | " Found existing installation: lxml 4.2.6\n",
397 | " Uninstalling lxml-4.2.6:\n",
398 | " Successfully uninstalled lxml-4.2.6\n",
399 | "Successfully installed cryptography-3.4.7 dlx-1.0.4 docplex-2.20.204 fastjsonschema-2.15.1 inflection-0.5.1 lxml-4.6.3 ntlm-auth-1.5.0 ply-3.11 pybind11-2.6.2 python-constraint-1.4.0 qiskit-0.27.0 qiskit-aer-0.8.2 qiskit-aqua-0.9.2 qiskit-ibmq-provider-0.14.0 qiskit-ignis-0.6.0 qiskit-terra-0.17.4 quandl-3.6.1 requests-ntlm-1.1.0 retworkx-0.9.0 websocket-client-1.1.0 yfinance-0.1.59\n"
400 | ],
401 | "name": "stdout"
402 | }
403 | ]
404 | },
405 | {
406 | "cell_type": "code",
407 | "metadata": {
408 | "colab": {
409 | "base_uri": "https://localhost:8080/"
410 | },
411 | "id": "mPVMDRDsPS58",
412 | "outputId": "c8fe66ba-cda7-4c5b-ead1-a16dd8b0e181"
413 | },
414 | "source": [
415 | "# check if CUDA is available\n",
416 | "import torch\n",
417 | "train_on_gpu = torch.cuda.is_available()\n",
418 | "\n",
419 | "if not train_on_gpu:\n",
420 | " print('CUDA is not available. Training on CPU ...')\n",
421 | "else:\n",
422 | " print('CUDA is available! Training on GPU ...')"
423 | ],
424 | "execution_count": 3,
425 | "outputs": [
426 | {
427 | "output_type": "stream",
428 | "text": [
429 | "CUDA is available! Training on GPU ...\n"
430 | ],
431 | "name": "stdout"
432 | }
433 | ]
434 | },
435 | {
436 | "cell_type": "code",
437 | "metadata": {
438 | "id": "cen8pzlVbzDF"
439 | },
440 | "source": [
441 | "\n",
442 | "import numpy as np\n",
443 | "import matplotlib.pyplot as plt\n",
444 | "\n",
445 | "import torch\n",
446 | "from torch.autograd import Function\n",
447 | "from torchvision import datasets, transforms\n",
448 | "import torch.optim as optim\n",
449 | "import torch.nn as nn\n",
450 | "import torch.nn.functional as F\n",
451 | "\n",
452 | "import qiskit\n",
453 | "from qiskit import transpile, assemble\n",
454 | "from qiskit.visualization import *"
455 | ],
456 | "execution_count": 4,
457 | "outputs": []
458 | },
459 | {
460 | "cell_type": "code",
461 | "metadata": {
462 | "id": "pYRqHiA4J_yw"
463 | },
464 | "source": [
465 | "import numpy as np\n",
466 | "import torch\n",
467 | "from torch.autograd import Function\n",
468 | "import torch.optim as optim\n",
469 | "import torch.nn as nn\n",
470 | "import torch.nn.functional as F\n",
471 | "import torchvision\n",
472 | "from torchvision import datasets, transforms\n",
473 | "from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister, execute\n",
474 | "from qiskit.circuit import Parameter\n",
475 | "from qiskit import Aer\n",
476 | "from tqdm import tqdm\n",
477 | "from matplotlib import pyplot as plt\n",
478 | "%matplotlib inline"
479 | ],
480 | "execution_count": 5,
481 | "outputs": []
482 | },
483 | {
484 | "cell_type": "code",
485 | "metadata": {
486 | "id": "uS6nwoWxdqQT"
487 | },
488 | "source": [
489 | "def to_numbers(tensor_list):\n",
490 | " num_list = []\n",
491 | " for tensor in tensor_list:\n",
492 | " num_list += [tensor.item()]\n",
493 | " return num_list"
494 | ],
495 | "execution_count": 6,
496 | "outputs": []
497 | },
498 | {
499 | "cell_type": "code",
500 | "metadata": {
501 | "id": "9Zxv2aYdJ_7W"
502 | },
503 | "source": [
504 | "class QuantumCircuit:\n",
505 | " \"\"\" \n",
506 | " This class provides a simple interface for interaction \n",
507 | " with the quantum circuit \n",
508 | " \"\"\"\n",
509 | " \n",
510 | " def __init__(self, n_qubits, backend, shots):\n",
511 | " # --- Circuit definition ---\n",
512 | " self._circuit = qiskit.QuantumCircuit(n_qubits)\n",
513 | " \n",
514 | " all_qubits = [i for i in range(n_qubits)]\n",
515 | " self.theta = qiskit.circuit.Parameter('theta')\n",
516 | " \n",
517 | " self._circuit.h(all_qubits)\n",
518 | " self._circuit.barrier()\n",
519 | " self._circuit.ry(self.theta, all_qubits)\n",
520 | " \n",
521 | " self._circuit.measure_all()\n",
522 | " # ---------------------------\n",
523 | "\n",
524 | " self.backend = backend\n",
525 | " self.shots = shots\n",
526 | " \n",
527 | " def run(self, thetas):\n",
528 | " t_qc = transpile(self._circuit,\n",
529 | " self.backend)\n",
530 | " qobj = assemble(t_qc,\n",
531 | " shots=self.shots,\n",
532 | " parameter_binds = [{self.theta: theta} for theta in thetas])\n",
533 | " job = self.backend.run(qobj)\n",
534 | " result = job.result().get_counts()\n",
535 | " \n",
536 | " counts = np.array(list(result.values()))\n",
537 | " states = np.array(list(result.keys())).astype(float)\n",
538 | " \n",
539 | " # Compute probabilities for each state\n",
540 | " probabilities = counts / self.shots\n",
541 | " # Get state expectation\n",
542 | " expectation = np.sum(states * probabilities)\n",
543 | " \n",
544 | " return np.array([expectation])"
545 | ],
546 | "execution_count": 7,
547 | "outputs": []
548 | },
549 | {
550 | "cell_type": "code",
551 | "metadata": {
552 | "id": "jcTJjA7aKVT-"
553 | },
554 | "source": [
555 | "class HybridFunction(Function):\n",
556 | " \"\"\" Hybrid quantum - classical function definition \"\"\"\n",
557 | " \n",
558 | " @staticmethod\n",
559 | " def forward(ctx, input, quantum_circuit, shift):\n",
560 | " \"\"\" Forward pass computation \"\"\"\n",
561 | " ctx.shift = shift\n",
562 | " ctx.quantum_circuit = quantum_circuit\n",
563 | "\n",
564 | " expectation_z = ctx.quantum_circuit.run(input[0].tolist())\n",
565 | " result = torch.tensor([expectation_z])\n",
566 | " ctx.save_for_backward(input, result)\n",
567 | "\n",
568 | " return result\n",
569 | " \n",
570 | " @staticmethod\n",
571 | " def backward(ctx, grad_output):\n",
572 | " \"\"\" Backward pass computation \"\"\"\n",
573 | " input, expectation_z = ctx.saved_tensors\n",
574 | " input_list = np.array(input.tolist())\n",
575 | " \n",
576 | " shift_right = input_list + np.ones(input_list.shape) * ctx.shift\n",
577 | " shift_left = input_list - np.ones(input_list.shape) * ctx.shift\n",
578 | " \n",
579 | " gradients = []\n",
580 | " for i in range(len(input_list)):\n",
581 | " expectation_right = ctx.quantum_circuit.run(shift_right[i])\n",
582 | " expectation_left = ctx.quantum_circuit.run(shift_left[i])\n",
583 | " \n",
584 | " gradient = torch.tensor([expectation_right]) - torch.tensor([expectation_left])\n",
585 | " gradients.append(gradient)\n",
586 | " gradients = np.array([gradients]).T\n",
587 | " return torch.tensor([gradients]).float() * grad_output.float(), None, None\n",
588 | "\n",
589 | "class Hybrid(nn.Module):\n",
590 | " \"\"\" Hybrid quantum - classical layer definition \"\"\"\n",
591 | " \n",
592 | " def __init__(self, backend, shots, shift):\n",
593 | " super(Hybrid, self).__init__()\n",
594 | " self.quantum_circuit = QuantumCircuit(1, backend, shots)\n",
595 | " self.shift = shift\n",
596 | " \n",
597 | " def forward(self, input):\n",
598 | " return HybridFunction.apply(input, self.quantum_circuit, self.shift)"
599 | ],
600 | "execution_count": 8,
601 | "outputs": []
602 | },
603 | {
604 | "cell_type": "code",
605 | "metadata": {
606 | "colab": {
607 | "base_uri": "https://localhost:8080/",
608 | "height": 99,
609 | "referenced_widgets": [
610 | "6b21baa29bbf408d96883c52c578d25e",
611 | "c0afc2958d7f4cb6ad5fa7df3127b838",
612 | "97126e60fd414c0ca90bcf1090f159e0",
613 | "61bcf60fe4cc4dc7bebc1215bf6c27f7",
614 | "2fe1f152bcf7413cae42224d18d44fd7",
615 | "20cfd8834a4548e993b60bce5a119264",
616 | "755a675c4f374bd0a427143b783eb6b7",
617 | "661d394b279547e197586c2e7ed91993"
618 | ]
619 | },
620 | "id": "jF_gcTnMKXNs",
621 | "outputId": "7da967d2-5363-4827-ca25-1120191d130a"
622 | },
623 | "source": [
624 | "import torchvision\n",
625 | "transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()]) # transform images to tensors/vectors\n",
626 | "cifar_trainset = datasets.CIFAR10(root='./data1', train=True, download=True, transform=transform)"
627 | ],
628 | "execution_count": 9,
629 | "outputs": [
630 | {
631 | "output_type": "stream",
632 | "text": [
633 | "Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data1/cifar-10-python.tar.gz\n"
634 | ],
635 | "name": "stdout"
636 | },
637 | {
638 | "output_type": "display_data",
639 | "data": {
640 | "application/vnd.jupyter.widget-view+json": {
641 | "model_id": "6b21baa29bbf408d96883c52c578d25e",
642 | "version_minor": 0,
643 | "version_major": 2
644 | },
645 | "text/plain": [
646 | "HBox(children=(FloatProgress(value=0.0, max=170498071.0), HTML(value='')))"
647 | ]
648 | },
649 | "metadata": {
650 | "tags": []
651 | }
652 | },
653 | {
654 | "output_type": "stream",
655 | "text": [
656 | "\n",
657 | "Extracting ./data1/cifar-10-python.tar.gz to ./data1\n"
658 | ],
659 | "name": "stdout"
660 | }
661 | ]
662 | },
663 | {
664 | "cell_type": "code",
665 | "metadata": {
666 | "colab": {
667 | "base_uri": "https://localhost:8080/"
668 | },
669 | "id": "LleGzzGrKjmY",
670 | "outputId": "9f0dcc2a-3ca4-43ae-a3d9-14b88b6e7282"
671 | },
672 | "source": [
673 | "len(cifar_trainset)"
674 | ],
675 | "execution_count": 10,
676 | "outputs": [
677 | {
678 | "output_type": "execute_result",
679 | "data": {
680 | "text/plain": [
681 | "50000"
682 | ]
683 | },
684 | "metadata": {
685 | "tags": []
686 | },
687 | "execution_count": 10
688 | }
689 | ]
690 | },
691 | {
692 | "cell_type": "code",
693 | "metadata": {
694 | "id": "wLYWsG_zKnyI"
695 | },
696 | "source": [
697 | "from torch.utils.data import DataLoader, random_split"
698 | ],
699 | "execution_count": 11,
700 | "outputs": []
701 | },
702 | {
703 | "cell_type": "code",
704 | "metadata": {
705 | "id": "51xN5aJDKo1S"
706 | },
707 | "source": [
708 | "#cifar_trainset = datasets.CIFAR10(root='./data1', train=True, download=True, transform=transform)\n",
709 | "\n",
710 | "\n",
711 | "labels = cifar_trainset.targets # get the labels for the data\n",
712 | "labels = np.array(labels)\n",
713 | "\n",
714 | "idx1 = np.where(labels == 0) # filter on aeroplanes\n",
715 | "idx2 = np.where(labels == 1) # filter on automobiles\n",
716 | "\n",
717 | "# Specify number of datapoints per class (i.e. there will be n pictures of automobiles and n pictures of aeroplanes in the training set)\n",
718 | "n=100\n",
719 | "\n",
720 | "# concatenate the data indices\n",
721 | "idx = np.concatenate((idx1[0][0:n],idx2[0][0:n])) \n",
722 | "\n",
723 | "# create the filtered dataset for our training set\n",
724 | "cifar_trainset.targets = labels[idx] \n",
725 | "cifar_trainset.data = cifar_trainset.data[idx]\n",
726 | "\n",
727 | "cifar_trainset, valid = random_split(cifar_trainset,[150,50])\n",
728 | "\n",
729 | "train_loader = torch.utils.data.DataLoader(cifar_trainset, batch_size=1, shuffle=True)\n",
730 | "valid_loader = torch.utils.data.DataLoader(valid, batch_size=1, shuffle=True)"
731 | ],
732 | "execution_count": 12,
733 | "outputs": []
734 | },
735 | {
736 | "cell_type": "code",
737 | "metadata": {
738 | "id": "pZtFi8B9LmvE"
739 | },
740 | "source": [
741 | "@torch.no_grad()\n",
742 | "def get_all_preds(model, train_loader):\n",
743 | " all_preds = torch.tensor([])\n",
744 | " for batch in train_loader:\n",
745 | " images, labels = batch\n",
746 | "\n",
747 | " preds = model(images)\n",
748 | " all_preds = torch.cat(\n",
749 | " (all_preds, preds)\n",
750 | " ,dim=0\n",
751 | " )\n",
752 | " return all_preds"
753 | ],
754 | "execution_count": 13,
755 | "outputs": []
756 | },
757 | {
758 | "cell_type": "code",
759 | "metadata": {
760 | "colab": {
761 | "base_uri": "https://localhost:8080/",
762 | "height": 130
763 | },
764 | "id": "_wUCuMmHLowP",
765 | "outputId": "062b0dd5-d53c-4f92-8483-5f136f23dfe8"
766 | },
767 | "source": [
768 | "import numpy as np \n",
769 | "import matplotlib.pyplot as plt\n",
770 | "\n",
771 | "n_samples_show = 6\n",
772 | "\n",
773 | "data_iter = iter(train_loader)\n",
774 | "fig, axes = plt.subplots(nrows=1, ncols=n_samples_show, figsize=(10, 2))\n",
775 | "\n",
776 | "while n_samples_show > 0:\n",
777 | " images, targets = data_iter.__next__()\n",
778 | " images=images.squeeze()\n",
779 | " \n",
780 | " axes[n_samples_show - 1].imshow(images[0].numpy(), cmap='gray')\n",
781 | " axes[n_samples_show - 1].set_xticks([])\n",
782 | " axes[n_samples_show - 1].set_yticks([])\n",
783 | " axes[n_samples_show - 1].set_title(\"Labeled: {}\".format(targets.item()))\n",
784 | " \n",
785 | " n_samples_show -= 1"
786 | ],
787 | "execution_count": 14,
788 | "outputs": [
789 | {
790 | "output_type": "display_data",
791 | "data": {
792 | "image/png": "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\n",
793 | "text/plain": [
794 | ""
795 | ]
796 | },
797 | "metadata": {
798 | "tags": []
799 | }
800 | }
801 | ]
802 | },
803 | {
804 | "cell_type": "code",
805 | "metadata": {
806 | "id": "tsft9NG8MZZG"
807 | },
808 | "source": [
809 | ""
810 | ],
811 | "execution_count": null,
812 | "outputs": []
813 | },
814 | {
815 | "cell_type": "code",
816 | "metadata": {
817 | "colab": {
818 | "base_uri": "https://localhost:8080/"
819 | },
820 | "id": "GGbi3LCbu48T",
821 | "outputId": "fdb2fbc4-db41-4f0a-ee9b-e672cf1c4076"
822 | },
823 | "source": [
824 | "import torchvision\n",
825 | "transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()]) # transform images to tensors/vectors\n",
826 | "cifar_testset = datasets.CIFAR10(root='./data1', train=False, download=True, transform=transform)\n",
827 | "\n",
828 | "labels = cifar_testset.targets # get the labels for the data\n",
829 | "labels = np.array(labels)\n",
830 | "\n",
831 | "idx1 = np.where(labels == 0) # filter on aeroplanes\n",
832 | "idx2 = np.where(labels == 1) # filter on automobiles\n",
833 | "\n",
834 | "# Specify number of datapoints per class (i.e. there will be n pictures of automobiles and n pictures of aeroplanes in the training set)\n",
835 | "n=100\n",
836 | "\n",
837 | "# concatenate the data indices\n",
838 | "idx = np.concatenate((idx1[0][0:n],idx2[0][0:n])) \n",
839 | "\n",
840 | "# create the filtered dataset for our training set\n",
841 | "cifar_testset.targets = labels[idx] \n",
842 | "cifar_testset.data = cifar_testset.data[idx]\n",
843 | "\n",
844 | "test_loader = torch.utils.data.DataLoader(cifar_testset, batch_size=1, shuffle=False)"
845 | ],
846 | "execution_count": 15,
847 | "outputs": [
848 | {
849 | "output_type": "stream",
850 | "text": [
851 | "Files already downloaded and verified\n"
852 | ],
853 | "name": "stdout"
854 | }
855 | ]
856 | },
857 | {
858 | "cell_type": "code",
859 | "metadata": {
860 | "colab": {
861 | "base_uri": "https://localhost:8080/"
862 | },
863 | "id": "6EepnrZFBtZ6",
864 | "outputId": "e9903bd8-bd38-4bab-a2c1-b4161f0c6147"
865 | },
866 | "source": [
867 | "len(cifar_testset)"
868 | ],
869 | "execution_count": 16,
870 | "outputs": [
871 | {
872 | "output_type": "execute_result",
873 | "data": {
874 | "text/plain": [
875 | "200"
876 | ]
877 | },
878 | "metadata": {
879 | "tags": []
880 | },
881 | "execution_count": 16
882 | }
883 | ]
884 | },
885 | {
886 | "cell_type": "code",
887 | "metadata": {
888 | "id": "_xmz9iOuvfAh"
889 | },
890 | "source": [
891 | "class Net(nn.Module):\n",
892 | " def __init__(self):\n",
893 | " super(Net, self).__init__()\n",
894 | " self.conv1 = nn.Conv2d(3, 10, kernel_size=5)\n",
895 | " self.conv2 = nn.Conv2d(10, 20, kernel_size=5)\n",
896 | " self.dropout = nn.Dropout2d()\n",
897 | " self.fc1 = nn.Linear(500, 500)\n",
898 | " self.fc2 = nn.Linear(500, 1)\n",
899 | " self.hybrid = Hybrid(qiskit.Aer.get_backend('qasm_simulator'), 100, np.pi / 2)\n",
900 | "\n",
901 | " def forward(self, x):\n",
902 | " x = F.relu(self.conv1(x))\n",
903 | " x = F.max_pool2d(x, 2)\n",
904 | " x = F.relu(self.conv2(x))\n",
905 | " x = F.max_pool2d(x, 2)\n",
906 | " x = self.dropout(x)\n",
907 | " x = x.view(1, -1)\n",
908 | " x = F.relu(self.fc1(x))\n",
909 | " x = self.fc2(x)\n",
910 | " x = self.hybrid(x)\n",
911 | " return torch.cat((x, 1 - x), -1)"
912 | ],
913 | "execution_count": 17,
914 | "outputs": []
915 | },
916 | {
917 | "cell_type": "code",
918 | "metadata": {
919 | "id": "OpOsgNA1OFjq"
920 | },
921 | "source": [
922 | ""
923 | ],
924 | "execution_count": null,
925 | "outputs": []
926 | },
927 | {
928 | "cell_type": "code",
929 | "metadata": {
930 | "colab": {
931 | "base_uri": "https://localhost:8080/",
932 | "height": 349
933 | },
934 | "id": "Ur6t9UeqMlpa",
935 | "outputId": "cc8428bf-997f-4fc0-ecc1-ade926685aac"
936 | },
937 | "source": [
938 | "%matplotlib inline\n",
939 | "import matplotlib.pyplot as plt\n",
940 | "model = Net()\n",
941 | "optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
942 | "loss_func = nn.NLLLoss()\n",
943 | "\n",
944 | "epochs = 5\n",
945 | "loss_list = []\n",
946 | "loss_list_V = []\n",
947 | "\n",
948 | "#training the model\n",
949 | "model.train()\n",
950 | "for epoch in range(epochs):\n",
951 | " train_loss = []\n",
952 | " for batch_idx, (data, target) in enumerate(train_loader):\n",
953 | " optimizer.zero_grad()\n",
954 | " # Forward pass\n",
955 | " output = model(data)\n",
956 | " # Calculating loss\n",
957 | " loss = loss_func(output, target)\n",
958 | " # Backward pass\n",
959 | " loss.backward()\n",
960 | " # Optimize the weights\n",
961 | " optimizer.step()\n",
962 | " \n",
963 | " train_loss.append(loss.item())\n",
964 | " loss_list.append(sum(train_loss)/len(train_loss))\n",
965 | " #print('Training [{:.0f}%]\\tLoss: {:.4f}'.format(100. * (epoch + 1) / epochs, loss_list[-1]))\n",
966 | "\n",
967 | "\n",
968 | "#Validate the model\n",
969 | "\n",
970 | "model.eval()\n",
971 | "for epoch in range(epochs):\n",
972 | " valid_loss = []\n",
973 | " for batch_idx, (data, target) in enumerate(valid_loader):\n",
974 | " optimizer.zero_grad()\n",
975 | " # Forward pass\n",
976 | " output = model(data)\n",
977 | " # Calculating loss\n",
978 | " validation_loss = loss_func(output, target)\n",
979 | " # Backward pass\n",
980 | " validation_loss.backward()\n",
981 | " # Optimize the weights\n",
982 | " optimizer.step()\n",
983 | " \n",
984 | " valid_loss.append(validation_loss.item())\n",
985 | " loss_list_V.append(sum(valid_loss)/len(valid_loss))\n",
986 | " #print('Training [{:.0f}%]\\tLoss: {:.4f}'.format(100. * (epoch + 1) / epochs, loss_list_V[-1]))\n",
987 | " print('Epoch: {} \\tTraining Loss: {:.6f} \\tValidation Loss: {:.6f}'.format(\n",
988 | " epoch, loss_list[-1], loss_list_V[-1]))\n",
989 | "\n",
990 | "\n",
991 | "\n",
992 | "\n",
993 | "#Now plotting the training graph\n",
994 | "plt.plot(loss_list,label='Training Loss') \n",
995 | "plt.plot(loss_list_V,label='Validation Loss') \n",
996 | "plt.legend() \n",
997 | "plt.show() \n"
998 | ],
999 | "execution_count": 34,
1000 | "outputs": [
1001 | {
1002 | "output_type": "stream",
1003 | "text": [
1004 | "Epoch: 0 \tTraining Loss: -0.670600 \tValidation Loss: -0.759400\n",
1005 | "Epoch: 1 \tTraining Loss: -0.670600 \tValidation Loss: -0.803600\n",
1006 | "Epoch: 2 \tTraining Loss: -0.670600 \tValidation Loss: -0.847600\n",
1007 | "Epoch: 3 \tTraining Loss: -0.670600 \tValidation Loss: -0.831200\n",
1008 | "Epoch: 4 \tTraining Loss: -0.670600 \tValidation Loss: -0.897600\n"
1009 | ],
1010 | "name": "stdout"
1011 | },
1012 | {
1013 | "output_type": "display_data",
1014 | "data": {
1015 | "image/png": "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\n",
1016 | "text/plain": [
1017 | ""
1018 | ]
1019 | },
1020 | "metadata": {
1021 | "tags": [],
1022 | "needs_background": "light"
1023 | }
1024 | }
1025 | ]
1026 | },
1027 | {
1028 | "cell_type": "code",
1029 | "metadata": {
1030 | "colab": {
1031 | "base_uri": "https://localhost:8080/"
1032 | },
1033 | "id": "bo6vTTvimIj4",
1034 | "outputId": "5a30f0fd-2014-4e28-91ea-d693f78b3dcb"
1035 | },
1036 | "source": [
1037 | "total_loss=[]\n",
1038 | "model.eval()\n",
1039 | "with torch.no_grad():\n",
1040 | " \n",
1041 | " correct = 0\n",
1042 | " for batch_idx, (data, target) in enumerate(test_loader):\n",
1043 | " output = model(data)\n",
1044 | " \n",
1045 | " pred = output.argmax(dim=1, keepdim=True) \n",
1046 | " correct += pred.eq(target.view_as(pred)).sum().item()\n",
1047 | " \n",
1048 | " loss = loss_func(output, target)\n",
1049 | " total_loss.append(loss.item())\n",
1050 | " \n",
1051 | " print('Performance on train data:\\n\\tLoss: {:.4f}\\n\\tAccuracy: {:.1f}%'.format(\n",
1052 | " sum(total_loss) / len(total_loss),\n",
1053 | " correct / len(test_loader) * 100)\n",
1054 | " )\n"
1055 | ],
1056 | "execution_count": 36,
1057 | "outputs": [
1058 | {
1059 | "output_type": "stream",
1060 | "text": [
1061 | "Performance on train data:\n",
1062 | "\tLoss: -0.7634\n",
1063 | "\tAccuracy: 81.5%\n"
1064 | ],
1065 | "name": "stdout"
1066 | }
1067 | ]
1068 | }
1069 | ]
1070 | }
1071 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Quantum-Classical Hyrid Neural Network for binary image classification using PyTorch-Qiskit pipeline
2 |
3 | This project involved developing a Hybrid Quantum Neural Network using the amalgamation of PyTorch and Qiskit , i.e intergrating the classical ML tools and features of PyTorch with the Quantum Computing framework of Qiskit. Hold-out validation was carried out, the model was tested on a validation set before noting the test accuracy. Hyperparameter tuning , effect of changing learning rates, optimizer and loss function on the model and Layer architectures were studied. The Quantum Layer involved a Parametrized Quantum circuit analogous to using a Variational Circuit as a classifier. This project was carried out under the guidance of Dr Elias F Combarro, Professor of Computer Science at Universidad de Oviedo, Spain and Advisor CERN QTI to whom I am extremely indebted to for his help and mentorship.
4 |
5 |
6 | ## Pre-requisites
7 | The following are the pre-requisites for running the notebook on a local machine (Google Colab was used throughout this project along with IBM Quantum Experience owing to the ease in integrating PyTorch and Qiskit without the local installation of additional dependencies).
8 |
9 | * Python3
10 | * Qiskit
11 | * PyTorch
12 | * Matplotlib
13 | * Numpy
14 | * torchvision
15 |
16 | The Google Colab notebooks can be accessed under the [Notebook](https://github.com/DRA-chaos/Quantum-Convolutional-Neural-Network/tree/main/Notebooks) folder of this repository.
17 |
18 | ## Dataset:
19 | The CIFAR-10 dataset outsourced from the torchvision datasets under PyTorch has been used for this project.
20 | The CIFAR-10 dataset that can be accessed [here](https://www.cs.toronto.edu/~kriz/cifar.html) consists of 60000 32x32 colour images in 10 classes, with 6000 images per class. There are 50000 training images and 10000 test images.
21 |
22 | The dataset is divided into five training batches and one test batch, each with 10000 images. The test batch contains exactly 1000 randomly-selected images from each class. The training batches contain the remaining images in random order, but some training batches may contain more images from one class than another. Between them, the training batches contain exactly 5000 images from each class.
23 | The project encompassed building a variational classifier to distinguish between Aeroplanes and Automobiles.
24 | 
25 |
26 | [image source](https://www.cs.toronto.edu/~kriz/cifar.html)
27 |
28 | Here are a few sample observations from the study :
29 | 
30 |
31 | ## Flowchart depicting the Quantum Layer
32 |
33 | 
34 |
35 |
36 | ## References:
37 | [1]Crooks, Gavin. (2019). Gradients of parameterized quantum gates using the parameter-shift rule and gate decomposition.
38 |
39 | [2]A. Asfaw, L. Bello, Y. Ben-Haim, S. Bravyi, L. Capelluto, A. C. Vazquez, J. Ceroni, J. Gambetta, S. Garion, L. Gil, et al., Learn quantum computation using qiskit (2020),
40 | URL:https://qiskit.org/textbook/ch-machine-learning/machine-learning-qiskit-pytorch.html
41 |
42 | [3]Krizhevsky, Alex. (2012). Learning Multiple Layers of Features from Tiny Images. University of Toronto.
43 |
44 | [4]Oh, Seunghyeok & Choi, Jaeho & Kim, Joongheon. (2020). A Tutorial on Quantum Convolutional Neural Networks (QCNN).
45 |
46 | [5]Farhi, Edward & Neven, Hartmut. (2018). Classification with Quantum Neural Networks on Near Term Processors.
47 |
48 | [6]Kulkarni, Viraj & Kulkarni, Milind & Pant, Aniruddha. (2020). Quantum Computing Methods for Supervised Learning.
49 |
50 | [7]Beer, K., Bondarenko, D., Farrelly, T. et al. Training deep quantum neural networks. Nat Commun 11, 808 (2020). https://doi.org/10.1038/s41467-020-14454-2
51 |
52 | Enjoy your journey through the quantum realm !!
53 |
54 | Rita Abani
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/paper.md.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DRA-chaos/Quantum-Classical-Hyrid-Neural-Network-for-binary-image-classification-using-PyTorch-Qiskit-pipeline/07c99915851af71584ebcf700c16c60d713ad81a/paper.md.zip
--------------------------------------------------------------------------------