Přeskočit na hlavní obsah

Optimalizační smyčky

V této lekci se naučíš, jak pomocí optimalizátoru iterativně prozkoumávat parametrizované kvantové stavy našeho ansatzu:

  • Spustit optimalizační smyčku
  • Pochopit kompromisy při použití lokálních a globálních optimalizátorů
  • Prozkoumat pusté planiny (barren plateaus) a jak se jim vyhnout

Na vysoké úrovni jsou optimalizátory klíčové pro prozkoumávání našeho prohledávacího prostoru. Optimalizátor používá vyhodnocení účelové funkce k výběru další sady parametrů ve variační smyčce a tento proces opakuje, dokud nedosáhne stabilního stavu. V tomto okamžiku je vrácena optimální sada hodnot parametrů θ\vec\theta^*.

Diagram některých důležitých faktorů optimalizace, včetně pustých planin, optimalizátorů na základě gradientu vs. bez gradientu a bootstrappingu.

Lokální a globální optimalizátory

Nejprve si nastavíme náš problém před prozkoumáním každé třídy optimalizátorů. Začneme s Circuit obsahujícím osm variačních parametrů:

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit scipy
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.circuit.library import TwoLocal
import numpy as np

theta_list = (2 * np.pi * np.random.rand(1, 8)).tolist()
observable = SparsePauliOp.from_list([("XX", 1), ("YY", -3)])

reference_circuit = QuantumCircuit(2)
reference_circuit.x(0)

variational_form = TwoLocal(
2,
rotation_blocks=["rz", "ry"],
entanglement_blocks="cx",
entanglement="linear",
reps=1,
)
ansatz = reference_circuit.compose(variational_form)

ansatz.decompose().draw("mpl")

Výstup předchozí buňky kódu

def cost_func_vqe(params, ansatz, hamiltonian, estimator):
"""Return estimate of energy from estimator

Parameters:
params (ndarray): Array of ansatz parameters
ansatz (QuantumCircuit): Parameterized ansatz circuit
hamiltonian (SparsePauliOp): Operator representation of Hamiltonian
estimator (Estimator): Estimator primitive instance

Returns:
float: Energy estimate
"""
pub = (ansatz, hamiltonian, params)
cost = estimator.run([pub]).result()[0].data.evs
return cost
from qiskit.primitives import StatevectorEstimator

estimator = StatevectorEstimator()

Lokální optimalizátory

Lokální optimalizátory hledají bod, který minimalizuje účelovou funkci, začínají od počátečního bodu (bodů) C(θ0)C(\vec{\theta_0}) a přecházejí na různé body na základě toho, co pozorují v oblasti, kterou právě vyhodnocují v postupných iteracích. To znamená, že konvergence těchto algoritmů bývá rychlá, ale může být silně závislá na počátečním bodu. Lokální optimalizátory nejsou schopny vidět za oblast, kde probíhá vyhodnocování, a mohou být zvláště náchylné k lokálním minimům – hlásí konvergenci, když takové minimum najdou, a ignorují ostatní stavy s příznivějšími hodnotami.

# SciPy minimizer routine
from scipy.optimize import minimize

x0 = np.ones(8)

result = minimize(
cost_func_vqe, x0, args=(ansatz, observable, estimator), method="SLSQP"
)

result
message: Optimization terminated successfully
success: True
status: 0
fun: -3.9999999964520634
x: [ 1.000e+00 1.000e+00 -1.571e+00 -4.556e-05 -1.207e+00
-1.935e+00 4.079e-01 -4.079e-01]
nit: 12
jac: [ 0.000e+00 0.000e+00 -7.957e-04 2.543e-04 1.381e-03
1.381e-03 5.430e-04 5.431e-04]
nfev: 112
njev: 12

Globální optimalizátory

