{ "cells": [ { "cell_type": "markdown", "id": "secondary-copying", "metadata": {}, "source": [ "# Torch Connector and Hybrid QNNs\n", "\n", "This tutorial introduces the `TorchConnector` class, and demonstrates how it allows for a natural integration of any `NeuralNetwork` from Qiskit Machine Learning into a PyTorch workflow. `TorchConnector` takes a `NeuralNetwork` and makes it available as a PyTorch `Module`. The resulting module can be seamlessly incorporated into PyTorch classical architectures and trained jointly without additional considerations, enabling the development and testing of novel **hybrid quantum-classical** machine learning architectures.\n", "\n", "## Content:\n", "\n", "[Part 1: Simple Classification & Regression](#Part-1:-Simple-Classification-&-Regression)\n", "\n", "The first part of this tutorial shows how quantum neural networks can be trained using PyTorch's automatic differentiation engine (`torch.autograd`, [link](https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html)) for simple classification and regression tasks. \n", "\n", "1. [Classification](#1.-Classification)\n", " 1. Classification with PyTorch and `EstimatorQNN`\n", " 2. Classification with PyTorch and `SamplerQNN`\n", "2. [Regression](#2.-Regression)\n", " 1. Regression with PyTorch and `EstimatorQNN`\n", "\n", "[Part 2: MNIST Classification, Hybrid QNNs](#Part-2:-MNIST-Classification,-Hybrid-QNNs)\n", "\n", "The second part of this tutorial illustrates how to embed a (Quantum) `NeuralNetwork` into a target PyTorch workflow (in this case, a typical CNN architecture) to classify MNIST data in a hybrid quantum-classical manner.\n", "\n", "***" ] }, { "cell_type": "code", "execution_count": 1, "id": "banned-helicopter", "metadata": {}, "outputs": [], "source": [ "# Necessary imports\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "from torch import Tensor\n", "from torch.nn import Linear, CrossEntropyLoss, MSELoss\n", "from torch.optim import LBFGS\n", "\n", "from qiskit import QuantumCircuit\n", "from qiskit.circuit import Parameter\n", "from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap\n", "from qiskit_algorithms.utils import algorithm_globals\n", "from qiskit_machine_learning.neural_networks import SamplerQNN, EstimatorQNN\n", "from qiskit_machine_learning.connectors import TorchConnector\n", "\n", "# Set seed for random generators\n", "algorithm_globals.random_seed = 42" ] }, { "cell_type": "markdown", "id": "unique-snapshot", "metadata": {}, "source": [ "## Part 1: Simple Classification & Regression" ] }, { "cell_type": "markdown", "id": "surgical-penetration", "metadata": {}, "source": [ "### 1. Classification\n", "\n", "First, we show how `TorchConnector` allows to train a Quantum `NeuralNetwork` to solve a classification tasks using PyTorch's automatic differentiation engine. In order to illustrate this, we will perform **binary classification** on a randomly generated dataset." ] }, { "cell_type": "code", "execution_count": 2, "id": "secure-tragedy", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Generate random dataset\n", "\n", "# Select dataset dimension (num_inputs) and size (num_samples)\n", "num_inputs = 2\n", "num_samples = 20\n", "\n", "# Generate random input coordinates (X) and binary labels (y)\n", "X = 2 * algorithm_globals.random.random([num_samples, num_inputs]) - 1\n", "y01 = 1 * (np.sum(X, axis=1) >= 0) # in { 0, 1}, y01 will be used for SamplerQNN example\n", "y = 2 * y01 - 1 # in {-1, +1}, y will be used for EstimatorQNN example\n", "\n", "# Convert to torch Tensors\n", "X_ = Tensor(X)\n", "y01_ = Tensor(y01).reshape(len(y)).long()\n", "y_ = Tensor(y).reshape(len(y), 1)\n", "\n", "# Plot dataset\n", "for x, y_target in zip(X, y):\n", " if y_target == 1:\n", " plt.plot(x[0], x[1], \"bo\")\n", " else:\n", " plt.plot(x[0], x[1], \"go\")\n", "plt.plot([-1, 1], [1, -1], \"--\", color=\"black\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "hazardous-rehabilitation", "metadata": {}, "source": [ "#### A. Classification with PyTorch and `EstimatorQNN`\n", "\n", "Linking an `EstimatorQNN` to PyTorch is relatively straightforward. Here we illustrate this by using the `EstimatorQNN` constructed from a feature map and an ansatz." ] }, { "cell_type": "code", "execution_count": 3, "id": "fewer-desperate", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Set up a circuit\n", "feature_map = ZZFeatureMap(num_inputs)\n", "ansatz = RealAmplitudes(num_inputs)\n", "qc = QuantumCircuit(num_inputs)\n", "qc.compose(feature_map, inplace=True)\n", "qc.compose(ansatz, inplace=True)\n", "qc.draw(\"mpl\")" ] }, { "cell_type": "code", "execution_count": 4, "id": "humanitarian-flavor", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Initial weights: [-0.01256962 0.06653564 0.04005302 -0.03752667 0.06645196 0.06095287\n", " -0.02250432 -0.04233438]\n" ] } ], "source": [ "# Setup QNN\n", "qnn1 = EstimatorQNN(\n", " circuit=qc, input_params=feature_map.parameters, weight_params=ansatz.parameters\n", ")\n", "\n", "# Set up PyTorch module\n", "# Note: If we don't explicitly declare the initial weights\n", "# they are chosen uniformly at random from [-1, 1].\n", "initial_weights = 0.1 * (2 * algorithm_globals.random.random(qnn1.num_weights) - 1)\n", "model1 = TorchConnector(qnn1, initial_weights=initial_weights)\n", "print(\"Initial weights: \", initial_weights)" ] }, { "cell_type": "code", "execution_count": 5, "id": "likely-grace", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([-0.3285], grad_fn=<_TorchNNFunctionBackward>)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Test with a single input\n", "model1(X_[0, :])" ] }, { "cell_type": "markdown", "id": "gorgeous-segment", "metadata": {}, "source": [ "##### Optimizer\n", "The choice of optimizer for training any machine learning model can be crucial in determining the success of our training's outcome. When using `TorchConnector`, we get access to all of the optimizer algorithms defined in the [`torch.optim`] package ([link](https://pytorch.org/docs/stable/optim.html)). Some of the most famous algorithms used in popular machine learning architectures include *Adam*, *SGD*, or *Adagrad*. However, for this tutorial we will be using the L-BFGS algorithm (`torch.optim.LBFGS`), one of the most well know second-order optimization algorithms for numerical optimization. \n", "\n", "##### Loss Function\n", "As for the loss function, we can also take advantage of PyTorch's pre-defined modules from `torch.nn`, such as the [Cross-Entropy](https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html) or [Mean Squared Error](https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html) losses.\n", "\n", "\n", "**💡 Clarification :** \n", "In classical machine learning, the general rule of thumb is to apply a Cross-Entropy loss to classification tasks, and MSE loss to regression tasks. However, this recommendation is given under the assumption that the output of the classification network is a class probability value in the $[0, 1]$ range (usually this is achieved through a Softmax layer). Because the following example for `EstimatorQNN` does not include such layer, and we don't apply any mapping to the output (the following section shows an example of application of parity mapping with `SamplerQNN`s), the QNN's output can take any value in the range $[-1, 1]$. In case you were wondering, this is the reason why this particular example uses MSELoss for classification despite it not being the norm (but we encourage you to experiment with different loss functions and see how they can impact training results). " ] }, { "cell_type": "code", "execution_count": 6, "id": "following-extension", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "25.535646438598633\n", "22.696760177612305\n", "20.039228439331055\n", "19.687908172607422\n", "19.267208099365234\n", "19.025373458862305\n", "18.154708862304688\n", "17.337854385375977\n", "19.082578659057617\n", "17.073287963867188\n", "16.21839141845703\n", "14.992582321166992\n", "14.929339408874512\n", "14.914533615112305\n", "14.907636642456055\n", "14.902364730834961\n", "14.902134895324707\n", "14.90211009979248\n", "14.902111053466797\n" ] }, { "data": { "text/plain": [ "tensor(25.5356, grad_fn=)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Define optimizer and loss\n", "optimizer = LBFGS(model1.parameters())\n", "f_loss = MSELoss(reduction=\"sum\")\n", "\n", "# Start training\n", "model1.train() # set model to training mode\n", "\n", "\n", "# Note from (https://pytorch.org/docs/stable/optim.html):\n", "# Some optimization algorithms such as LBFGS need to\n", "# reevaluate the function multiple times, so you have to\n", "# pass in a closure that allows them to recompute your model.\n", "# The closure should clear the gradients, compute the loss,\n", "# and return it.\n", "def closure():\n", " optimizer.zero_grad() # Initialize/clear gradients\n", " loss = f_loss(model1(X_), y_) # Evaluate loss function\n", " loss.backward() # Backward pass\n", " print(loss.item()) # Print loss\n", " return loss\n", "\n", "\n", "# Run optimizer step4\n", "optimizer.step(closure)" ] }, { "cell_type": "code", "execution_count": 7, "id": "efficient-bangkok", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Accuracy: 0.8\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Evaluate model and compute accuracy\n", "model1.eval()\n", "y_predict = []\n", "for x, y_target in zip(X, y):\n", " output = model1(Tensor(x))\n", " y_predict += [np.sign(output.detach().numpy())[0]]\n", "\n", "print(\"Accuracy:\", sum(y_predict == y) / len(y))\n", "\n", "# Plot results\n", "# red == wrongly classified\n", "for x, y_target, y_p in zip(X, y, y_predict):\n", " if y_target == 1:\n", " plt.plot(x[0], x[1], \"bo\")\n", " else:\n", " plt.plot(x[0], x[1], \"go\")\n", " if y_target != y_p:\n", " plt.scatter(x[0], x[1], s=200, facecolors=\"none\", edgecolors=\"r\", linewidths=2)\n", "plt.plot([-1, 1], [1, -1], \"--\", color=\"black\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "abstract-parish", "metadata": {}, "source": [ "The red circles indicate wrongly classified data points." ] }, { "cell_type": "markdown", "id": "typical-cross", "metadata": {}, "source": [ "#### B. Classification with PyTorch and `SamplerQNN`\n", "\n", "Linking a `SamplerQNN` to PyTorch requires a bit more attention than `EstimatorQNN`. Without the correct setup, backpropagation is not possible. \n", "\n", "In particular, we must make sure that we are returning a dense array of probabilities in the network's forward pass (`sparse=False`). This parameter is set up to `False` by default, so we just have to make sure that it has not been changed.\n", "\n", "**⚠️ Attention:** \n", "If we define a custom interpret function ( in the example: `parity`), we must remember to explicitly provide the desired output shape ( in the example: `2`). For more info on the initial parameter setup for `SamplerQNN`, please check out the [official qiskit documentation](https://qiskit.org/ecosystem/machine-learning/stubs/qiskit_machine_learning.neural_networks.SamplerQNN.html)." ] }, { "cell_type": "code", "execution_count": 8, "id": "present-operator", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Initial weights: [ 0.0364991 -0.0720495 -0.06001836 -0.09852755]\n" ] } ], "source": [ "# Define feature map and ansatz\n", "feature_map = ZZFeatureMap(num_inputs)\n", "ansatz = RealAmplitudes(num_inputs, entanglement=\"linear\", reps=1)\n", "\n", "# Define quantum circuit of num_qubits = input dim\n", "# Append feature map and ansatz\n", "qc = QuantumCircuit(num_inputs)\n", "qc.compose(feature_map, inplace=True)\n", "qc.compose(ansatz, inplace=True)\n", "\n", "# Define SamplerQNN and initial setup\n", "parity = lambda x: \"{:b}\".format(x).count(\"1\") % 2 # optional interpret function\n", "output_shape = 2 # parity = 0, 1\n", "qnn2 = SamplerQNN(\n", " circuit=qc,\n", " input_params=feature_map.parameters,\n", " weight_params=ansatz.parameters,\n", " interpret=parity,\n", " output_shape=output_shape,\n", ")\n", "\n", "# Set up PyTorch module\n", "# Reminder: If we don't explicitly declare the initial weights\n", "# they are chosen uniformly at random from [-1, 1].\n", "initial_weights = 0.1 * (2 * algorithm_globals.random.random(qnn2.num_weights) - 1)\n", "print(\"Initial weights: \", initial_weights)\n", "model2 = TorchConnector(qnn2, initial_weights)" ] }, { "cell_type": "markdown", "id": "liquid-reviewer", "metadata": {}, "source": [ "For a reminder on optimizer and loss function choices, you can go back to [this section](#Optimizer)." ] }, { "cell_type": "code", "execution_count": 9, "id": "marked-harvest", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.6925069093704224\n", "0.6881508231163025\n", "0.6516683101654053\n", "0.6485998034477234\n", "0.6394743919372559\n", "0.7057444453239441\n", "0.669085681438446\n", "0.766187310218811\n", "0.7188469171524048\n", "0.7919709086418152\n", "0.7598814964294434\n", "0.7028256058692932\n", "0.7486447095870972\n", "0.6890242695808411\n", "0.7760348916053772\n", "0.7892935276031494\n", "0.7556288242340088\n", "0.7058126330375671\n", "0.7203161716461182\n", "0.7030722498893738\n" ] } ], "source": [ "# Define model, optimizer, and loss\n", "optimizer = LBFGS(model2.parameters())\n", "f_loss = CrossEntropyLoss() # Our output will be in the [0,1] range\n", "\n", "# Start training\n", "model2.train()\n", "\n", "# Define LBFGS closure method (explained in previous section)\n", "def closure():\n", " optimizer.zero_grad(set_to_none=True) # Initialize gradient\n", " loss = f_loss(model2(X_), y01_) # Calculate loss\n", " loss.backward() # Backward pass\n", "\n", " print(loss.item()) # Print loss\n", " return loss\n", "\n", "\n", "# Run optimizer (LBFGS requires closure)\n", "optimizer.step(closure);" ] }, { "cell_type": "code", "execution_count": 10, "id": "falling-electronics", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Accuracy: 0.5\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Evaluate model and compute accuracy\n", "model2.eval()\n", "y_predict = []\n", "for x in X:\n", " output = model2(Tensor(x))\n", " y_predict += [np.argmax(output.detach().numpy())]\n", "\n", "print(\"Accuracy:\", sum(y_predict == y01) / len(y01))\n", "\n", "# plot results\n", "# red == wrongly classified\n", "for x, y_target, y_ in zip(X, y01, y_predict):\n", " if y_target == 1:\n", " plt.plot(x[0], x[1], \"bo\")\n", " else:\n", " plt.plot(x[0], x[1], \"go\")\n", " if y_target != y_:\n", " plt.scatter(x[0], x[1], s=200, facecolors=\"none\", edgecolors=\"r\", linewidths=2)\n", "plt.plot([-1, 1], [1, -1], \"--\", color=\"black\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "aboriginal-white", "metadata": {}, "source": [ "The red circles indicate wrongly classified data points." ] }, { "cell_type": "markdown", "id": "scheduled-nicaragua", "metadata": {}, "source": [ "### 2. Regression \n", "\n", "We use a model based on the `EstimatorQNN` to also illustrate how to perform a regression task. The chosen dataset in this case is randomly generated following a sine wave. " ] }, { "cell_type": "code", "execution_count": 11, "id": "amateur-dubai", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Generate random dataset\n", "\n", "num_samples = 20\n", "eps = 0.2\n", "lb, ub = -np.pi, np.pi\n", "f = lambda x: np.sin(x)\n", "\n", "X = (ub - lb) * algorithm_globals.random.random([num_samples, 1]) + lb\n", "y = f(X) + eps * (2 * algorithm_globals.random.random([num_samples, 1]) - 1)\n", "plt.plot(np.linspace(lb, ub), f(np.linspace(lb, ub)), \"r--\")\n", "plt.plot(X, y, \"bo\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "protected-genre", "metadata": {}, "source": [ "#### A. Regression with PyTorch and `EstimatorQNN`" ] }, { "cell_type": "markdown", "id": "lovely-semiconductor", "metadata": {}, "source": [ "The network definition and training loop will be analogous to those of the classification task using `EstimatorQNN`. In this case, we define our own feature map and ansatz, but let's do it a little different." ] }, { "cell_type": "code", "execution_count": 12, "id": "brazilian-adapter", "metadata": {}, "outputs": [], "source": [ "# Construct simple feature map\n", "param_x = Parameter(\"x\")\n", "feature_map = QuantumCircuit(1, name=\"fm\")\n", "feature_map.ry(param_x, 0)\n", "\n", "# Construct simple parameterized ansatz\n", "param_y = Parameter(\"y\")\n", "ansatz = QuantumCircuit(1, name=\"vf\")\n", "ansatz.ry(param_y, 0)\n", "\n", "qc = QuantumCircuit(1)\n", "qc.compose(feature_map, inplace=True)\n", "qc.compose(ansatz, inplace=True)\n", "\n", "# Construct QNN\n", "qnn3 = EstimatorQNN(circuit=qc, input_params=[param_x], weight_params=[param_y])\n", "\n", "# Set up PyTorch module\n", "# Reminder: If we don't explicitly declare the initial weights\n", "# they are chosen uniformly at random from [-1, 1].\n", "initial_weights = 0.1 * (2 * algorithm_globals.random.random(qnn3.num_weights) - 1)\n", "model3 = TorchConnector(qnn3, initial_weights)" ] }, { "cell_type": "markdown", "id": "waiting-competition", "metadata": {}, "source": [ "For a reminder on optimizer and loss function choices, you can go back to [this section](#Optimizer)." ] }, { "cell_type": "code", "execution_count": 13, "id": "bibliographic-consciousness", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "14.947757720947266\n", "2.948650360107422\n", "8.952412605285645\n", "0.37905153632164\n", "0.24995625019073486\n", "0.2483610212802887\n", "0.24835753440856934\n" ] }, { "data": { "text/plain": [ "tensor(14.9478, grad_fn=)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Define optimizer and loss function\n", "optimizer = LBFGS(model3.parameters())\n", "f_loss = MSELoss(reduction=\"sum\")\n", "\n", "# Start training\n", "model3.train() # set model to training mode\n", "\n", "# Define objective function\n", "def closure():\n", " optimizer.zero_grad(set_to_none=True) # Initialize gradient\n", " loss = f_loss(model3(Tensor(X)), Tensor(y)) # Compute batch loss\n", " loss.backward() # Backward pass\n", " print(loss.item()) # Print loss\n", " return loss\n", "\n", "\n", "# Run optimizer\n", "optimizer.step(closure)" ] }, { "cell_type": "code", "execution_count": 14, "id": "timely-happiness", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot target function\n", "plt.plot(np.linspace(lb, ub), f(np.linspace(lb, ub)), \"r--\")\n", "\n", "# Plot data\n", "plt.plot(X, y, \"bo\")\n", "\n", "# Plot fitted line\n", "model3.eval()\n", "y_ = []\n", "for x in np.linspace(lb, ub):\n", " output = model3(Tensor([x]))\n", " y_ += [output.detach().numpy()[0]]\n", "plt.plot(np.linspace(lb, ub), y_, \"g-\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "individual-georgia", "metadata": {}, "source": [ "***\n", "\n", "## Part 2: MNIST Classification, Hybrid QNNs\n", "\n", "In this second part, we show how to leverage a hybrid quantum-classical neural network using `TorchConnector`, to perform a more complex image classification task on the MNIST handwritten digits dataset. \n", "\n", "For a more detailed (pre-`TorchConnector`) explanation on hybrid quantum-classical neural networks, you can check out the corresponding section in the [Qiskit Textbook](https://qiskit.org/textbook/ch-machine-learning/machine-learning-qiskit-pytorch.html)." ] }, { "cell_type": "code", "execution_count": 15, "id": "otherwise-military", "metadata": {}, "outputs": [], "source": [ "# Additional torch-related imports\n", "import torch\n", "from torch import cat, no_grad, manual_seed\n", "from torch.utils.data import DataLoader\n", "from torchvision import datasets, transforms\n", "import torch.optim as optim\n", "from torch.nn import (\n", " Module,\n", " Conv2d,\n", " Linear,\n", " Dropout2d,\n", " NLLLoss,\n", " MaxPool2d,\n", " Flatten,\n", " Sequential,\n", " ReLU,\n", ")\n", "import torch.nn.functional as F" ] }, { "cell_type": "markdown", "id": "bronze-encounter", "metadata": {}, "source": [ "### Step 1: Defining Data-loaders for train and test" ] }, { "cell_type": "markdown", "id": "parliamentary-middle", "metadata": {}, "source": [ "We take advantage of the `torchvision` [API](https://pytorch.org/vision/stable/datasets.html) to directly load a subset of the [MNIST dataset](https://en.wikipedia.org/wiki/MNIST_database) and define torch `DataLoader`s ([link](https://pytorch.org/docs/stable/data.html)) for train and test." ] }, { "cell_type": "code", "execution_count": 16, "id": "worthy-charlotte", "metadata": {}, "outputs": [], "source": [ "# Train Dataset\n", "# -------------\n", "\n", "# Set train shuffle seed (for reproducibility)\n", "manual_seed(42)\n", "\n", "batch_size = 1\n", "n_samples = 100 # We will concentrate on the first 100 samples\n", "\n", "# Use pre-defined torchvision function to load MNIST train data\n", "X_train = datasets.MNIST(\n", " root=\"./data\", train=True, download=True, transform=transforms.Compose([transforms.ToTensor()])\n", ")\n", "\n", "# Filter out labels (originally 0-9), leaving only labels 0 and 1\n", "idx = np.append(\n", " np.where(X_train.targets == 0)[0][:n_samples], np.where(X_train.targets == 1)[0][:n_samples]\n", ")\n", "X_train.data = X_train.data[idx]\n", "X_train.targets = X_train.targets[idx]\n", "\n", "# Define torch dataloader with filtered data\n", "train_loader = DataLoader(X_train, batch_size=batch_size, shuffle=True)" ] }, { "cell_type": "markdown", "id": "completed-spring", "metadata": {}, "source": [ "If we perform a quick visualization we can see that the train dataset consists of images of handwritten 0s and 1s." ] }, { "cell_type": "code", "execution_count": 17, "id": "medieval-bibliography", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "n_samples_show = 6\n", "\n", "data_iter = iter(train_loader)\n", "fig, axes = plt.subplots(nrows=1, ncols=n_samples_show, figsize=(10, 3))\n", "\n", "while n_samples_show > 0:\n", " images, targets = data_iter.__next__()\n", "\n", " axes[n_samples_show - 1].imshow(images[0, 0].numpy().squeeze(), cmap=\"gray\")\n", " axes[n_samples_show - 1].set_xticks([])\n", " axes[n_samples_show - 1].set_yticks([])\n", " axes[n_samples_show - 1].set_title(\"Labeled: {}\".format(targets[0].item()))\n", "\n", " n_samples_show -= 1" ] }, { "cell_type": "code", "execution_count": 18, "id": "structural-chuck", "metadata": {}, "outputs": [], "source": [ "# Test Dataset\n", "# -------------\n", "\n", "# Set test shuffle seed (for reproducibility)\n", "# manual_seed(5)\n", "\n", "n_samples = 50\n", "\n", "# Use pre-defined torchvision function to load MNIST test data\n", "X_test = datasets.MNIST(\n", " root=\"./data\", train=False, download=True, transform=transforms.Compose([transforms.ToTensor()])\n", ")\n", "\n", "# Filter out labels (originally 0-9), leaving only labels 0 and 1\n", "idx = np.append(\n", " np.where(X_test.targets == 0)[0][:n_samples], np.where(X_test.targets == 1)[0][:n_samples]\n", ")\n", "X_test.data = X_test.data[idx]\n", "X_test.targets = X_test.targets[idx]\n", "\n", "# Define torch dataloader with filtered data\n", "test_loader = DataLoader(X_test, batch_size=batch_size, shuffle=True)" ] }, { "cell_type": "markdown", "id": "abroad-morris", "metadata": {}, "source": [ "### Step 2: Defining the QNN and Hybrid Model" ] }, { "cell_type": "markdown", "id": "super-tokyo", "metadata": {}, "source": [ "This second step shows the power of the `TorchConnector`. After defining our quantum neural network layer (in this case, a `EstimatorQNN`), we can embed it into a layer in our torch `Module` by initializing a torch connector as `TorchConnector(qnn)`.\n", "\n", "**⚠️ Attention:**\n", "In order to have an adequate gradient backpropagation in hybrid models, we MUST set the initial parameter `input_gradients` to TRUE during the qnn initialization." ] }, { "cell_type": "code", "execution_count": 19, "id": "urban-purse", "metadata": {}, "outputs": [], "source": [ "# Define and create QNN\n", "def create_qnn():\n", " feature_map = ZZFeatureMap(2)\n", " ansatz = RealAmplitudes(2, reps=1)\n", " qc = QuantumCircuit(2)\n", " qc.compose(feature_map, inplace=True)\n", " qc.compose(ansatz, inplace=True)\n", "\n", " # REMEMBER TO SET input_gradients=True FOR ENABLING HYBRID GRADIENT BACKPROP\n", " qnn = EstimatorQNN(\n", " circuit=qc,\n", " input_params=feature_map.parameters,\n", " weight_params=ansatz.parameters,\n", " input_gradients=True,\n", " )\n", " return qnn\n", "\n", "\n", "qnn4 = create_qnn()" ] }, { "cell_type": "code", "execution_count": 20, "id": "exclusive-productivity", "metadata": {}, "outputs": [], "source": [ "# Define torch NN module\n", "\n", "\n", "class Net(Module):\n", " def __init__(self, qnn):\n", " super().__init__()\n", " self.conv1 = Conv2d(1, 2, kernel_size=5)\n", " self.conv2 = Conv2d(2, 16, kernel_size=5)\n", " self.dropout = Dropout2d()\n", " self.fc1 = Linear(256, 64)\n", " self.fc2 = Linear(64, 2) # 2-dimensional input to QNN\n", " self.qnn = TorchConnector(qnn) # Apply torch connector, weights chosen\n", " # uniformly at random from interval [-1,1].\n", " self.fc3 = Linear(1, 1) # 1-dimensional output from QNN\n", "\n", " def forward(self, x):\n", " x = F.relu(self.conv1(x))\n", " x = F.max_pool2d(x, 2)\n", " x = F.relu(self.conv2(x))\n", " x = F.max_pool2d(x, 2)\n", " x = self.dropout(x)\n", " x = x.view(x.shape[0], -1)\n", " x = F.relu(self.fc1(x))\n", " x = self.fc2(x)\n", " x = self.qnn(x) # apply QNN\n", " x = self.fc3(x)\n", " return cat((x, 1 - x), -1)\n", "\n", "\n", "model4 = Net(qnn4)" ] }, { "cell_type": "markdown", "id": "academic-specific", "metadata": {}, "source": [ "### Step 3: Training" ] }, { "cell_type": "code", "execution_count": 21, "id": "precious-career", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Training [10%]\tLoss: -1.1630\n", "Training [20%]\tLoss: -1.5294\n", "Training [30%]\tLoss: -1.7855\n", "Training [40%]\tLoss: -1.9863\n", "Training [50%]\tLoss: -2.2257\n", "Training [60%]\tLoss: -2.4513\n", "Training [70%]\tLoss: -2.6758\n", "Training [80%]\tLoss: -2.8832\n", "Training [90%]\tLoss: -3.1006\n", "Training [100%]\tLoss: -3.3061\n" ] } ], "source": [ "# Define model, optimizer, and loss function\n", "optimizer = optim.Adam(model4.parameters(), lr=0.001)\n", "loss_func = NLLLoss()\n", "\n", "# Start training\n", "epochs = 10 # Set number of epochs\n", "loss_list = [] # Store loss history\n", "model4.train() # Set model to training mode\n", "\n", "for epoch in range(epochs):\n", " total_loss = []\n", " for batch_idx, (data, target) in enumerate(train_loader):\n", " optimizer.zero_grad(set_to_none=True) # Initialize gradient\n", " output = model4(data) # Forward pass\n", " loss = loss_func(output, target) # Calculate loss\n", " loss.backward() # Backward pass\n", " optimizer.step() # Optimize weights\n", " total_loss.append(loss.item()) # Store loss\n", " loss_list.append(sum(total_loss) / len(total_loss))\n", " print(\"Training [{:.0f}%]\\tLoss: {:.4f}\".format(100.0 * (epoch + 1) / epochs, loss_list[-1]))" ] }, { "cell_type": "code", "execution_count": 22, "id": "spoken-stationery", "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot loss convergence\n", "plt.plot(loss_list)\n", "plt.title(\"Hybrid NN Training Convergence\")\n", "plt.xlabel(\"Training Iterations\")\n", "plt.ylabel(\"Neg. Log Likelihood Loss\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "physical-closure", "metadata": {}, "source": [ "Now we'll save the trained model, just to show how a hybrid model can be saved and re-used later for inference. To save and load hybrid models, when using the TorchConnector, follow the PyTorch recommendations of saving and loading the models." ] }, { "cell_type": "code", "execution_count": 23, "id": "regulation-bread", "metadata": {}, "outputs": [], "source": [ "torch.save(model4.state_dict(), \"model4.pt\")" ] }, { "cell_type": "markdown", "id": "pacific-flour", "metadata": {}, "source": [ "### Step 4: Evaluation" ] }, { "cell_type": "markdown", "id": "fabulous-tribe", "metadata": {}, "source": [ "We start from recreating the model and loading the state from the previously saved file. You create a QNN layer using another simulator or a real hardware. So, you can train a model on real hardware available on the cloud and then for inference use a simulator or vice verse. For a sake of simplicity we create a new quantum neural network in the same way as above." ] }, { "cell_type": "code", "execution_count": 24, "id": "prospective-flooring", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "qnn5 = create_qnn()\n", "model5 = Net(qnn5)\n", "model5.load_state_dict(torch.load(\"model4.pt\"))" ] }, { "cell_type": "code", "execution_count": 25, "id": "spectacular-conservative", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Performance on test data:\n", "\tLoss: -3.3585\n", "\tAccuracy: 100.0%\n" ] } ], "source": [ "model5.eval() # set model to evaluation mode\n", "with no_grad():\n", "\n", " correct = 0\n", " for batch_idx, (data, target) in enumerate(test_loader):\n", " output = model5(data)\n", " if len(output.shape) == 1:\n", " output = output.reshape(1, *output.shape)\n", "\n", " pred = output.argmax(dim=1, keepdim=True)\n", " correct += pred.eq(target.view_as(pred)).sum().item()\n", "\n", " loss = loss_func(output, target)\n", " total_loss.append(loss.item())\n", "\n", " print(\n", " \"Performance on test data:\\n\\tLoss: {:.4f}\\n\\tAccuracy: {:.1f}%\".format(\n", " sum(total_loss) / len(total_loss), correct / len(test_loader) / batch_size * 100\n", " )\n", " )" ] }, { "cell_type": "code", "execution_count": 26, "id": "color-brave", "metadata": { "tags": [ "nbsphinx-thumbnail" ] }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Plot predicted labels\n", "\n", "n_samples_show = 6\n", "count = 0\n", "fig, axes = plt.subplots(nrows=1, ncols=n_samples_show, figsize=(10, 3))\n", "\n", "model5.eval()\n", "with no_grad():\n", " for batch_idx, (data, target) in enumerate(test_loader):\n", " if count == n_samples_show:\n", " break\n", " output = model5(data[0:1])\n", " if len(output.shape) == 1:\n", " output = output.reshape(1, *output.shape)\n", "\n", " pred = output.argmax(dim=1, keepdim=True)\n", "\n", " axes[count].imshow(data[0].numpy().squeeze(), cmap=\"gray\")\n", "\n", " axes[count].set_xticks([])\n", " axes[count].set_yticks([])\n", " axes[count].set_title(\"Predicted {}\".format(pred.item()))\n", "\n", " count += 1" ] }, { "cell_type": "markdown", "id": "prompt-visibility", "metadata": {}, "source": [ "🎉🎉🎉🎉\n", "**You are now able to experiment with your own hybrid datasets and architectures using Qiskit Machine Learning.** \n", "**Good Luck!**" ] }, { "cell_type": "code", "execution_count": 27, "id": "related-wheat", "metadata": {}, "outputs": [ { "data": { "text/html": [ "

Version Information

Qiskit SoftwareVersion
qiskit-terra0.22.0
qiskit-aer0.11.1
qiskit-ignis0.7.0
qiskit0.33.0
qiskit-machine-learning0.5.0
System information
Python version3.7.9
Python compilerMSC v.1916 64 bit (AMD64)
Python builddefault, Aug 31 2020 17:10:11
OSWindows
CPUs4
Memory (Gb)31.837730407714844
Thu Nov 03 09:57:38 2022 GMT Standard Time
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "

This code is a part of Qiskit

© Copyright IBM 2017, 2022.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import qiskit.tools.jupyter\n", "\n", "%qiskit_version_table\n", "%qiskit_copyright" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.13" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }