최적화 루프
이 강의에서 우리는 *optimizer(최적화기)*를 사용하여 우리의 ansatz의 매개변수화된 양자 상태를 반복적으로 탐색하는 방법을 배우게 됩니다:
- 최적화 루프 구축
- 지역 최적화기와 전역 최적화기 사용 시 트레이드오프 이해
- barren plateau를 탐색하고 이를 피하는 방법
높은 수준에서, 최적화기는 우리의 탐색 공간을 탐색하는 데 중심적인 역할을 합니다. 최적화기는 비용 함수 평가를 사용하여 변분 루프에서 다음 매개변수 집합을 선택하고, 안정된 상태에 도달할 때까지 이 과정을 반복합니다. 이 단계에서 최적의 매개변수 값 가 반환됩니다.
지역 최적화기와 전역 최적화기
먼저 각 최적화기 클래스를 탐색하기 전에 우리의 문제를 설정하겠습니다. 8개의 변분 매개변수를 포함하는 회로로 시작할 것입니다:
# 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")
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()
지역 최적화기
지역 최적화기는 초기 포인트 에서 시작하여 비용 함수를 최소화하는 포인트를 찾고, 연속적인 반복에서 현재 평가 중인 영역에서 관찰되는 것을 기반으로 다른 포인트로 이동합니다. 이는 이러한 알고리즘의 수렴이 일반적으로 빠르지만, 초기 포인트에 크게 의존할 수 있음을 의미합니다. 지역 최적화기는 평가하고 있는 영역 너머를 볼 수 없으며, 특히 지역 최솟값에 취약할 수 있으며, 하나를 찾으면 수렴을 보고하고 더 나은 평가를 가진 다른 상태를 무시합니다.
# 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
전역 최적화기
전역 최적화기는 도메인의 여러 영역에서 비용 함수를 최소화하는 포인트를 찾습니다(즉, non-local), 반복적으로(즉, 반복 에서) 최적화기가 결정한 매개변수 벡터 집합 에 대해 평가합니다. 이는 지역 최솟값에 덜 취약하고 초기화와 어느 정도 독립적이지만, 제안된 해결책으로 수렴하는 데 훨씬 더 느립니다.
최적화 부트스트래핑
Bootstrapping, 또는 이전 최적화를 기반으로 매개변수 의 초기 값을 설정하는 것은 우리의 최적화기가 더 빠르게 해결책으로 수렴하도록 도울 수 있습니다. 우리는 이를 초기 포인트 으로 부르며, 을 초기 상태로 부릅니다. 이 초기 상태는 우리의 참조 상태 와 다릅니다. 전자는 우리의 최적화 루프 중 설정된 초기 매개변수에 초점을 맞추고, 후자는 알려진 "참조" 해결책을 사용하는 데 초점을 맞춥니다. (즉, 항등 연산)인 경우 일치할 수 있습니다.
지역 최적화기가 최적이 아닌 지역 최솟값으로 수렴할 때, 우리는 최적화를 전역적으로 부트스트래핑하고 수렴을 지역적으로 개선하려고 시도할 수 있습니다. 이는 두 개의 변분 작업을 설정해야 하지만, 최적화기가 지역 최적화기만으로 얻을 수 있는 것보다 더 최적의 해결책을 찾을 수 있게 해줍니다.
Gradient 기반 및 Gradient-Free 최적화기
Gradient 기반
우리의 비용 함수 에 대해, 초기 포인트에서 함수의 기울기 에 접근할 수 있다면, 함수를 최소화하는 가장 간단한 방법은 함수의 가장 가파른 하강 방향으로 매개변수를 업데이트하는 것입니다. 즉, 우리는 매개변수를 로 업데이트합니다. 여기서 는 학습 속도입니다. 이는 업데이트의 크기를 제어하는 작은, 양수 hyperparameter(하이퍼파라미터)입니다. 우리는 비용 함수의 local minimum(지역 최솟값)으로 수렴할 때까지 이를 계속 수행합니다. 즉, .
이 비용 함수와 최적화기를 사용하여 최적의 매개변수를 계산할 수 있습니다.
# 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
이러한 유형의 최적화의 주요 단점은 매우 느릴 수 있는 수렴 속도이며, 최적의 해결책을 달성한다는 보장이 없습니다.
Gradient-Free
Gradient-free 최적화 알고리즘은 기울기 정보를 필요로 하지 않으며 기울기 계산이 어렵거나, 비싸거나, 너무 노이즈가 많은 상황에서 유용할 수 있습니다. 또한 gradient-based 방법이 지역 최솟값으로 수렴하는 경향이 있는 반면, 전역 최적값을 찾는 데 더 강건한 경향이 있습니다. 우리는 gradient-free 최적화기가 barren plateau를 피하는 데 도움이 될 수 있는 몇 가지 경우를 탐색할 것입니다. 그러나 gradient-free 방법은 특히 높은 차원의 탐색 공간을 가진 문제에 대해 더 많은 계산 리소스를 필요로 합니다.
다음은 대신 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
Barren Plateaus
실제로, 비용 풍경은 아래 예시의 언덕과 계곡에서 볼 수 있듯이 매우 복잡할 수 있습니다. 최적화 방법은 검은 점과 선으로 표시된 최솟값을 찾으면서 비용 풍경을 탐색합니다. 우리는 3개 탐색 중 2개가 전역 최솟값이 아니라 지역 최솟값으로 끝나는 것을 볼 수 있습니다.
사용되는 최적화 방법의 유형과 관계없이, 비용 풍경이 상대적으로 평탄하면, 방법이 탐색할 적절한 방향을 결정하기 어려울 수 있습니다. 이 시나리오를 barren plateau(황량한 고원)이라고 부르며, 비용 풍경은 점진적으로 더 평탄해집니다(따라서 최솟값 방향을 결정하기 더 어렵습니다). 매개변수화된 양자 회로의 넓은 범위에 대해, 모든 합리적인 방향을 따른 기울기가 특정 정밀도에 non-zero인 확률은 큐빗 수가 증가함에 따라 지수적으로 감소합니다.
이 영역은 여전히 활발한 연구 중이지만, 최적화 성능을 개선하기 위한 몇 가지 권장 사항이 있습니다:
- Bootstrapping은 최적화 루프가 기울기가 작은 매개변수 공간에 갇히는 것을 피하는 데 도움이 될 수 있습니다.
- Hardware-efficient ansatz 실험: 우리는 노이즈가 있는 양자 시스템을 블랙박스 오라클로 사용하고 있으므로, 이러한 평가의 품질이 최적화기의 성능에 영향을 미칠 수 있습니다.
EfficientSU2와 같은 hardware-efficient ansatz를 사용하면 지수적으로 작은 기울기를 생성하는 것을 피할 수 있습니다. - 오류 억제 및 오류 완화 실험: Qiskit Runtime 프리미티브(primitives)는
optimization_level과resilience_setting의 다양한 값으로 실험할 수 있는 간단한 인터페이스를 제공합니다. 이는 노이즈의 영향을 줄이고 최적화 프로세스를 더 효율적으로 만들 수 있습니다. - Gradient-free 최적화기 실험: Gradient-based 최적화 알고리즘과 달리,
COBYLA와 같은 최적화기는 기울기 정보에 의존하지 않으며 따라서 barren plateau의 영향을 덜 받을 가능성이 높습니다.
요약
이 강의를 통해 우리는 최적화 루프를 정의하는 방법을 배웠습니다:
- 최적화 루프 부트스트래핑
- 지역 최적화기와 전역 최적화기 사용 시 트레이드오프 이해
- Barren plateau를 탐색하고 이를 피하는 방법
우리의 높은 수준의 변분 작업이 완료되었습니다:
다음으로, 우리는 이 프레임워크를 염두에 두고 구체적인 변분 알고리즘을 탐색할 것입니다.