Globální optimalizátory hledají bod, který minimalizuje účelovou funkci přes několik oblastí jejího definičního oboru (tj. nelokálně), a vyhodnocují ji iterativně (tj. v iteraci ii) přes sadu vektorů parametrů Θi:=θi,jjJopti\Theta_i := \\{ {\vec\theta_{i,j} | j \in \mathcal{J}_\text{opt}^i} \\} určených optimalizátorem. Díky tomu jsou méně náchylné k lokálním minimům a do jisté míry nezávislé na inicializaci, ale také výrazně pomaleji konvergují k navrhovanému řešení.

Bootstrapping optimalizace

Bootstrapping, neboli nastavení počáteční hodnoty pro parametry θ\vec\theta na základě předchozí optimalizace, může pomoci našemu optimalizátoru rychleji konvergovat k řešení. Označujeme to jako počáteční bod θ0\vec\theta_0 a ψ(θ0)=UV(θ0)ρ|\psi(\vec\theta_0)\rangle = U_V(\vec\theta_0)|\rho\rangle jako počáteční stav. Tento počáteční stav se liší od našeho referenčního stavu ρ|\rho\rangle, protože první se zaměřuje na počáteční parametry nastavené během naší optimalizační smyčky, zatímco druhý se zaměřuje na použití známých „referenčních" řešení. Mohou se shodovat, pokud UV(θ0)IU_V(\vec\theta_0) \equiv I (tj. operace identity).

Když lokální optimalizátory konvergují k neoptimálním lokálním minimům, můžeme zkusit bootstrapping optimalizace globálně a lokálně konvergenci zpřesnit. Přestože to vyžaduje nastavení dvou variačních pracovních zátěží, umožňuje to optimalizátoru najít optimálnější řešení, než by lokální optimalizátor dokázal sám.

Optimalizátory na základě gradientu a bez gradientu

Na základě gradientu

Pro naši účelovou funkci C(θ)C(\vec\theta), pokud máme přístup ke gradientu funkce C(θ)\vec{\nabla} C(\vec\theta) počínaje od počátečního bodu, nejjednodušší způsob minimalizace funkce je aktualizovat parametry ve směru největšího klesání funkce. To znamená, že parametry aktualizujeme jako θn+1=θnηC(θ)\vec\theta_{n+1} = \vec\theta_n - \eta \vec{\nabla} C(\vec\theta), kde η\eta je rychlost učení – malý, kladný hyperparametr řídící velikost aktualizace. Pokračujeme v tom, dokud nekonvergujeme k lokálnímu minimu účelové funkce C(θ)C({\vec\theta^*}). Tuto účelovou funkci a optimalizátor můžeme použít k výpočtu optimálních parametrů

# SciPy minimizer routine
from scipy.optimize import minimize

x0 = np.ones(8)

result = minimize(
cost_func_vqe, x0, args=(ansatz, observable, estimator), method="BFGS"
)

result
message: Optimization terminated successfully.
success: True
status: 0
fun: -3.9999999999997025
x: [ 1.000e+00 1.000e+00 1.571e+00 3.220e-07 2.009e-01
-2.009e-01 6.342e-01 -6.342e-01]
nit: 14
jac: [-1.192e-07 -2.980e-08 8.345e-07 1.103e-06 5.960e-08
0.000e+00 -5.960e-08 2.980e-08]
hess_inv: [[ 1.000e+00 1.872e-10 ... 5.077e-05 3.847e-05]
[ 1.872e-10 1.000e+00 ... -5.208e-05 -4.060e-05]
...
[ 5.077e-05 -5.208e-05 ... 7.243e-01 -2.604e-01]
[ 3.847e-05 -4.060e-05 ... -2.604e-01 8.179e-01]]
nfev: 144
njev: 16

Hlavními nevýhodami tohoto typu optimalizace jsou rychlost konvergence, která může být velmi pomalá, a neexistuje žádná záruka dosažení optimálního řešení.

Graf f(theta) oproti theta, více bodů zobrazuje různé stavy algoritmu gradientního sestupu při hledání minima křivky.

Bez gradientu

