@yuichirominato 2018.12.31更新 337views

Wildqatにサンプリング機能をつけてボルツマンマシンを準備する

DBM QUBO RBM 機械学習 深層学習 量子アニーリング

はじめに

アニーリングのQUBOやイジングに慣れてきた方も増えてきました。その際になんども計算を行って計算結果を欲しいという方もいると思いますので、サンプリングの機能を作りました。これによって同じ問題を何回も繰り返し計算して計算結果の分布が取れます。

Wildqatの導入の仕方

こちらはpipで簡単に入れられます。

pip3 install wildqat

簡単な例題で普通の使い方。モジュールを読み込み、インスタンスを用意して、QUBOの式を用意します。QUBOは上三角行列で量子アニーリングマシンを実行するための問題のパラメータが含まれています。今回はsaで実行してみます。

from wildqat import *
a = opt()
a.qubo = [[1,-1,-1],[0,1,-1],[0,0,1]]
a.run() 

[0, 0, 0]

print(a.E[-1])                                                          
0.0

元の式から計算された量子ビットの値と全体のエネルギー値が戻ってきます。これを使って簡単に計算ができます。このように簡単にできます。

サンプリング

簡単です。実行時にshots=100のように試行回数を指定します。100個答えが出ます。下記はWildqatのsel関数を使ってQUBOで3量子ビットから1量子ビット選ぶ問題を作ります。地味に以前のfloatのarrayからintのlistに変わってます。

from wildqat import *
a = opt()
a.qubo = sel(3,1)
a.run(shots=100) 

[[0, 1, 0],
 [0, 0, 1],
 [0, 1, 0],
 [1, 0, 0],
 [1, 0, 0],
 [0, 0, 1],
 [0, 1, 0],
 ...

こちらの分布を見てます。分布を見るにはcounter()を使います。

result = a.run(shots=100)
counter(result)

Counter({'001': 37, '010': 25, '100': 38})

この答えが出てくる確率計算によって機械学習に応用ができたりします。オプションはshotsの数とサンプリングの速度。あとは計算途中経過の表示です。

from wildqat import *
a = opt()
a.qubo = sel(10,1) #10量子ビットから1量子ビット選ぶ                                                                                                                  

result = a.run(shots=100,sampler="fast",verbose=True) 

0 : [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
1 : [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
2 : [0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
3 : [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
4 : [0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
5 : [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
6 : [0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
7 : [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
8 : [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
9 : [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
10 : [0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
11 : [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
12 : [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
13 : [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
14 : [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
15 : [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
16 : [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
...

counter(result)

Counter({'0010000000': 12,
         '0000001000': 15,
         '0000010000': 9,
         '0000000001': 12,
         '0000000100': 11,
         '0000000010': 3,
         '1000000000': 13,
         '0000100000': 11,
         '0100000000': 7,
         '0001000000': 7})

多少便利になりました。

ボルツマンマシンの実行

「D-Waveで深層学習の基礎となるRBMのボルツマン学習を実行してみた」
https://blog.mdrft.com/post/258

こちらの記事を参考にWildqatで機械学習してみます。

モデルはRBMでつかうQUBOは$$Q=[[-1,2],[0,-1]]$$にしてみます。

from wildqat import *
a = opt()
a.qubo = [[-1,2],[0,-1]]
result = a.run(shots=100,sampler="fast")
counter(result)                                                                                                                            

Counter({'10': 60, '01': 40})

01と10が半分ずつくらいでました。ここですこしセッティングを変えてサンプリングの温度を決めてみます。taregtTの引数に1をいれるとアニーリングの最終温度を1Kに設定できます。実行してみると

from wildqat import * 
a = opt() 
a.qubo = [[-1,2],[0,-1]] 
result = a.run(shots=100,targetT=1,sampler="fast") 
counter(result)   

Counter({'01': 41, '11': 16, '10': 31, '00': 12})

こちらででました。確率分布は理想的な0.37/0.13/0.37/0.13に近くなりました。こちらは機械学習に利用できそうです。

機械学習に向けて

ニューラルネットワークの構成に関して、結合荷重とバイアスの値を求めていきますが、いくつかQUBOで使えそうなものを用意しました。まずはランダムで結合荷重とバイアスを決めてQUBOを生成します。rands(N)は0から1の係数でNxNサイズのランダムなQUBOをつくります。

print(rands(5))
                                                                                                                      
[[0.09115732 0.29359074 0.35405008 0.49994961 0.51651569]
 [0.         0.04694928 0.7346531  0.0262923  0.91495861]
 [0.         0.         0.67008585 0.20086915 0.98148961]
 [0.         0.         0.         0.95067288 0.97851068]
 [0.         0.         0.         0.         0.82717209]]

すべて0のQUBOをつくるzeros(N)

print(zeros(5))

[[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]

そして複層のNNを構成するdbms(arr)は、arrにlistで渡された層をランダムで構成します。

print(dbms([2,2,2]))

[[0.76902154 0.         0.39452523 0.04723368 0.         0.        ]
 [0.         0.30177968 0.31477805 0.94816362 0.         0.        ]
 [0.         0.         0.51159807 0.         0.28540382 0.89286157]
 [0.         0.         0.         0.50259602 0.16700922 0.87016573]
 [0.         0.         0.         0.         0.88094842 0.        ]
 [0.         0.         0.         0.         0.         0.57970873]]


通常はRBMをつかい、それは2層なので、dbms([2,2])のように層を調整して使います。

print(dbms([2,2]))                                                                                                                                                                                            

[[0.77507208 0.         0.3367279  0.05164013]
 [0.         0.68135985 0.56009716 0.09424495]
 [0.         0.         0.75018226 0.        ]
 [0.         0.         0.         0.47063999]]

準備ができましたので、モデルを作ってみたいと思います。

RBMのモデル

下記のような4×4のRBM回路を作ってみます。

パラメータは早速準備されたdbms()を使います。

from wildqat import *
a = opt()
a.qubo = dbms([4,4])
print(a.qubo)

[[0.49916422 0.         0.         0.         0.28494359 0.20770453
  0.40299902 0.84179542]
 [0.         0.65409222 0.         0.         0.57088742 0.54236081
  0.42355624 0.06049014]
 [0.         0.         0.04613128 0.         0.02690597 0.72976234
  0.10690582 0.31747239]
 [0.         0.         0.         0.66022467 0.6870002  0.37389617
  0.96633279 0.21226541]
 [0.         0.         0.         0.         0.40721383 0.
  0.         0.        ]
 [0.         0.         0.         0.         0.         0.32555584
  0.         0.        ]
 [0.         0.         0.         0.         0.         0.
  0.78054798 0.        ]
 [0.         0.         0.         0.         0.         0.
  0.         0.7939747 ]]

4×4のRBMは8×8のQUBOmatrixを使います。このように基本機能で機械学習の準備ができました。

今後は少し具体的なモデルで学習と推論を実行してみたいと思います。以上です。

Recommended


Wikiへ移動