Help us understand the problem. What is going on with this article?

pytorch / tensorflow + blueqatで量子回路の自動微分

はじめに

今後量子機械学習が流行ると思います。既存の量子アニーリングや量子ゲートのVQE/QAOAを拡張する形でアプリケーションが加速すると思います。

勾配計算

量子ゲートの変分計算を最適化する場合、量子回路の中にパラメータ回路があるのですが、それは今までブラックボックス最適や局所最適化アルゴリズムを使う際にあまり深くは考えていませんでした。

今回、数値微分を使って量子回路の勾配計算するものを手作業で作ってみましたが、

量子コンピュータ SGD / momentum SGD / Adagrad でのry回転ゲートのパラメータ最適化
https://qiita.com/YuichiroMinato/items/09967e4ee304bbd3d5ff

pytorchなど深層学習のツールを取り込みながら量子回路をいじるのが増えそうです。そんなか、pytorchの特徴であるテンソルの自動微分を量子回路に適用してみました。

量子回路

量子回路は通常の量子コンピュータだと、Xゲートとか、Hゲートとかを想像しますが、NISQと呼ばれる近年の量子コンピュータでは変分回路と呼ばれる角度パラメータ付きの量子回路を角度で最適化するのが主流です。

今回はこの角度パラメータを最適化するのに、pytorchを使ってみました。

勾配計算

数値微分を使って、最終的に求めた値に対してパラメータで偏微分を行い、その偏微分の勾配を適用して最適化をします。最適化手法は様々ありますので、それは別の機会にみます。

pytorchを使った自動微分概要

勾配計算の概要は、

1、量子回路のパラメータを把握する
2、パラメータ化量子回路から測定値の期待値を求める
3、測定値の期待値とターゲット値から損失関数を利用する
4、損失関数が小さくなるように数値微分と勾配法を使って更新

となります。パラメータから最終の損失関数に至るまでは多くのステップがありますが、それぞれの関数の微分係数を持つことで断続的に勾配の値を持つことができます。

pytorchにおけるtensor

量子回路のゲート操作をテンソル操作として認識することによって自動微分が可能になります。numpyやcuda tensorとも親和性が高いのでpytorchは導入がしやすいです。

状態ベクトルは、通常のベクトルとしてテンソルで扱えます。

x = torch.tensor([1.,0.])

また、各ゲートも行列なのでテンソルとして自然に扱えます。

測定は状態ベクトルから期待値を得られます。
損失関数は期待値から計算できます。

それらの操作を断続的に扱うことでpytorchで量子回路を扱うことができます。

backward

損失関数は((期待値)-(ターゲット))**2と、なるのでそれを利用して、

loss.backward()

と勾配を計算できます。実際に勾配を確認するときには、

a_grad = angle.grad.item()

これを利用して、最適化を進めることができます。

85484E13-C443-497C-8A74-201BCD56BB1C.png

損失関数を使わず、変分原理とpytorchで計算

従来のVQEやQAOAのように、変分原理を使って計算をすることもできます。その際には期待値をそのまま使います。-1に最適化されます。

import matplotlib.pyplot as plt
import torch.optim as optim
import numpy as np
%matplotlib inline

x = torch.tensor([1., 0.])
a = torch.tensor([0.2],requires_grad=True)
arr = []

#the first variable is list of paramters.
op = optim.Adam([a],lr=0.05)

for _ in range(100):
    y = [[torch.cos(a/2),-torch.sin(a/2)],[torch.sin(a/2),torch.cos(a/2)]]
    z = [x[0]*y[0][0]+x[1]*y[0][1],x[0]*y[1][0]+x[1]*y[1][1]]

    expt = torch.abs(z[0])**2 - torch.abs(z[1])**2
    arr.append(expt)

    op.zero_grad()
    expt.backward()
    op.step()

plt.plot(arr)
plt.show()

FADFACA2-5C44-4328-A7E6-3DF265E10400.png

今後の展開

厳密なVQEやQAOAを行うことも、損失関数を使うことも自動微分を利用してできました。今後はよりblueqatで回路の使いやすい形を提案していきたいと思います。

pytorchの簡単使い方

今後使う予定もあるので、まとめます。
初心者です。めちゃ簡単にやります。
量子コンピュータを想定してある角度を最適化するものをやってみたいので、とても簡単なネットワークを作りたいです。

input1 / linear10 / output3

でやってみたいと思います。

import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
%matplotlib inline

#モデル適当に
model = nn.Sequential()
model.add_module('fc1', nn.Linear(1, 12))
model.add_module('relu', nn.ReLU())
model.add_module('fc2', nn.Linear(12, 2))