Optimalizační algoritmy bez gradientu nevyžadují informace o gradientu a mohou být užitečné v situacích, kde je výpočet gradientu obtížný, nákladný nebo příliš zašuměný. Mívají také tendenci být robustnější při hledání globálních optim, zatímco metody na základě gradientu mají tendenci konvergovat k lokálním optimům. Prozkoumáme několik případů, kde optimalizátor bez gradientu může pomoci vyhnout se pustým planinám. Metody bez gradientu však vyžadují vyšší výpočetní zdroje, zejména u problémů s vícerozměrnými prohledávacími prostory.

Zde je příklad, který místo toho používá optimalizátor COBYLA:

# SciPy minimizer routine
from scipy.optimize import minimize

x0 = np.ones(8)

result = minimize(
cost_func_vqe, x0, args=(ansatz, observable, estimator), method="COBYLA"
)

result
message: Optimization terminated successfully.
success: True
status: 1
fun: -3.999999973369678
x: [ 1.631e+00 1.492e+00 1.571e+00 3.142e+00 1.375e+00
-1.767e+00 1.484e+00 1.658e+00]
nfev: 137
maxcv: 0.0

Pusté planiny

Ve skutečnosti může být krajina účelové funkce poměrně složitá, jak ukazují kopce a údolí v níže uvedeném příkladu. Optimalizační metoda nás vede po krajině účelové funkce a hledá minimum, jak ukazují černé body a čáry. Vidíme, že dvě ze tří hledání skončí v lokálním minimu krajiny, nikoli v globálním.

Složitá zakřivená plocha s mnoha vrcholy a prohlubněmi.

Bez ohledu na typ použité optimalizační metody platí, že pokud je krajina účelové funkce relativně plochá, může být pro metodu obtížné určit správný směr hledání. Tento scénář se označuje jako pustá planina, kde se krajina účelové funkce stává postupně plošší (a tedy obtížnějším pro určení směru k minimu). Pro širokou škálu parametrizovaných kvantových obvodů pravděpodobnost, že gradient v jakémkoli rozumném směru je nenulový s určitou pevnou přesností, klesá exponenciálně s rostoucím počtem Qubitů.

Diagram geografické planiny ve srovnání se svahem hory, vysvětlující, proč nám gradient pomáhá najít minimum a planina naše snahy ztěžuje.

Přestože tato oblast je stále aktivně zkoumána, máme několik doporučení pro zlepšení výkonu optimalizace:

  • Bootstrapping může pomoct optimalizační smyčce vyhnout se uvíznutí v parametrickém prostoru, kde je gradient malý.
  • Experimentování s hardwarově efektivním ansatzem: Protože používáme zašuměný kvantový systém jako černou skříňku (oracle), kvalita těchto vyhodnocení může ovlivnit výkon optimalizátoru. Použití hardwarově efektivního ansatzu, jako je EfficientSU2, může zabránit vzniku exponenciálně malých gradientů.
  • Experimentování s potlačením chyb a zmírněním chyb: Primitivy Qiskit Runtime poskytují jednoduché rozhraní pro experimentování s různými hodnotami optimization_level a resilience_setting. To může snížit dopad šumu a zefektivnit proces optimalizace.
  • Experimentování s optimalizátory bez gradientu: Na rozdíl od optimalizačních algoritmů na základě gradientu se optimalizátory jako COBYLA nespoléhají na informace o gradientu pro optimalizaci parametrů, a jsou tedy méně náchylné k pustým planinám.

Shrnutí

V této lekci ses naučil/a, jak definovat svou optimalizační smyčku:

  • Spustit optimalizační smyčku
  • Pochopit kompromisy při použití lokálních a globálních optimalizátorů
  • Prozkoumat pusté planiny a jak se jim vyhnout

Naše variační pracovní zátěž na vysoké úrovni je hotová:

Kvantový Circuit nyní s unitárním operátorem pro přípravu referenčního stavu a druhým unitárním operátorem pro variaci stavu pomocí variačních parametrů.

Dále prozkoumáme konkrétní variační algoritmy s ohledem na tento rámec.