{
  "cells": [
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "2a246d14-ed2b-4573-bf97-939c3628b3bb",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"최적화 루프\"\n",
        "description: \"이 강의에서는 양자 계산에 매개변수를 입력하기 위해 고전적 최적화 루프를 사용하는 방법을 단계별로 설명합니다.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore nabla */}\n",
        "\n",
        "<span id=\"optimization-loops\" />\n",
        "\n",
        "# 최적화 루프\n",
        "\n",
        "이 강의에서는 *최적화* 도구를 사용하여 매개변수화된 양자 상태를 반복적으로 탐색하는 방법을 배웁니다:\n",
        "\n",
        "* 최적화 루프 부트스트랩\n",
        "* 로컬 및 글로벌 최적화 도구 사용 시 장단점 이해하기\n",
        "* 척박한 고원 탐험과 이를 피하는 방법\n",
        "\n",
        "높은 수준에서 최적화 도구는 검색 공간을 탐색하는 데 있어 핵심적인 역할을 합니다. 최적화 도구는 비용 함수 평가를 사용하여 가변 루프에서 다음 매개변수 집합을 선택하고 안정 상태에 도달할 때까지 이 과정을 반복합니다. 이 단계에서는 최적의 매개변수 값 집합 $\\vec\\theta^*$ 이 반환됩니다.\n",
        "\n",
        "![불모지, 그라데이션과 그라데이션이 없는 최적화 도구, 부트스트랩 등 최적화에 있어 중요한 몇 가지 요소에 대한 다이어그램입니다.](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-workflow.svg)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "110421e7-0d2a-4653-a195-1925c809ca61",
      "metadata": {},
      "source": [
        "<span id=\"local-and-global-optimizers\" />\n",
        "\n",
        "## 국소 최적화기 및 전역 최적화기\n",
        "\n",
        "각 옵티마이저 클래스를 살펴보기 전에 먼저 문제를 설정하겠습니다. 8개의 변형 매개변수가 포함된 회로부터 시작하겠습니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "15cf7810-1d25-4c54-aff0-91d3a0c51cec",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/variational-algorithm-design/optimization-loops/extracted-outputs/15cf7810-1d25-4c54-aff0-91d3a0c51cec-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.circuit.library import TwoLocal\n",
        "import numpy as np\n",
        "\n",
        "theta_list = (2 * np.pi * np.random.rand(1, 8)).tolist()\n",
        "observable = SparsePauliOp.from_list([(\"XX\", 1), (\"YY\", -3)])\n",
        "\n",
        "reference_circuit = QuantumCircuit(2)\n",
        "reference_circuit.x(0)\n",
        "\n",
        "variational_form = TwoLocal(\n",
        "    2,\n",
        "    rotation_blocks=[\"rz\", \"ry\"],\n",
        "    entanglement_blocks=\"cx\",\n",
        "    entanglement=\"linear\",\n",
        "    reps=1,\n",
        ")\n",
        "ansatz = reference_circuit.compose(variational_form)\n",
        "\n",
        "ansatz.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "950569c0-4e8f-49b5-b118-7cd227bd5ce1",
      "metadata": {},
      "outputs": [],
      "source": [
        "def cost_func_vqe(params, ansatz, hamiltonian, estimator):\n",
        "    \"\"\"Return estimate of energy from estimator\n",
        "\n",
        "    Parameters:\n",
        "        params (ndarray): Array of ansatz parameters\n",
        "        ansatz (QuantumCircuit): Parameterized ansatz circuit\n",
        "        hamiltonian (SparsePauliOp): Operator representation of Hamiltonian\n",
        "        estimator (Estimator): Estimator primitive instance\n",
        "\n",
        "    Returns:\n",
        "        float: Energy estimate\n",
        "    \"\"\"\n",
        "    pub = (ansatz, hamiltonian, params)\n",
        "    cost = estimator.run([pub]).result()[0].data.evs\n",
        "    return cost"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "f536ee50-373f-4873-b258-66c5c07c65c5",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.primitives import StatevectorEstimator\n",
        "\n",
        "estimator = StatevectorEstimator()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c9dcec4d-5b84-4731-8b5a-cb8a0f7572d5",
      "metadata": {},
      "source": [
        "<span id=\"local-optimizers\" />\n",
        "\n",
        "### 국소 최적화기\n",
        "\n",
        "로컬 옵티마이저는 초기 지점( $C(\\vec{\\theta_0})$ )에서 시작하여 비용 함수를 최소화하는 지점을 검색하고 연속적인 반복에서 현재 평가 중인 영역에서 관찰한 내용을 기반으로 다른 지점으로 이동합니다. 이는 이러한 알고리즘의 수렴이 일반적으로 빠르지만 초기 지점에 따라 크게 달라질 수 있음을 의미합니다. 로컬 옵티마이저는 평가하는 지역 너머를 볼 수 없으며, 특히 지역 최소값에 취약하여 한 지역을 발견하면 수렴을 보고하고 더 유리한 평가를 받은 다른 주를 무시할 수 있습니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "447df742-13bd-4d4a-a364-41d34380cbc9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              " message: Optimization terminated successfully\n",
              " success: True\n",
              "  status: 0\n",
              "     fun: -3.9999999964520634\n",
              "       x: [ 1.000e+00  1.000e+00 -1.571e+00 -4.556e-05 -1.207e+00\n",
              "           -1.935e+00  4.079e-01 -4.079e-01]\n",
              "     nit: 12\n",
              "     jac: [ 0.000e+00  0.000e+00 -7.957e-04  2.543e-04  1.381e-03\n",
              "            1.381e-03  5.430e-04  5.431e-04]\n",
              "    nfev: 112\n",
              "    njev: 12"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# SciPy minimizer routine\n",
        "from scipy.optimize import minimize\n",
        "\n",
        "x0 = np.ones(8)\n",
        "\n",
        "result = minimize(\n",
        "    cost_func_vqe, x0, args=(ansatz, observable, estimator), method=\"SLSQP\"\n",
        ")\n",
        "\n",
        "result"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "25fee3f4-9d3e-45ce-a104-dfde5e132b2b",
      "metadata": {},
      "source": [
        "<span id=\"global-optimizers\" />\n",
        "\n",
        "### 글로벌 최적화기\n",
        "\n",
        "글로벌 옵티마이저는 도메인의 여러 영역(즉, 비로컬)에서 비용 함수를 최소화하는 지점을 검색하여 옵티마이저가 결정한 파라미터 벡터 집합 $\\Theta_i := \\\\{ {\\vec\\theta_{i,j} | j \\in \\mathcal{J}_\\text{opt}^i} \\\\}$ 에 대해 반복적으로(즉, 반복에서 $i$ ) 평가합니다. 따라서 로컬 최소값에 덜 민감하고 초기화와는 어느 정도 독립적이지만 제안된 솔루션으로 수렴하는 속도가 상당히 느립니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8d794038-8e75-4649-a978-a9e832ebed60",
      "metadata": {},
      "source": [
        "<span id=\"bootstrapping-optimization\" />\n",
        "\n",
        "### 부트스트래핑 최적화\n",
        "\n",
        "*부트스트랩* 또는 이전 최적화를 기반으로 매개변수 $\\vec\\theta$ 의 초기 값을 설정하면 옵티마이저가 솔루션에 더 빠르게 수렴하는 데 도움이 될 수 있습니다. 이를 초기 지점 $\\vec\\theta_0$, $|\\psi(\\vec\\theta_0)\\rangle = U_V(\\vec\\theta_0)|\\rho\\rangle$ 을 초기 상태라고 합니다. 이 초기 상태는 참조 상태( $|\\rho\\rangle$ )와 다르며, 전자는 최적화 루프 중에 설정된 초기 파라미터에 초점을 맞추고 후자는 알려진 '참조' 솔루션을 사용하는 데 중점을 두기 때문입니다. $U_V(\\vec\\theta_0) \\equiv I$ (즉, ID 연산)이 일치하는 경우 일치할 수 있습니다.\n",
        "\n",
        "로컬 옵티마이저가 최적이 아닌 로컬 최소값으로 수렴하는 경우 글로벌 최적화를 부트스트랩하고 로컬에서 수렴을 개선할 수 있습니다. 이를 위해서는 두 가지 변형 워크로드를 설정해야 하지만 로컬 옵티마이저만 사용하는 것보다 옵티마이저가 더 최적의 솔루션을 찾을 수 있습니다.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "07ba982e-9280-4e15-9d8c-4b6460b1deea",
      "metadata": {
        "gloss": {
          "hyperparameter": {
            "text": "A hyperparameter is a parameter that we use to control our algorithm. The ‘hyper’ distinguishes it from the parameters (θ) that our algorithm is trying to find.",
            "title": "Hyperparameter"
          },
          "local-minimum": {
            "text": "A local minimum is the lowest point of the function, for a small range of values of theta. In contrast, a global minimum is <i>the</i> lowest point, anywhere in our function (that is, for any value of theta). <a href='https://en.wikipedia.org/wiki/Maxima_and_minima'>Read more</a>.",
            "title": "Local minimum"
          }
        }
      },
      "source": [
        "<span id=\"gradient-based-and-gradient-free-optimizers\" />\n",
        "\n",
        "## 경사 기반 및 경사 자유 최적화기\n",
        "\n",
        "<span id=\"gradient-based\" />\n",
        "\n",
        "### 경사 기반\n",
        "\n",
        "비용 함수 $C(\\vec\\theta)$ 의 경우, 초기 지점에서 시작하여 $\\vec{\\nabla} C(\\vec\\theta)$ 함수의 기울기에 액세스할 수 있는 경우 함수를 최소화하는 가장 간단한 방법은 함수의 가장 가파른 하강 방향으로 매개 변수를 업데이트하는 것입니다. 즉, 파라미터를 $\\vec\\theta_{n+1} = \\vec\\theta_n - \\eta \\vec{\\nabla} C(\\vec\\theta)$ 로 업데이트하는데, 여기서 $\\eta$ 은 학습률이며, <DefinitionTooltip definition=\"하이퍼파라미터는 알고리즘을 제어하는 데 사용하는 매개변수입니다. 하이퍼라는 용어는 알고리즘이 찾으려는 매개변수(θ)와 구별됩니다.\">하이퍼매개변수</DefinitionTooltip> 은 업데이트의 크기를 제어하는 작고 양수입니다. 비용 함수의 <DefinitionTooltip definition=\"국부 최소값은 세타 값의 작은 범위에서 함수의 가장 낮은 지점입니다. 반면, 글로벌 최소값은 함수의 어느 위치에서든(즉, θ의 모든 값에 대해) 가장 낮은 지점입니다.\">로컬 최소값</DefinitionTooltip> 에 수렴할 때까지 이 작업을 계속 수행합니다( $C({\\vec\\theta^*})$ ).\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "0897260d-f3f8-4caa-8a79-f258e41f8e21",
      "metadata": {},
      "source": [
        "이 비용 함수와 최적화 도구를 사용하여 최적의 매개 변수를 계산할 수 있습니다\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "aad81101-3c19-4946-8453-3db9df3369c0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "  message: Optimization terminated successfully.\n",
              "  success: True\n",
              "   status: 0\n",
              "      fun: -3.9999999999997025\n",
              "        x: [ 1.000e+00  1.000e+00  1.571e+00  3.220e-07  2.009e-01\n",
              "            -2.009e-01  6.342e-01 -6.342e-01]\n",
              "      nit: 14\n",
              "      jac: [-1.192e-07 -2.980e-08  8.345e-07  1.103e-06  5.960e-08\n",
              "             0.000e+00 -5.960e-08  2.980e-08]\n",
              " hess_inv: [[ 1.000e+00  1.872e-10 ...  5.077e-05  3.847e-05]\n",
              "            [ 1.872e-10  1.000e+00 ... -5.208e-05 -4.060e-05]\n",
              "            ...\n",
              "            [ 5.077e-05 -5.208e-05 ...  7.243e-01 -2.604e-01]\n",
              "            [ 3.847e-05 -4.060e-05 ... -2.604e-01  8.179e-01]]\n",
              "     nfev: 144\n",
              "     njev: 16"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# SciPy minimizer routine\n",
        "from scipy.optimize import minimize\n",
        "\n",
        "x0 = np.ones(8)\n",
        "\n",
        "result = minimize(\n",
        "    cost_func_vqe, x0, args=(ansatz, observable, estimator), method=\"BFGS\"\n",
        ")\n",
        "\n",
        "result"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "0f7d55f8-e3a2-4223-b456-17b39a81f524",
      "metadata": {},
      "source": [
        "이러한 유형의 최적화의 가장 큰 단점은 수렴 속도가 매우 느릴 수 있으며 최적의 솔루션을 얻을 수 있다는 보장이 없다는 것입니다.\n",
        "\n",
        "![f(theta)와 세타의 그래프에서 여러 개의 점은 곡선의 최소값을 찾는 그라데이션 하강 알고리즘의 다양한 상태를 나타냅니다.](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-gradient-descent.svg)\n",
        "\n",
        "<span id=\"gradient-free\" />\n",
        "\n",
        "### 경사도 없음\n",
        "\n",
        "무경사 최적화 알고리즘은 경사 정보가 필요하지 않으므로 경사 계산이 어렵거나 비용이 많이 들거나 노이즈가 너무 많은 상황에서 유용할 수 있습니다. 또한 그라데이션 기반 방법은 로컬 최적값에 수렴하는 경향이 있는 반면, 글로벌 최적값을 찾는 데 더 강력한 경향이 있습니다. 그라데이션 없는 옵티마이저를 사용하면 막막한 정체기를 피할 수 있는 몇 가지 사례를 살펴보겠습니다. 그러나 그라데이션이 없는 방법은 특히 고차원 검색 공간의 문제에서 더 많은 계산 리소스를 필요로 합니다.\n",
        "\n",
        "다음은 [`COBYLA`](https://docs.scipy.org/doc/scipy/reference/optimize.minimize-cobyla.html#optimize-minimize-cobyla) 옵티마이저를 사용하는 예제입니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "c749695b-3124-47d8-8a23-10c9d5965a7f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              " message: Optimization terminated successfully.\n",
              " success: True\n",
              "  status: 1\n",
              "     fun: -3.999999973369678\n",
              "       x: [ 1.631e+00  1.492e+00  1.571e+00  3.142e+00  1.375e+00\n",
              "           -1.767e+00  1.484e+00  1.658e+00]\n",
              "    nfev: 137\n",
              "   maxcv: 0.0"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# SciPy minimizer routine\n",
        "from scipy.optimize import minimize\n",
        "\n",
        "x0 = np.ones(8)\n",
        "\n",
        "result = minimize(\n",
        "    cost_func_vqe, x0, args=(ansatz, observable, estimator), method=\"COBYLA\"\n",
        ")\n",
        "\n",
        "result"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "396d0617-9f20-48cb-b57c-30dfa54293ff",
      "metadata": {
        "gloss": {
          "barren-plateaus": {
            "text": "When gradients of parametrized quantum circuits become exponentially small with respect to the number of qubits, making optimization difficult and potentially impossible.",
            "title": "Barren Plateaus"
          }
        }
      },
      "source": [
        "<span id=\"barren-plateaus\" />\n",
        "\n",
        "## 황량한 고원\n",
        "\n",
        "실제로 아래 예시의 언덕과 계곡에서 볼 수 있듯이 비용 환경은 매우 복잡할 수 있습니다. 최적화 방법은 검은색 점과 선으로 표시된 것처럼 비용 환경을 탐색하여 최소값을 찾습니다. 세 가지 검색 중 두 가지 검색이 글로벌 검색이 아닌 최소한의 로컬 검색으로 끝나는 것을 볼 수 있습니다.\n",
        "\n",
        "![최고점과 최저점이 많은 복잡한 곡선형 매니폴드입니다.](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-loss-landscape.svg)\n",
        "\n",
        "사용된 최적화 방법의 유형에 관계없이 비용 환경이 비교적 평탄한 경우, 해당 방법이 적절한 검색 방향을 결정하기 어려울 수 있습니다. 이 시나리오를 <DefinitionTooltip definition=\"매개변수화된 양자 회로의 기울기가 큐비트 수에 비해 기하급수적으로 작아지면 최적화가 어려워지고 잠재적으로 불가능해질 수 있습니다.\">척박한 고원,</DefinitionTooltip> 비용 환경이 점점 더 평평해지는(따라서 최소한의 방향을 결정하기가 더 어려워지는) 시나리오라고 합니다. 광범위한 매개변수화된 양자 회로의 경우, 어떤 합리적인 방향에 따른 기울기가 0이 아닌 고정된 정밀도가 될 확률은 큐비트 수가 증가함에 따라 기하급수적으로 감소합니다.\n",
        "\n",
        "![지리적 고원을 산의 경사면과 비교한 다이어그램으로, 경사면은 최소값을 찾는 데 도움이 되고 고원은 우리의 노력을 방해하는 이유를 설명합니다.](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-barren-plateaus.svg)\n",
        "\n",
        "이 영역은 아직 활발히 연구 중이지만 최적화 성능을 개선하기 위한 몇 가지 권장 사항이 있습니다:\n",
        "\n",
        "* **부트스트랩을** 사용하면 최적화 루프가 그라데이션이 작은 매개변수 공간에서 멈추는 것을 방지할 수 있습니다.\n",
        "* **하드웨어 효율이 높은 안사츠 실험** : 노이즈가 많은 양자 시스템을 블랙박스 오라클로 사용하기 때문에 이러한 평가의 품질이 최적화 도구의 성능에 영향을 미칠 수 있습니다. 와 같은 하드웨어 효율이 높은 안사츠를 사용하면 [`EfficientSU2`](/docs/api/qiskit/qiskit.circuit.library.EfficientSU2)를 사용하면 기하급수적으로 작은 그라데이션을 만들지 않을 수 있습니다.\n",
        "* **오류 억제 및 오류 완화 실험** : IBM Quantum 의 기본 요소는 `optimization_level``resilience_setting` 각각과에 대해 다양한 값을 실험할 수 있는 간단한 인터페이스를 제공합니다. 이를 통해 소음의 영향을 줄일 수 있으며, 최적화 과정을 더욱 효율적으로 진행할 수 있습니다.\n",
        "* 그라데이션이 **없는 최적화 도구로 실험하기** : 기울기 기반 최적화 알고리즘과 달리 `COBYLA` 같은 최적화 도구는 매개변수를 최적화하기 위해 기울기 정보에 의존하지 않으므로 불모의 고원에 영향을 덜 받습니다.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "182110bc-f952-4460-8048-d1df961ba860",
      "metadata": {},
      "source": [
        "<span id=\"summary\" />\n",
        "\n",
        "## 요약\n",
        "\n",
        "이 단원에서는 최적화 루프를 정의하는 방법을 배웠습니다:\n",
        "\n",
        "* 최적화 루프 부트스트랩\n",
        "* 로컬 및 글로벌 최적화 도구 사용 시 장단점 이해하기\n",
        "* 척박한 고원 탐험과 이를 피하는 방법\n",
        "\n",
        "높은 수준의 변형 워크로드가 완성되었습니다:\n",
        "\n",
        "![이제 기준 상태를 준비하는 단일체와 가변 파라미터를 사용하여 상태를 변화시키는 두 번째 단일체를 모두 갖춘 양자 회로입니다.](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-circuit.svg)\n",
        "\n",
        "다음으로 이 프레임워크를 염두에 두고 구체적인 변형 알고리즘을 살펴보겠습니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}