#最適化選ぶ
optimizer = optim.Adam(model.parameters(), lr=0.1)

#損失関数選ぶ
lossf = nn.MSELoss()

#入力値とターゲット
input = torch.Tensor([[0],[1]])
target = torch.Tensor([[1,2],[4,5]])

model.train()
arr = []

#トレーニング
for _ in range(100):
  loss = lossf(model(input), target)
  arr.append(loss)
  optimizer.zero_grad()
  loss.backward()
  optimizer.step()

plt.plot(arr)
plt.show()

D9D3F296-8CAF-4B5A-9EB1-9AA835789905.png

とりあえず収束しました。

optuna

VQEを使って簡単な回路の最適化をしてみますが、なるべく早く計算を終わらせたいので、pytorchの勾配計算をoptunaを使って最適化します。また、回路自体はNISQ計算のVQEを使います。

ハミルトニアン

ハミルトニアンは、

H = -Z_0 - Z_0Z_1

を想定します。最小値は-2になりそうです。pytorchを使って計算してみます。

量子回路

量子回路はansatzとして、

Circuit().ry(a)[0].rz(b)[0].cx[0,1]

を使いたいと思います。

VQE

普通にblueqatでやってみると、適当にansatzを作って期待値からハミルトニアンの最小値の期待値は、

import numpy as np
from blueqat import Circuit
from blueqat.pauli import X, Y, Z, I
from blueqat.vqe import AnsatzBase, Vqe

class OneQubitAnsatz(AnsatzBase):
    def __init__(self, hamiltonian):
        super().__init__(hamiltonian.to_expr(), 2)
        self.step = 1

    def get_circuit(self, params):
        a, b = params
        return Circuit().ry(a)[0].rz(b)[0].cx[0,1]

h = -Z(0) - Z(0)*Z(1)
runner = Vqe(OneQubitAnsatz(h))
result = runner.run()

print('Result by VQE')
print(runner.ansatz.get_energy(result.circuit, runner.sampler))
Result by VQE
-1.99999999994664

想定通りのだいたい-2程度になりました。

pytorchで実装

ちょっとコードが整理できてないのですが、

momentum SGDを使って、

1024360A-A32A-4344-9238-3B4D7E1D38E8.png

こんな感じになりました。期待値は

-1.999962329864502

となりました。今blueqatからpytorchへの変換ツールを作っているので出来上がったら公開予定です。

optuna

続いてoptunaでハイパラ最適化して見ました。最適化のアルゴリズムを比較して見ました。

TRIAL_SIZE = 100

で行いました。結果は、

study.best_params

{'optimizer': 'Adam',
 'weight_decay': 0.000456965918794761,
 'adam_lr': 0.09922399869322862}

でしたので、

op = optim.Adam([a,b], lr=study.best_params['adam_lr'], weight_decay=study.best_params['weight_decay'])

を設定して、

1A4F5E27-47E5-477C-A2A6-B99F33C942FB.png

となり、期待値は

-1.9999990463256836

となりました。今回は一定の精度を決めながらハイパラ最適化を行ったので、狙った通りの値が効率的に得られてとても良かったです。

Tensorflow

Tensorflow2のGradientTapeを使って同じことをしてみます。バックエンドはtensorflowのテンソル計算を量子コンピュータゲートシミュレータとして使っています。

import tensorflow as tf
import matplotlib.pyplot as plt
%matplotlib inline

def Ry(a):
    return [[tf.math.cos(a/2),-tf.math.sin(a/2)],[tf.math.sin(a/2),tf.math.cos(a/2)]]

def exptZ(x,a):
    z = tf.tensordot(x,Ry(a),1)
    return tf.abs(z[0])**2 - tf.abs(z[1])**2

a = tf.Variable(.2)
x = tf.constant([1.,0.])

opt = tf.keras.optimizers.SGD(lr=.1)
arr= []

expt = lambda : exptZ(x,a)

for _ in range(100):
    arr.append(expt().numpy())
    opt.minimize(expt, var_list=[a])

plt.plot(arr)
plt.show()

print(arr[-1])

optimizerはSGDでlr=0.1と設定、
Ryゲートを変数パラメータとして、VQEを行いました。
損失関数は使わず、量子ビットのZ測定の期待値を最適化したため、最小値-1になっています。

8FA407BC-2420-438F-B4F9-C047AC4B0031.png

-0.99999976

となりました。

今後

フロントエンドの量子回路でVQEではない、もうちょっと新しめのansatzを使って見たいと思います。コードはライブラリにして公開しようと思います。

mdrft
量子コンピュータのアプリケーション、ミドルウェア、ハードウェアをフルスタックで開発
https://blueqat.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした