Qulacs-Osaka / scikit-qulacs

scikit-qulacs is a library for quantum neural network. This library is based on qulacs and named after scikit-learn.
https://qulacs-osaka.github.io/scikit-qulacs/index.html
MIT License
21 stars 6 forks source link

Seisei #174

Closed WATLE closed 2 years ago

WATLE commented 2 years ago

mainをマージして、qulcasを0.3.0に上げたら、実行できて、テスト通った

WATLE commented 2 years ago

99 生成モデルです。

ikanago commented 2 years ago

poetry.lock がこわれてたので直しました

WATLE commented 2 years ago

Solverを使うようにしました。 細かい調整などはまだです。 とりあえずBFGS部分のテストは手元で通りました。 formatとかはまだです。 Adamは元のAdam()と同じでは通らないと思います。shapeが違うので。

WATLE commented 2 years ago

いや、通るか

WATLE commented 2 years ago

generation をうまく実装しました ちゃんとSolverが使えます

forest1040 commented 2 years ago

私も#99 生成モデル確認して、コードみてみます。

forest1040 commented 2 years ago

元論文読んで、元コードと実装されたコードを見ました。

以下、こんな感じの実装がされていると思いました。

データを与えると、そのデータが持つ確率分布を推定して、確率分布を生成します。

- VQEと同様の回路 create_farhi_neven_ansatz() を使う。
- fit_direct_distribution() は、テスト用に直接確率分布を与えれるようになっている。
- predict(): 確率分布推定
`y_pred_in = self._predict_inner().get_vector()` を実行すると
量子回路の状態ベクトルから設定したデータの確率振幅が取り出せる。
複素共役を取って、かけて確率分布にして返す。
- fit(): 学習。スケール調整して、fit_direct_distribution()を呼び出す。
- conving(): カーネル関数。畳み込み演算を行う。
- cost_func(): 損失関数は、MMDを使う。

カーネル関数の辺りは、まだざっとしか見れておりません。。 最適化アルゴリズムをAdamにして、BFGSと比較するとよいかも知れません。。

forest1040 commented 2 years ago

@WATLE テストコードのスキップされている test_bar_stripe() と test_bar_stripe_hamming() ですが QNNGeneretorクラスの第2パラメータにSolverを指定する必要があるかと思います。

forest1040 commented 2 years ago

評価アルゴリズム: Adam() と カーネルタイプ: gauss 等の組み合わせで実行しようとした所、zero divのエラーになりました。。

テストコード

from math import exp
import time
import numpy as np

from skqulacs.circuit import create_farhi_neven_ansatz
from skqulacs.qnn import QNNGeneretor
from skqulacs.qnn.solver import Bfgs, Adam

# 80%程度の正解率は出る。
def test_bar_stripe(solver, karnel_type):

    n_qubit = 9
    depth = 22
    circuit = create_farhi_neven_ansatz(n_qubit, depth)
    #qnn = QNNGeneretor(circuit, Bfgs(), "same", 0, 9)
    qnn = QNNGeneretor(circuit, solver, karnel_type, 0, 9)

    prob_list = np.zeros(512)
    for i in range(8):
        prob_list[i * 73] += 0.0625
        uuu = 0
        if (i & 4) > 0:
            uuu += 64
        if (i & 2) > 0:
            uuu += 8
        if (i & 1) > 0:
            uuu += 1
        prob_list[uuu * 7] += 0.0625

    datas = np.random.choice(a=range(512), size=100000, p=prob_list)

    maxiter = 600
    qnn.fit(datas, maxiter)

    data_param = qnn.predict()

    gosa = 0
    for i in range(512):
        gosa += abs(data_param[i] - prob_list[i])
        if prob_list[i] > 0.001:
            print(i, data_param[i])
    assert gosa < 0.4
    print("gosa: ", gosa)

start = time.time()
test_bar_stripe(Bfgs(), "same")
elapsed_time = time.time() - start
print ("Bfgs and same: {0}".format(elapsed_time) + "[sec]")

start = time.time()
test_bar_stripe(Bfgs(), "gauss")
elapsed_time = time.time() - start
print ("Bfgs and same: {0}".format(elapsed_time) + "[sec]")

start = time.time()
test_bar_stripe(Adam(), "same")
elapsed_time = time.time() - start
print ("Adam and same: {0}".format(elapsed_time) + "[sec]")

start = time.time()
test_bar_stripe(Adam(), "gauss")
elapsed_time = time.time() - start
print ("Adam and same: {0}".format(elapsed_time) + "[sec]")

エラーログ

root@c45c40769a39:~/temp/20200518# python s.py
Traceback (most recent call last):
  File "/root/temp/20200518/s.py", line 51, in <module>
    test_bar_stripe(Bfgs(), "gauss")
  File "/root/temp/20200518/s.py", line 33, in test_bar_stripe
    qnn.fit(datas, maxiter)
  File "/usr/local/lib/python3.9/dist-packages/skqulacs/qnn/generation.py", line 83, in fit
    return self.fit_direct_distribution(train_scaled, maxiter)
  File "/usr/local/lib/python3.9/dist-packages/skqulacs/qnn/generation.py", line 89, in fit_direct_distribution
    return self.solver.run(
  File "/usr/local/lib/python3.9/dist-packages/skqulacs/qnn/solver.py", line 74, in run
    result = minimize(
  File "/usr/local/lib/python3.9/dist-packages/scipy/optimize/_minimize.py", line 676, in minimize
    res = _minimize_bfgs(fun, x0, args, jac, callback, **options)
  File "/usr/local/lib/python3.9/dist-packages/scipy/optimize/_optimize.py", line 1296, in _minimize_bfgs
    sf = _prepare_scalar_function(fun, x0, jac, args=args, epsilon=eps,
  File "/usr/local/lib/python3.9/dist-packages/scipy/optimize/_optimize.py", line 263, in _prepare_scalar_function
    sf = ScalarFunction(fun, x0, args, grad, hess,
  File "/usr/local/lib/python3.9/dist-packages/scipy/optimize/_differentiable_functions.py", line 158, in __init__
    self._update_fun()
  File "/usr/local/lib/python3.9/dist-packages/scipy/optimize/_differentiable_functions.py", line 251, in _update_fun
    self._update_fun_impl()
  File "/usr/local/lib/python3.9/dist-packages/scipy/optimize/_differentiable_functions.py", line 155, in update_fun
    self.f = fun_wrapped(self.x)
  File "/usr/local/lib/python3.9/dist-packages/scipy/optimize/_differentiable_functions.py", line 137, in fun_wrapped
    fx = fun(np.copy(x), *args)
  File "/usr/local/lib/python3.9/dist-packages/skqulacs/qnn/generation.py", line 195, in cost_func
    conv_diff = self.conving(data_diff)
  File "/usr/local/lib/python3.9/dist-packages/skqulacs/qnn/generation.py", line 148, in conving
    beta = -0.5 / self.gauss_sigma
ZeroDivisionError: float division by zero

root@c45c40769a39:~/temp/20200518# python s.py
Traceback (most recent call last):
  File "/root/temp/20200518/s.py", line 56, in <module>
    test_bar_stripe(Adam(), "same")
  File "/root/temp/20200518/s.py", line 33, in test_bar_stripe
    qnn.fit(datas, maxiter)
  File "/usr/local/lib/python3.9/dist-packages/skqulacs/qnn/generation.py", line 83, in fit
    return self.fit_direct_distribution(train_scaled, maxiter)
  File "/usr/local/lib/python3.9/dist-packages/skqulacs/qnn/generation.py", line 89, in fit_direct_distribution
    return self.solver.run(
  File "/usr/local/lib/python3.9/dist-packages/skqulacs/qnn/solver.py", line 121, in run
    y[iter % len(y) : iter % len(y) + 5],
ZeroDivisionError: integer division or modulo by zero

ちょっと見てみます。

forest1040 commented 2 years ago

評価アルゴリズム: Adam() と カーネルタイプ: gauss 等の組み合わせで実行しようとした所、zero divのエラーになりました。。

よく見たら指定しているパラメータが0だからですね。。

forest1040 commented 2 years ago

以下のような感じになりました。 Adam()は、最適化の処理自体は速いですが、精度が悪いですね。。 Bfgs()で、カーネルは gauss の方がよい結果がでましたが、結果が安定しない気がしています。

※Adam() の場合、_cost_func_grad()の更新時に、イテレーション数があわないため、一時的にイテレーション数を512に書き換えて実行しました。

結果

# python s.py
/usr/local/lib/python3.9/dist-packages/scipy/optimize/_linesearch.py:155: ComplexWarning: Casting complex values to real discards the imaginary part
  stp, phi1, derphi1, task = minpack2.dcsrch(alpha1, phi1, derphi1,
0 (0.122732656334093+0j)
7 (0.059786281708801875+0j)
56 (0.060585023834097695+0j)
63 (0.060847034043319065+0j)
73 (0.060640690587019055+0j)
146 (0.06141697300562065+0j)
219 (0.05917982291209568+0j)
292 (0.059938702802542876+0j)
365 (0.0616526192593371+0j)
438 (0.060140588647330205+0j)
448 (0.05951952352845949+0j)
455 (0.0611376097740885+0j)
504 (0.059992893239780236+0j)
511 (0.12348470656661531+0j)
gosa:  0.05788974751359935
Bfgs and same: 73.56574845314026[sec]
0 (0.12471545025285323+0j)
7 (0.062039626623453206+0j)
56 (0.061765524845125035+0j)
63 (0.061748263713792814+0j)
73 (0.06128091097183188+0j)
146 (0.062441298707139374+0j)
219 (0.06198032845480563+0j)
292 (0.0624442754395209+0j)
365 (0.059927025342892126+0j)
438 (0.06256253929742411+0j)
448 (0.06201679016502146+0j)
455 (0.062159586399058345+0j)
504 (0.061863337599216806+0j)
511 (0.12503881466219652+0j)
gosa:  0.016235162970578393
Bfgs and gauss: 57.84395384788513[sec]
0 (0.11500141585727836+0j)
7 (0.04806137224609201+0j)
56 (0.05461186662747158+0j)
63 (0.05178309712504523+0j)
73 (0.0037156778337893636+0j)
146 (0.005867236658809195+0j)
219 (0.05188175378918395+0j)
292 (0.05154550348272225+0j)
365 (0.0018954332212237418+0j)
438 (0.001299931607384525+0j)
448 (0.052877636801976026+0j)
455 (0.051848747593337775+0j)
504 (0.04831710617517458+0j)
511 (0.11414771996089268+0j)
gosa:  0.6942910020392374
Adam and same: 2.8896913528442383[sec]
0 (0.11097037286877917+0j)
7 (0.039327967724504934+0j)
56 (0.055329816298311525+0j)
63 (0.04980675708311158+0j)
73 (0.009020876379897236+0j)
146 (0.0024222674417955564+0j)
219 (0.037703831464262386+0j)
292 (0.036674488492328836+0j)
365 (0.015907798087379632+0j)
438 (0.001585521338788234+0j)
448 (0.04844926053711909+0j)
455 (0.052112764296371336+0j)
504 (0.03655547907220827+0j)
511 (0.11368371640404687+0j)
gosa:  0.7808981650221903
Adam and gauss: 2.896209955215454[sec]
root@c45c40769a39:~/temp/20200518# 
forest1040 commented 2 years ago

Adam()で、maxiterを600から40倍の24000で試しました。 あまり結果が安定していないですし、Bfgs()に比べて、それほど良い精度にはなりませんでした。。

root@c45c40769a39:~/temp/seisei# python s.py
0 (0.12282892078419376+0j)
7 (0.061298138928447765+0j)
56 (0.06186084965831065+0j)
63 (0.061397889445434804+0j)
73 (0.06304935828499061+0j)
146 (0.06076738982625458+0j)
219 (0.06342910553990032+0j)
292 (0.06296746657256204+0j)
365 (0.06166897356026799+0j)
438 (0.06140369405171732+0j)
448 (0.06059533922977197+0j)
455 (0.06342394756245828+0j)
504 (0.06271674956569716+0j)
511 (0.12358929774132336+0j)
gosa:  0.02417901354855656
Adam and same: 113.7599241733551[sec]
root@c45c40769a39:~/temp/seisei# 
root@c45c40769a39:~/temp/seisei# 
root@c45c40769a39:~/temp/seisei# 
root@c45c40769a39:~/temp/seisei# python s.py
0 (0.1231643378083779+0j)
7 (0.060739238826695144+0j)
56 (0.06216170162834887+0j)
63 (0.06200357226838695+0j)
73 (0.06320408727754581+0j)
146 (0.06138740929427611+0j)
219 (0.06180659618484891+0j)
292 (0.06354351337990076+0j)
365 (0.06357588556832985+0j)
438 (0.0637136485634689+0j)
448 (0.06402319181040111+0j)
455 (0.0613884496474543+0j)
504 (0.06229059835451905+0j)
511 (0.125730999023939+0j)
gosa:  0.015116191974185678
Adam and same: 115.66483664512634[sec]
root@c45c40769a39:~/temp/seisei# 
root@c45c40769a39:~/temp/seisei# python s.py
0 (0.12430451674398407+0j)
7 (0.06250563897611967+0j)
56 (0.0625659989704961+0j)
63 (0.06293780930964371+0j)
73 (0.061823651975557004+0j)
146 (0.06305458666753191+0j)
219 (0.06288752990957323+0j)
292 (0.06262393601371959+0j)
365 (0.06103062576565881+0j)
438 (0.06294921786483577+0j)
448 (0.061935657377202566+0j)
455 (0.06260952946299758+0j)
504 (0.06266552324393973+0j)
511 (0.12423873820846883+0j)
gosa:  0.008333619858258232
Adam and same: 114.75292730331421[sec]
WATLE commented 2 years ago

結局、マージOKですか?

kosukemtr commented 2 years ago

簡単なチュートリアルノートブック用意していただけますか?

forest1040 commented 2 years ago

@WATLE もし、チュートリアル作るのに時間がかかりそうなら、言ってください。サポートします。

WATLE commented 2 years ago

チュートリアル作ります

WATLE commented 2 years ago

チュートリアルつくりました

forest1040 commented 2 years ago

@WATLE

生成モデルですが、以下のような説明がいいかなと思いました。

生成モデルとは、 教師なし学習の一種で、 入力データを学習し、 それと特徴が似た出力をするモデルです。

生成モデルとは、教師なし学習の一種で、与えられた入力データから確率分布を学習し、それに応じて新しいサンプルを生成するモデルです。

後、コードの説明をもう少し入れた方がよいかなと思いました。 例えば、

codecov[bot] commented 2 years ago

Codecov Report

:exclamation: No coverage uploaded for pull request base (main@4ff6849). Click here to learn what that means. The diff coverage is n/a.

@@           Coverage Diff           @@
##             main     #174   +/-   ##
=======================================
  Coverage        ?   90.61%           
=======================================
  Files           ?       12           
  Lines           ?      863           
  Branches        ?      163           
=======================================
  Hits            ?      782           
  Misses          ?       50           
  Partials        ?       31           

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 4ff6849...3f3fce6. Read the comment docs.

forest1040 commented 2 years ago

LGTMです! いかがでしょうか? > @kosukemtr

kosukemtr commented 2 years ago

少しだけ修正お願いします。チュートリアルに文章やコメントに謎の全角スペースが入っているのと、よくわからないコメント (# VQEと同じ回路を用いている とかです) を直してほしいです。よろしくお願いします。それ以外は LGTM です

WATLE commented 2 years ago

全角消しました