はじめに
量子ビットの節約は近年のまだ量子ビット数の少ないマシンでは重要です。そのうちでTree Tensor Networkの構造を量子ビットの再利用を使って節約する方法を見てみます。
TTN
木構造をもつTTNによってユニタリ変換を繰り返し、片方の測定を行わず捨てることで、量子ビットの量子状態をどんどん統合していくテクがあります。
QCNNなどに利用されてるTTNやMERAでみられますが、量子回路を再利用することで、より効率的に実行できる回路を見てみます。
上の図の左側は8量子ビットを準備し、順番に計算をしながら量子ビットの数を半分にしながら計算をしています。最初に4つのゲート、残った4量子ビットに2つのゲート、最後に1つのゲートで1量子ビットの測定にまとめています。
上記の右側は量子ビットを捨てて、初期化をすることで、再度利用を行い、初期の量子ビット数を半分に減らしています。
Towards Quantum Machine Learning with Tensor Networks
もちょいみてみます。
Towards Quantum Machine Learning with Tensor Networks
William Huggins,1 Piyush Patil,1 Bradley Mitchell,1 K. Birgitta Whaley,1 and E. Miles Stoudenmire2
1University of California Berkeley, Berkeley, CA 94720 USA
2Center for Computational Quantum Physics, Flatiron Institute, 162 5th Avenue, New York, NY 10010, USA
(Dated: August 1, 2018)
基本的に量子状態を表現するのにテンソルネットワークの木構造を使うことがありますが、下記のような8量子ビットの量子状態は、左側テンソルネットワークで結合次元が4の構造を利用するのに対して、右側の量子回路は量子ビット数を最終的な出力数に揃えて入力数を準備してあげる必要があり、ユニタリ回路を通じて同様の操作を実現します。
引用:https://iopscience.iop.org/article/10.1088/2058-9565/ab4eb5/pdf
次に
引用:https://iopscience.iop.org/article/10.1088/2058-9565/ab4eb5/pdf
TTNの構造を量子回路に落とし込んだものを見てみます。左側は量子回路に相当し、斜線が日本あるところは測定無しになってます。右側では量子状態の期待値を求めるものですが、測定する最後の量子ビット以外は縮約を取り、縮約密度行列ができます。
MPS
行列積状態を実現する量子回路は論文より、
引用:https://iopscience.iop.org/article/10.1088/2058-9565/ab4eb5/pdf
隣接するノードとの結合次元がユニタリ操作を通じて実現されています。
生成TTN
TTNモデルを識別モデルではなく、生成モデルとしてデータ生成に活かすためには、逆方向に実装し、0状態からユニタリ操作を通じて最終的に全ての量子ビットの測定を行ってサンプルを取ります。
引用:https://iopscience.iop.org/article/10.1088/2058-9565/ab4eb5/pdf
生成MPS
MPSを生成モデルとして利用する際にも、同じようにできます。0に量子ビット準備して、ユニタリ回路で実装してきます。最終的に全ての量子ビットのサンプルを取ります。
引用:https://iopscience.iop.org/article/10.1088/2058-9565/ab4eb5/pdf
めちゃんこ便利ですね。実装してみます。
MERA
今回作るモデルはMERAと呼ばれる木構造をしています。U3ゲートとCXゲートを使います。
|0> --[input]--U3--*--
|
|0> --[input]--U3--X--U3--*--
|
|0> --[input]--U3--*-- |
| |
|0> --[input]--U3--X--U3--X--[m]-[expt]-[loss]-[output]
#MERA circuit
def mera(a):
u = Circuit()
u.u3(a[0],a[1],a[2])[0]
u.u3(a[3],a[4],a[5])[1]
u.u3(a[6],a[7],a[8])[2]
u.u3(a[9],a[10],a[11])[3]
u.cx[0,1].cx[2,3]
u.u3(a[12],a[13],a[14])[1]
u.u3(a[15],a[16],a[17])[3]
u.cx[1,3]
return u
from blueqat import Circuit
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import time
%matplotlib inline
np.random.seed(39)
#initial parameters
ainit = [np.random.rand()*np.pi*2 for i in range(18)]
必要な関数を実装します。
#expectation value
def E(sv):
return sum(np.abs(sv[:8])**2)-sum(np.abs(sv[8:])**2)
#loss function
def L(p,t):
return (p-t)**2
#data to gate
def ix(l):
u = Circuit(4)
for i in l:
u.x[i]
return u
データを準備します。トレーニング用のデータと検証用を準備しました。
#training data
inp = [[0,1],[2,3],[0],[3]]
tgt = [1,1,-1,-1]
#validation data
inp_c = [[1],[2],[0,2],[1,3]]
tgt_c = [-1,-1,1,1]
早速開始です。毎回の勾配の計算時に訓練データをランダムで選び最適化をかけます。
#initial parameters
a = ainit.copy()
#result list
ar = []
h = 0.01
e = 0.01
#iterations
nsteps = 800
start = time.time()
for i in range(nsteps):
r = np.random.randint(0,len(inp))
c = ix(inp[r])+mera(a)
loss = L(E(c.run()),tgt[r])
ar.append(loss)
at = [0 for i in range(len(a))]
for j in range(len(a)):
aa = a.copy()
aa[j] += h
loss2 = L(E((ix(inp[r])+mera(aa)).run()),tgt[r])
at[j] = a[j] - e*(loss2 - loss)/h
a = at
plt.plot(ar)
plt.show()
print(time.time() - start)
<Figure size 432x288 with 1 Axes>
5.946179628372192
うまく収束したのでチェックしてみたいと思います。
#training accuracy
np.mean([E((ix(inp[i])+mera(a)).run())/tgt[i] for i in range(len(inp))])
#=>0.9760245973174358
0.9760245973174352
#validation accuracy
np.mean([E((ix(inp_c[i])+mera(a)).run())/tgt_c[i] for i in range(len(inp_c))])
#=>0.9769492668551134
0.9769492668551134
いい感じですね。
MPS
次に作るのモデルはMPSと呼ばれる階段構造をしています。U3ゲートとCXゲートを使います。
|0> --[input]--U3--*--
|
|0> --[input]--U3--X--U3--*--
|
|0> --[input]---------U3--X--U3--*
|
|0> --[input]----------------U3--X--[m]-[expt]-[loss]-[output]
モデルは、
#MPS circuit
def mps(a):
u = Circuit()
u.u3(a[0],a[1],a[2])[0]
u.u3(a[3],a[4],a[5])[1]
u.u3(a[6],a[7],a[8])[2]
u.u3(a[9],a[10],a[11])[3]
u.cx[0,1]
u.u3(a[12],a[13],a[14])[1]
u.cx[1,2]
u.u3(a[15],a[16],a[17])[2]
u.cx[2,3]
return u
早速計算します。その他のパラメータ類は先ほどと同じにします。
start = time.time()
#initial parameters
a = ainit.copy()
#result list
ar = []
h = 0.01
e = 0.01
for i in range(nsteps):
r = np.random.randint(0,len(inp))
loss = L(E((ix(inp[r])+mps(a)).run()),tgt[r])
ar.append(loss)
at = [0 for i in range(len(a))]
for j in range(len(a)):
aa = a.copy()
aa[j] += h
loss2 = L(E((ix(inp[r])+mps(aa)).run()),tgt[r])
at[j] = a[j] - e*(loss2 - loss)/h
a = at
plt.plot(ar)
plt.show()
print(time.time() - start)
<Figure size 432x288 with 1 Axes>
5.819611310958862
7.919758081436157
精度です。
#training accuracy
np.mean([E((ix(inp[i])+mps(a)).run())/tgt[i] for i in range(len(inp))])
#=>0.9697437828925157
0.9700788727843366
#validation accuracy
np.mean([E((ix(inp_c[i])+mps(a)).run())/tgt_c[i] for i in range(len(inp_c))])
#=>0.9696755262709482
0.970138094683916