Skip to content

Instantly share code, notes, and snippets.

@mohzeki222
Created February 23, 2024 00:14
Show Gist options
  • Save mohzeki222/0aaad1328bc5956bfe22b6b11abc6e81 to your computer and use it in GitHub Desktop.
Save mohzeki222/0aaad1328bc5956bfe22b6b11abc6e81 to your computer and use it in GitHub Desktop.
QC4U2_day4_dis.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"private_outputs": true,
"provenance": [],
"gpuType": "V100",
"authorship_tag": "ABX9TyPfpcRHhxq+2hXrL4jP82mg",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/mohzeki222/0aaad1328bc5956bfe22b6b11abc6e81/qc4u2_day4_dis.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"# 識別の問題もマスターしよう!\n",
"\n",
"PyTorchでこれまでは回帰という問題を実践してきました。\n",
"関数で得られた数値を予測するニューラルネットワークを作ることができました。\n",
"これに対して識別という問題があり、与えられたデータがどのグループに属するものなのかを推定するという問題です。\n",
"わかりやすい例では犬の画像を入れたら、犬。\n",
"猫の画像を入れたら、猫と答えるものです。\n",
"このニューラルネットワークを作ることができたら、これまでと同様に量子化色を組み込むことで量子機械学習による識別を実行することができます。\n",
"まず前回と同様にpennylaneを導入しましょう。"
],
"metadata": {
"id": "uGmLZB6KFinL"
}
},
{
"cell_type": "code",
"source": [
"!pip install pennylane"
],
"metadata": {
"id": "1RNzd-fWFgHp"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"!pip install pennylane-lightning pennylane-lightning[gpu] pennylane-qiskit"
],
"metadata": {
"id": "bGPCd7N_FjHo"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"今後パワフルな計算が必要な際にはGPUを利用します。\n",
"そのためには以下のコードでGPU対応をしたシミュレータをインストールする必要があります。"
],
"metadata": {
"id": "veJfawu_M3xe"
}
},
{
"cell_type": "code",
"source": [
"!pip install pennylane custatevec-cu11 pennylane-lightning-gpu"
],
"metadata": {
"id": "dJxR66XJLSYW"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"(これで従来うまくいっていたのですが、どうもgpu利用モードにはならないので原因調査中です)"
],
"metadata": {
"id": "qWpK3VXEUE2-"
}
},
{
"cell_type": "code",
"source": [
"import pennylane as qml\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim"
],
"metadata": {
"id": "ARi4NZIVGBXn"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"次に今回のことはじめに必要なデータセットを呼び出しましょう。\n",
"わかりやすい事例ということで、アヤメの識別に挑戦します。"
],
"metadata": {
"id": "9ynyTw0YF0U4"
}
},
{
"cell_type": "markdown",
"source": [
"scikit-learnと呼ばれるライブラリを利用してアヤメのデータセットを呼び出します。"
],
"metadata": {
"id": "YFVIFGP97Leg"
}
},
{
"cell_type": "code",
"source": [
"from sklearn import datasets\n",
"iris = datasets.load_iris()"
],
"metadata": {
"id": "g78s6rOzeIAt"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"どんなデータなのかをみるには、iris.data,iris.targetを実行してください。"
],
"metadata": {
"id": "C9bKDKhFn7IS"
}
},
{
"cell_type": "code",
"source": [
"iris.data"
],
"metadata": {
"id": "NdjCQ2nhn6Pi"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"iris.target"
],
"metadata": {
"id": "HVcVMr3woKdz"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"3種類のアヤメがあり、それをがく片と花弁の幅と長さ(4つの数値)のみで分類するという問題です。"
],
"metadata": {
"id": "9rr0Wk8QoUZs"
}
},
{
"cell_type": "markdown",
"source": [
"これらのデータをPyTorchで利用できる形に整形しましょう。"
],
"metadata": {
"id": "D_xjyLJOo2Xa"
}
},
{
"cell_type": "code",
"source": [
"n = len(iris.target)\n",
"xdata = iris.data.reshape(n,4)\n",
"tdata = iris.target.reshape(n)\n",
"xdata = torch.tensor(xdata, dtype=torch.float32)\n",
"tdata = torch.tensor(tdata)\n",
"dataset = torch.utils.data.TensorDataset(xdata, tdata)"
],
"metadata": {
"id": "kKQwUbEqoTea"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"同じようにテストデータと訓練データを分けます。\n",
"ここら辺の手順は全く同じようにして実行することができます。"
],
"metadata": {
"id": "4ZaxaPv6pNfG"
}
},
{
"cell_type": "code",
"source": [
"n_train = int(len(dataset) * 0.8)\n",
"n_test = len(dataset) - n_train\n",
"train_set, test_set = torch.utils.data.random_split(dataset, [n_train, n_test])"
],
"metadata": {
"id": "rTcYAlXQoxjc"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"バッチサイズを指定して、train_loaderおよびtest_loaderを用意します。"
],
"metadata": {
"id": "7e_Ju0kspTBT"
}
},
{
"cell_type": "code",
"source": [
"batch_size = 10\n",
"train_loader = torch.utils.data.DataLoader(train_set, batch_size = batch_size, shuffle = True)\n",
"test_loader = torch.utils.data.DataLoader(test_set, batch_size = batch_size, shuffle = False)"
],
"metadata": {
"id": "nqxFfyadpMw3"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"同じようにニューラルネットワークの設定をしましょう。\n",
"ここで注意したいのは入力が4つ\n",
"出力はあやめの3種類のうちどれっぽいかを示す数値を出力するように3個の出力を出させるところです。"
],
"metadata": {
"id": "qZReMQ0cpfkM"
}
},
{
"cell_type": "code",
"source": [
"class NN(nn.Module):\n",
" def __init__(self, n_hidden):\n",
" super().__init__()\n",
" self.fc1 = nn.Linear(4, n_hidden)\n",
" self.fc2 = nn.Linear(n_hidden, 3)\n",
" self.relu = nn.ReLU()\n",
"\n",
" def forward(self, x):\n",
" h = self.fc1(x)\n",
" h = self.relu(h)\n",
" y = self.fc2(h)\n",
" return y"
],
"metadata": {
"id": "6qC7JcrR5R_Z"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"こうした識別の問題ではクロスエントロピーと呼ばれる量を基準にして学習を進めます。\n",
"criterionを変更してこれまでと同様に進めていきましょう"
],
"metadata": {
"id": "5LRXrj2c5zJQ"
}
},
{
"cell_type": "code",
"source": [
"net = NN(2)\n",
"#gpu利用時\n",
"device = torch.device(\"cuda:0\")\n",
"net = net.to(device)"
],
"metadata": {
"id": "s6ufKwO_pXGc"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"criterion = nn.CrossEntropyLoss()\n",
"optimizer = optim.SGD(net.parameters(), lr=0.001)\n",
"#optimizer = optim.Adam(net.parameters(), lr=0.001)"
],
"metadata": {
"id": "xudD6BSR9Gtv"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"lossだけでなく精度も計算結果を残すようにしましょう。"
],
"metadata": {
"id": "IVXZmipB59LM"
}
},
{
"cell_type": "code",
"source": [
"train_loss_value=[]\n",
"train_acc_value=[]\n",
"test_loss_value=[]\n",
"test_acc_value=[]"
],
"metadata": {
"id": "b5TeowFW4-KF"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"学習のループ計算は全く同様にして行います。\n",
"ただ途中でどれだけ正解しているのか、\n",
"試しにラベルを吐き出させてみて、それとデータがいかに一致しているのか精度を調べてみることにしましょう。\n",
"\n",
"ylabel = torch.argmax(ytrain, dim=1)\n",
"\n",
"というところで、ytrain=net(xtrain)で何のデータっぽいのかという数値を出しているのですが、\n",
"それの一番大きいものを選び、ylabelとしています。\n",
"これがylabel==ttrainで比べてみて、等しい数を調べればacc、精度を調べることができます。\n",
"これが100パーセントになることを目指します。"
],
"metadata": {
"id": "x6miuUEH6Bkt"
}
},
{
"cell_type": "code",
"source": [
"Tall = 500"
],
"metadata": {
"id": "r28bGc--8eus"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"for epoch in range(Tall):\n",
" sum_loss = 0\n",
" sum_acc = 0\n",
" for batch in train_loader:\n",
" xtrain,ttrain = batch\n",
" #gpu利用時\n",
" xtrain, ttrain = xtrain.to(device), ttrain.to(device)\n",
" optimizer.zero_grad()\n",
" ytrain = net(xtrain)\n",
" ylabel = torch.argmax(ytrain, dim=1)\n",
" acc = torch.sum(ylabel == ttrain)/len(ttrain)\n",
" loss = criterion(ytrain, ttrain)\n",
" loss.backward()\n",
" optimizer.step()\n",
" sum_loss += loss.item()\n",
" sum_acc += acc.item()\n",
" train_loss_value.append(sum_loss/len(train_loader))\n",
" train_acc_value.append(sum_acc/len(train_loader))\n",
"\n",
" sum_loss = 0\n",
" sum_acc = 0\n",
" for batch in test_loader:\n",
" xtest, ttest = batch\n",
" #gpu利用時\n",
" xtest, ttest = xtest.to(device), ttest.to(device)\n",
" optimizer.zero_grad()\n",
" ytest = net(xtest)\n",
" ylabel = torch.argmax(ytest, dim=1)\n",
" acc = torch.sum(ylabel == ttest)/len(ttest)\n",
" loss = criterion(ytest, ttest)\n",
"\n",
" sum_loss += loss.item()\n",
" sum_acc += acc.item()\n",
" test_loss_value.append(sum_loss/len(test_loader))\n",
" test_acc_value.append(sum_acc/len(test_loader))\n"
],
"metadata": {
"id": "TPqJjahg5Gms"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"回帰の時と同じようにうまく識別ができているかどうか調べてみましょう。\n",
"それこそニューラルネットワークが目覚めるのかどうか。"
],
"metadata": {
"id": "e-1uo8YD8yN1"
}
},
{
"cell_type": "code",
"source": [
"plt.figure(figsize=(6,6))\n",
"plt.plot(range(len(train_loss_value)), train_loss_value)\n",
"plt.plot(range(len(test_loss_value)), test_loss_value)"
],
"metadata": {
"id": "gpRYcBxr5Mfs"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"lossの値は下がっていると嬉しい。\n",
"その一方でacc、精度はテストの点数的で上がっていると嬉しいものです。\n",
"こちらについても表示してみましょう。"
],
"metadata": {
"id": "mCz-6-m185v3"
}
},
{
"cell_type": "code",
"source": [
"plt.figure(figsize=(6,6))\n",
"plt.plot(range(len(train_acc_value)), train_acc_value)\n",
"plt.plot(range(len(test_acc_value)), test_acc_value)\n",
"plt.ylim([0,1.01])"
],
"metadata": {
"id": "EpJyZxTJ5PBU"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# 量子回路を取り込む\n",
"\n",
"こうした識別の問題であっても量子回路を自由にデザインして取り込むことができます。\n",
"今回はreluの代わりに入れてみることにしましょう。"
],
"metadata": {
"id": "eAw532RE946v"
}
},
{
"cell_type": "markdown",
"source": [
"まずは量子回路の設計です。\n"
],
"metadata": {
"id": "s-wXWlan-KoX"
}
},
{
"cell_type": "code",
"source": [
"n_layers = 1\n",
"n_qubits = 2\n",
"weight_shapes = {\"weights\": (n_layers, n_qubits)}\n",
"\n",
"#dev = qml.device('lightning.qubit', wires=n_qubits)\n",
"#gpu利用時\n",
"dev = qml.device('lightning.gpu', wires=n_qubits)\n",
"@qml.qnode(dev)\n",
"def circuitNN(inputs,weights):\n",
" qml.AngleEmbedding(inputs, rotation = \"X\", wires=range(n_qubits))\n",
" qml.BasicEntanglerLayers(weights, rotation = qml.RX, wires=range(n_qubits))\n",
" res = []\n",
" for k in range(n_qubits):\n",
" res.append(qml.expval(qml.PauliZ(k)))\n",
" return res"
],
"metadata": {
"id": "CFkQtJpt-Nr9"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"(warning文章が出てきます)"
],
"metadata": {
"id": "LzQiSK2sQt_L"
}
},
{
"cell_type": "markdown",
"source": [
"前回の回帰の時と同様に量子回路を取り込んでみます。\n",
"AngleEmbeddingでX軸まわりの回転を実行して入力された数値に応じて回転をして、BasicEntanglerLayersによりX軸まわりの回転を実行しつつ制御Zゲートを利用してエンタングルメントを作成しています。"
],
"metadata": {
"id": "lLMtqJwN-YGn"
}
},
{
"cell_type": "code",
"source": [
"class QNN(nn.Module):\n",
" def __init__(self, n_hidden):\n",
" super().__init__()\n",
" self.qnn = qml.qnn.TorchLayer(circuitNN, weight_shapes=weight_shapes)\n",
" self.fc1 = nn.Linear(4, n_hidden)\n",
" self.fc2 = nn.Linear(n_hidden, 3)\n",
"\n",
" def forward(self, x):\n",
" h = self.fc1(x)\n",
" h = self.qnn(h)\n",
" y = self.fc2(h)\n",
" return y"
],
"metadata": {
"id": "BPTEFO1y5x6c"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"これで量子回路を取り込んだニューラルネットワークの完成です。\n",
"RELUとは異なる非線形変換を利用したことになります。\n",
"さらに内部にパラメータを導入していることからある程度柔軟に形を変えることのできる非線形変換ということで、RELUを使うよりは有利です。"
],
"metadata": {
"id": "bdw9RFmZ_eT0"
}
},
{
"cell_type": "code",
"source": [
"qnet = QNN(2)\n",
"#gpu利用時\n",
"device = torch.device(\"cuda:0\")\n",
"qnet = qnet.to(device)"
],
"metadata": {
"id": "PdalXTG7-WrG"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"criterion = nn.CrossEntropyLoss()\n",
"optimizer = optim.SGD(qnet.parameters(), lr=0.001)\n",
"#optimizer = optim.Adam(net.parameters(), lr=0.001)"
],
"metadata": {
"id": "C-MtWEloGilP"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"最適化する手法を変えずに同じように実行することとしましょう。\n",
"また途中の学習結果を比較するために、学習の記録をする部分は変更してみましょう。"
],
"metadata": {
"id": "Q-787TbE_ury"
}
},
{
"cell_type": "code",
"source": [
"qtrain_loss_value=[]\n",
"qtrain_acc_value=[]\n",
"qtest_loss_value=[]\n",
"qtest_acc_value=[]"
],
"metadata": {
"id": "uEcIrtSJ_rWe"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"同じように何度か学習を実行してください。\n",
"おそらくGPUを利用しないとなかなか計算時間がかかることと思います。\n"
],
"metadata": {
"id": "DhcvbGRGFGD6"
}
},
{
"cell_type": "code",
"source": [
"for epoch in range(Tall):\n",
" sum_loss = 0\n",
" sum_acc = 0\n",
" for batch in train_loader:\n",
" xtrain,ttrain = batch\n",
" #gpu利用時\n",
" xtrain, ttrain = xtrain.to(device), ttrain.to(device)\n",
" optimizer.zero_grad()\n",
" ytrain = qnet(xtrain)\n",
" ylabel = torch.argmax(ytrain, dim=1)\n",
" acc = torch.sum(ylabel == ttrain)/len(ttrain)\n",
" loss = criterion(ytrain, ttrain)\n",
" loss.backward()\n",
" optimizer.step()\n",
" sum_loss += loss.item()\n",
" sum_acc += acc.item()\n",
" qtrain_loss_value.append(sum_loss/len(train_loader))\n",
" qtrain_acc_value.append(sum_acc/len(train_loader))\n",
"\n",
" sum_loss = 0\n",
" sum_acc = 0\n",
" for batch in test_loader:\n",
" xtest, ttest = batch\n",
" #gpu利用時\n",
" xtest, ttest = xtest.to(device), ttest.to(device)\n",
" optimizer.zero_grad()\n",
" ytest = qnet(xtest)\n",
" ylabel = torch.argmax(ytest, dim=1)\n",
" acc = torch.sum(ylabel == ttest)/len(ttest)\n",
" loss = criterion(ytest, ttest)\n",
"\n",
" sum_loss += loss.item()\n",
" sum_acc += acc.item()\n",
" qtest_loss_value.append(sum_loss/len(test_loader))\n",
" qtest_acc_value.append(sum_acc/len(test_loader))\n"
],
"metadata": {
"id": "PQjTI70l_4U0"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"plt.figure(figsize=(6,6))\n",
"plt.plot(range(len(train_acc_value)), train_acc_value)\n",
"plt.plot(range(len(test_acc_value)), test_acc_value)\n",
"plt.plot(range(len(qtrain_acc_value)), qtrain_acc_value)\n",
"plt.plot(range(len(qtest_acc_value)), qtest_acc_value)\n",
"plt.ylim([0,1.01])"
],
"metadata": {
"id": "Ohwun-LIAAYA"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# 画像の識別もやってみよう\n",
"\n",
"まずそのために準備されたPyTorchのライブラリとしてtorchbisionをインポートします。"
],
"metadata": {
"id": "xpidXcRWGnMs"
}
},
{
"cell_type": "code",
"source": [
"import torchvision"
],
"metadata": {
"id": "qLsLQy8jA8Pm"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"まず初めに公開データセットで一番有名なMNISTをダウンロードしてみましょう。 訓練データセットを呼び出し、その際にそれをtorch特有のTensor形式に変換します。 そのためにどんな変形をするのかを宣言しておきます。"
],
"metadata": {
"id": "YknUvkFJGvT5"
}
},
{
"cell_type": "code",
"source": [
"trans = torchvision.transforms.ToTensor()"
],
"metadata": {
"id": "fwME-PL9Gt5P"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"この変換規則を宣言したあとは、まずは訓練データセットをダウンロードしましょう。\n",
"\n"
],
"metadata": {
"id": "6DK-AsiuGx81"
}
},
{
"cell_type": "code",
"source": [
"train_set = torchvision.datasets.MNIST(root = 'path', train = True, download = True, transform = trans)"
],
"metadata": {
"id": "ZgEIuALjGwig"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"torchvisionのdatasetsにはいくつかのデータセットへのダウンロードや前処理をするための関数が用意されています。 train=Trueで訓練データセットを用意します。 download=Trueでダウンロードをするということもオプションで選択しています。transformでどんな変形をするのか、事前に宣言したものに基づき変形します。"
],
"metadata": {
"id": "KYUqD0gxG0qk"
}
},
{
"cell_type": "markdown",
"source": [
"どんな画像があるのかをみるとイメージがつくと思います。"
],
"metadata": {
"id": "h4AwkY-zG4Gf"
}
},
{
"cell_type": "code",
"source": [
"plt.imshow(train_set[1][0][0])"
],
"metadata": {
"id": "rMY3nd60GzLT"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"このような形でいくつかの手描き文字がデータセットとして用意されています。最初の数字がデータ番号、2つ目の数字が何番の数字であるのかを教えてくれる正解ラベル、3つ目の数字が画像のRGBチャンネルです。"
],
"metadata": {
"id": "vBDODBBjG8RR"
}
},
{
"cell_type": "markdown",
"source": [
"前回のsinカーブの時のデータと同様にDataLoaderを利用し てニューラルネットワークに入れてみましょう。batch_sizeを適当に設定して準備完了です。"
],
"metadata": {
"id": "KR9EiSYcG9tz"
}
},
{
"cell_type": "code",
"source": [
"batch_size = 100\n",
"train_loader = torch.utils.data.DataLoader(train_set, batch_size = batch_size, shuffle = True)"
],
"metadata": {
"id": "XjBLA6HjG5d2"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"もちろん訓練データに対して、テストデータも必要ですからその準備もしておきましょう。MNISTについては次のように準備することができます。"
],
"metadata": {
"id": "rrwjeZPwHDhw"
}
},
{
"cell_type": "code",
"source": [
"test_set = torchvision.datasets.MNIST(root = 'path', train = False, download = True, transform = trans)\n",
"test_loader = torch.utils.data.DataLoader(test_set, batch_size = 100, shuffle = False)"
],
"metadata": {
"id": "3eP-vgpqHCgr"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"ここまででデータの準備が完了しましたので、あとはニューラルネットワークの設定です。"
],
"metadata": {
"id": "Obt1P0GnHG1t"
}
},
{
"cell_type": "code",
"source": [
"class NN(nn.Module):\n",
" def __init__(self):\n",
" super(NN, self).__init__()\n",
" #準備・使う関数の設定を書く\n",
" self.relu = nn.ReLU()\n",
" self.pool = nn.MaxPool2d(2, stride=2)\n",
" #Conv2d(in_channel,out_channel,kernel_size)\n",
" self.conv1 = nn.Conv2d(1,16,3)\n",
" self.conv2 = nn.Conv2d(16,32,3)\n",
"\n",
" self.fc1 = nn.Linear(32 * 5 * 5, 120)\n",
" self.fc2 = nn.Linear(120, 10)\n",
"\n",
" def forward(self, x):\n",
" x = self.conv1(x)\n",
" x = self.relu(x)\n",
" x = self.pool(x)\n",
" x = self.conv2(x)\n",
" x = self.relu(x)\n",
" x = self.pool(x)\n",
" #縦に並べる\n",
" x = x.reshape(-1, 32 * 5 * 5)\n",
" x = self.fc1(x)\n",
" x = self.relu(x)\n",
" x = self.fc2(x)\n",
" return x"
],
"metadata": {
"id": "BUceGGpmHGV9"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"この画像のための畳み込みは少々面倒ですが基本的な形は一緒です。 必要に応じて複雑なニューラルネットワークを用意します。\n",
"\n",
"それではここで作ったニューラルネットワークを呼び出しましょう。"
],
"metadata": {
"id": "6RMk440-INp2"
}
},
{
"cell_type": "code",
"source": [
"net = NN()\n",
"#gpu利用時\n",
"device = torch.device(\"cuda:0\")\n",
"net = net.to(device)"
],
"metadata": {
"id": "kf4tz1w7ILu-"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"MNISTの問題は識別の問題ですので、クロスエントロピーというものを用いて予測の正確さを調べます。"
],
"metadata": {
"id": "tIQXng3bIRzE"
}
},
{
"cell_type": "code",
"source": [
"criterion = nn.CrossEntropyLoss()\n",
"optimizer = optim.SGD(net.parameters(), lr=0.001)"
],
"metadata": {
"id": "Xtf-DUTPIO6v"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"訓練中に次第に性能が向上していく様子を見ていくために空リストを用意しましょう。"
],
"metadata": {
"id": "-oHExTVqIUO7"
}
},
{
"cell_type": "code",
"source": [
"train_loss_value=[]\n",
"train_acc_value=[]\n",
"test_loss_value=[]\n",
"test_acc_value=[]"
],
"metadata": {
"id": "BVoHQ0a9ISOP"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"lossだけでなく精度を調べるためにacc(accuracy)も用意します。"
],
"metadata": {
"id": "hAL-Grf1IXow"
}
},
{
"cell_type": "code",
"source": [
"Tall = 10"
],
"metadata": {
"id": "JuG4psbxIWBR"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"for epoch in range(Tall):\n",
" sum_loss = 0\n",
" sum_acc = 0\n",
" for batch in train_loader:\n",
" xtrain,ttrain = batch\n",
" #gpu利用時\n",
" xtrain, ttrain = xtrain.to(device), ttrain.to(device)\n",
" optimizer.zero_grad()\n",
" ytrain = net(xtrain)\n",
" ylabel = torch.argmax(ytrain, dim=1)\n",
" acc = torch.sum(ylabel == ttrain)/len(ttrain)\n",
" loss = criterion(ytrain, ttrain)\n",
" loss.backward()\n",
" optimizer.step()\n",
" sum_loss += loss.item()\n",
" sum_acc += acc.item()\n",
" train_loss_value.append(sum_loss/len(train_loader))\n",
" train_acc_value.append(sum_acc/len(train_loader))\n",
"\n",
" sum_loss = 0\n",
" sum_acc = 0\n",
" for batch in test_loader:\n",
" xtest, ttest = batch\n",
" #gpu利用時\n",
" xtest, ttest = xtest.to(device), ttest.to(device)\n",
" optimizer.zero_grad()\n",
" ytest = net(xtest)\n",
" ylabel = torch.argmax(ytest, dim=1)\n",
" acc = torch.sum(ylabel == ttest)/len(ttest)\n",
" loss = criterion(ytest, ttest)\n",
"\n",
" sum_loss += loss.item()\n",
" sum_acc += acc.item()\n",
" test_loss_value.append(sum_loss/len(test_loader))\n",
" test_acc_value.append(sum_acc/len(test_loader))\n"
],
"metadata": {
"id": "xJnR4jgCIY-M"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"学習の様子を表示するのもこれまでと同様に実行できます。"
],
"metadata": {
"id": "1keAN204KFA0"
}
},
{
"cell_type": "code",
"source": [
"plt.figure(figsize=(6,6))\n",
"plt.plot(range(len(train_loss_value)), train_loss_value)\n",
"plt.plot(range(len(test_loss_value)), test_loss_value)"
],
"metadata": {
"id": "B7uNuBOaIc72"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"lossが順調に下がっていることを確認したら精度についても確認してみましょう。 要するに点数です。"
],
"metadata": {
"id": "CC27tT_rKJar"
}
},
{
"cell_type": "code",
"source": [
"plt.figure(figsize=(6,6))\n",
"plt.plot(range(len(train_acc_value)), train_acc_value)\n",
"plt.plot(range(len(test_acc_value)), test_acc_value)\n",
"plt.ylim([0,1.01])"
],
"metadata": {
"id": "3vvXzcabKBDO"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"比較的単純なモデルでもMNISTの識別はできます。"
],
"metadata": {
"id": "fgWxkwy_KNBv"
}
},
{
"cell_type": "markdown",
"source": [
"# 量子回路で適当にMNISTを識別してみよう\n",
"\n",
"それではこれまでと同様に量子回路を導入してMNISTを識別してみましょう。"
],
"metadata": {
"id": "vtDydGltKLNp"
}
},
{
"cell_type": "markdown",
"source": [
"どうしても量子回路の量子ビット数を多くすることは得策ではないので次のようなものを考えてみます。"
],
"metadata": {
"id": "TxwnkimMKdh3"
}
},
{
"cell_type": "code",
"source": [
"n_layers = 1\n",
"n_qubits = 2\n",
"weight_shapes = {\"weights\": (n_layers, n_qubits)}\n",
"\n",
"#dev = qml.device('lightning.qubit', wires=n_qubits)\n",
"#gpu利用時\n",
"dev = qml.device('lightning.gpu', wires=n_qubits)\n",
"@qml.qnode(dev)\n",
"def circuitNN(inputs,weights):\n",
" qml.AngleEmbedding(inputs, rotation = \"X\", wires=range(n_qubits))\n",
" qml.BasicEntanglerLayers(weights, rotation = qml.RX, wires=range(n_qubits))\n",
" res = []\n",
" for k in range(n_qubits):\n",
" res.append(qml.expval(qml.PauliZ(k)))\n",
" return res"
],
"metadata": {
"id": "n5G6brRTKDM9"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"class QNN(nn.Module):\n",
" def __init__(self,n_hidden):\n",
" super().__init__()\n",
" #準備・使う関数の設定を書く\n",
" self.qnn = qml.qnn.TorchLayer(circuitNN, weight_shapes=weight_shapes)\n",
" self.fc1 = nn.Linear(28*28, n_hidden)\n",
" self.fc2 = nn.Linear(n_hidden, 10)\n",
"\n",
" def forward(self, x):\n",
" x = x.reshape(-1, 1 * 28 * 28)\n",
" h = self.fc1(x)\n",
" h = self.qnn(h)\n",
" x = self.fc2(h)\n",
" return x"
],
"metadata": {
"id": "lS6AZ3V4Kixk"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"MNISTの画像データは、1チャンネル、28*28のサイズなので、それを列に指定すれば(x.reshape(-1, 1 * 28 * 28))行としてデータ数に整形したデータにすることができます。\n",
"fc1で変形した後にqnn、つまり量子回路で変換したものを考えてみましょう。"
],
"metadata": {
"id": "_A4lCVj4RFLc"
}
},
{
"cell_type": "code",
"source": [
"qnet = QNN(2)\n",
"#gpu利用時\n",
"device = torch.device(\"cuda:0\")\n",
"qnet = qnet.to(device)"
],
"metadata": {
"id": "-ZSQOmFDQrSk"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"量子回路を導入したニューラルネットワークを用意したらあとは学習を実行するだけです。\n",
"その方法は今までと変わらないやり方ですから復讐と思って実行してみましょう。\n",
"criterionとしてCrossEntropyLoss()を実行して、最適化手法としてSGDやAdamを利用します。"
],
"metadata": {
"id": "Xn2MY3HgSgnV"
}
},
{
"cell_type": "code",
"source": [
"criterion = nn.CrossEntropyLoss()\n",
"optimizer = optim.SGD(qnet.parameters(), lr=0.001)\n",
"#optimizer = optim.Adam(net.parameters(), lr=0.001)"
],
"metadata": {
"id": "0SNFO0UKQ8hy"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"比較のために訓練中の誤差や精度を記録するリストを用意します。"
],
"metadata": {
"id": "kat65gc6SwsO"
}
},
{
"cell_type": "code",
"source": [
"qtrain_loss_value=[]\n",
"qtrain_acc_value=[]\n",
"qtest_loss_value=[]\n",
"qtest_acc_value=[]"
],
"metadata": {
"id": "82N9DK-nQ-ji"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"学習の実行はいつも通りです。\n",
"Tallの回数分だけ、内部で量子回路を利用した学習を実行しましょう。"
],
"metadata": {
"id": "5sVfTR0NS1AI"
}
},
{
"cell_type": "code",
"source": [
"for epoch in range(Tall):\n",
" sum_loss = 0\n",
" sum_acc = 0\n",
" for batch in train_loader:\n",
" xtrain,ttrain = batch\n",
" #gpu利用時\n",
" xtrain, ttrain = xtrain.to(device), ttrain.to(device)\n",
" optimizer.zero_grad()\n",
" ytrain = qnet(xtrain)\n",
" ylabel = torch.argmax(ytrain, dim=1)\n",
" acc = torch.sum(ylabel == ttrain)/len(ttrain)\n",
" loss = criterion(ytrain, ttrain)\n",
" loss.backward()\n",
" optimizer.step()\n",
" sum_loss += loss.item()\n",
" sum_acc += acc.item()\n",
" qtrain_loss_value.append(sum_loss/len(train_loader))\n",
" qtrain_acc_value.append(sum_acc/len(train_loader))\n",
"\n",
" sum_loss = 0\n",
" sum_acc = 0\n",
" for batch in test_loader:\n",
" xtest, ttest = batch\n",
" #gpu利用時\n",
" xtest, ttest = xtest.to(device), ttest.to(device)\n",
" optimizer.zero_grad()\n",
" ytest = qnet(xtest)\n",
" ylabel = torch.argmax(ytest, dim=1)\n",
" acc = torch.sum(ylabel == ttest)/len(ttest)\n",
" loss = criterion(ytest, ttest)\n",
"\n",
" sum_loss += loss.item()\n",
" sum_acc += acc.item()\n",
" qtest_loss_value.append(sum_loss/len(test_loader))\n",
" qtest_acc_value.append(sum_acc/len(test_loader))\n"
],
"metadata": {
"id": "LaxX6SaURCGH"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"学習の結果もいつものとおりやってみましょう。"
],
"metadata": {
"id": "d49QEWqnT7pb"
}
},
{
"cell_type": "code",
"source": [
"plt.figure(figsize=(6,6))\n",
"plt.plot(range(len(train_acc_value)), train_acc_value)\n",
"plt.plot(range(len(test_acc_value)), test_acc_value)\n",
"plt.plot(range(len(qtrain_acc_value)), qtrain_acc_value)\n",
"plt.plot(range(len(qtest_acc_value)), qtest_acc_value)\n",
"plt.ylim([0,1.01])"
],
"metadata": {
"id": "sHrc7AXIREDo"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [],
"metadata": {
"id": "KnSqAbYtRir3"
},
"execution_count": null,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment