{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b6d1e3ec",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"ハイブリッド量子強化アンサンブル分類（系統安定性ワークフロー）\"\n",
        "description: \"Multiverse ComputingのSingularity Qiskit関数を用いて、 IBM 量子プロセッサ上でグリッド安定性分類のためのハイブリッド量子・古典アンサンブルを構築・分析する。\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore QEEC interpretability hyperparameters overfitting sublinear preds prec */}\n",
        "\n",
        "<span id=\"hybrid-quantum-enhanced-ensemble-classification-grid-stability-workflow\" />\n",
        "\n",
        "# ハイブリッド量子強化アンサンブル分類（系統安定性ワークフロー）\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a6f69b77",
      "metadata": {},
      "source": [
        "*使用量の見積もり：Eagle r3 プロセッサ上で各ジョブのQPU時間20分。 (注：これはあくまでも目安です。 実行時間は異なるかもしれない)。*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8bf80006",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## 背景\n",
        "\n",
        "このチュートリアルでは、量子最適化ステップを用いて古典的なアンサンブルを強化する、量子・古典ハイブリッドなワークフローについて解説します。 Multiverse Computingの「Singularity Machine Learning – Classification」（Qiskitの関数）を使用して、従来の学習アルゴリズム（例えば、決定木、k-NN、ロジスティック回帰など）のプールを学習させ、その後、量子レイヤーを用いてそのプールを微調整し、多様性と汎化性能を向上させます。 その目的は実用的なものです。実際の送電網の安定性予測タスクにおいて、同じデータ分割条件下で、強力な従来のベースライン手法と量子最適化された代替手法を比較することで、量子技術の導入がどこで効果を発揮し、どのようなコストを伴うのかを確認できるようにしています。\n",
        "\n",
        "なぜこれが重要なのか：多くの弱い学習者から良い部分集合を選択することは、アンサンブルのサイズとともに急速に大きくなる組み合わせ問題である。 ブースティング、バギング、スタッキングのような古典的なヒューリスティックは、中程度のスケールではうまく機能するが、大規模で冗長なモデルのライブラリを効率的に探索するのに苦労することがある。 この機能は、量子アルゴリズム、特にQAOA（他の構成ではオプションでVQE）を統合することで、古典的な学習者の学習後にその空間をより効率的に探索し、よりよく汎化するコンパクトで多様な部分集合を見つける可能性を高める。\n",
        "\n",
        "重要なのは、データのスケールが量子ビットに制限されないことだ。 前処理、学習者プールのトレーニング、評価といった、データに対する重労働は古典的なままであり、何百万もの例を扱うことができる。 キュービットは、量子選択ステップで使用されるアンサンブルサイズを決定するだけである。 このデカップリングこそが、今日のハードウェアで実行可能なアプローチなのだ。データとモデルトレーニングのための使い慣れたscikit-learnのワークフローを維持しながら、 Qiskit Functions のクリーンなアクションインターフェイスを通して量子ステップを呼び出すことができる。\n",
        "\n",
        "実際には、アンサンブルにさまざまなタイプの学習器を提供することができますが（決定木、ロジスティック回帰、k-NNなど）、決定木が最高のパフォーマンスを発揮する傾向があります。 オプティマイザは一貫して、より強力なアンサンブル・メンバーを優先します。異種学習者が供給される場合、線形回帰器などの弱いモデルは、決定木のような表現力の高いモデルを優先して刈り込まれるのが一般的です。\n",
        "\n",
        "ここで行うこと：グリッド安定性データセットの準備とバランス調整、古典的な AdaBoost ベースラインの確立、アンサンブル幅と正則化を変化させたいくつかの量子コンフィギュレーションの実行、 IBM® シミュレータまたは QPU 上での実行（ Qiskit Serverless ）、すべての実行における精度、正確度、再現率、 F1 の比較。 その過程で、関数のアクションパターン（`create`, `fit`, `predict`, `fit_predict`, `create_fit_predict` ）とキーコントロールを使います：\n",
        "\n",
        "* 正則化の種類： `onsite` (λ) は直接的なスパース性を、 `alpha` は相互作用項とオンサイト項の間の比率ベースのトレードオフを表す\n",
        "* 自動正則化： `regularization=\"auto\"` を目標選択率で設定し、スパース性を自動的に適応させる\n",
        "* オプティマイザーのオプション：シミュレータとQPUの比較、反復回数、従来型オプティマイザーとそのオプション、トランスパイルの深さ、および IBM Quantum のサンプラーまたはエスティメータの設定\n",
        "\n",
        "ドキュメントにあるベンチマークでは、学習者（量子ビット）の数が増えるにつれて精度が向上し、古典的なアンサンブルに匹敵するか、それを上回ることが示されている。 このチュートリアルでは、ワークフローをエンド・ツー・エンドで再現し、アンサンブル幅を大きくしたり、適応的正則化に切り替えたりすることで、妥当なリソース使用量でより良い F1。 その結果、実際のアプリケーションにおいて、量子最適化ステップが古典的なアンサンブル学習に取って代わるのではなく、それを補完することができるという、根拠のある見解が得られた。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "55b94021",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## 要件\n",
        "\n",
        "このチュートリアルを始める前に、 Python 環境に以下のパッケージがインストールされていることを確認してください：\n",
        "\n",
        "* `qiskit[visualization]~=2.1.0`\n",
        "* `qiskit-serverless~=0.24.0`\n",
        "* `qiskit-ibm-runtime v0.40.1`\n",
        "* `qiskit-ibm-catalog~=0.8.0`\n",
        "* `scikit-learn==1.5.2`\n",
        "* `pandas>=2.0.0,<3.0.0`\n",
        "* `imbalanced-learn~=0.12.3`\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "7db2e559",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## セットアップ\n",
        "\n",
        "このセクションでは、 Qiskit Serverless クライアントを初期化し、Multiverse Computing が提供する Singularity Machine Learning - Classification 関数をロードする。\n",
        "Qiskit Serverless を使えば、 IBM マネージド・クラウド・インフラストラクチャ上で、リソース管理を心配することなく、ハイブリッド量子クラシカル・ワークフローを実行することができる。\n",
        "認証して Qiskit Functions にアクセスするには、 IBM Quantum Platform API キーとクラウド リソース名 (CRN) が必要です。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d4fe7ee1-21ce-445c-b151-598cd4cf9227",
      "metadata": {},
      "source": [
        "<span id=\"download-the-dataset\" />\n",
        "\n",
        "### データセットをダウンロードする\n",
        "\n",
        "このチュートリアルを実行するには、ラベル付けされた電力系統センサーの測定値を含む、前処理済みの**系統安定性分類データセットを**使用します。\n",
        "次のセルは、必要なフォルダ構造を自動的に作成し、 `wget` を使用して、トレーニングファイルとテストファイルの両方をあなたの環境に直接ダウンロードします。\n",
        "これらのファイルがすでにローカルにある場合は、この手順で安全に上書きし、バージョンの一貫性を確保する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "7a32efb3-a425-4c02-804b-65029ecffb6f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "data_tutorial/grid_ 100%[===================>] 612.94K  --.-KB/s    in 0.01s   \n",
            "data_tutorial/grid_ 100%[===================>] 108.19K  --.-KB/s    in 0.006s  \n",
            "Dataset files downloaded:\n",
            "-rw-r--r-- 1 coder coder 109K Nov  8 18:50 data_tutorial/grid_stability/test.csv\n",
            "-rw-r--r-- 1 coder coder 613K Nov  8 18:50 data_tutorial/grid_stability/train.csv\n"
          ]
        }
      ],
      "source": [
        "## Download dataset for Grid Stability Classification\n",
        "\n",
        "# Create data directory if it doesn't exist\n",
        "!mkdir -p data_tutorial/grid_stability\n",
        "\n",
        "# Download the training and test sets from the official Qiskit documentation repo\n",
        "base_url = (\n",
        "    \"https://raw.githubusercontent.com/Qiskit/documentation/\"\n",
        "    \"main/datasets/tutorials/grid_stability\"\n",
        ")\n",
        "!wget -q --show-progress -O data_tutorial/grid_stability/train.csv {base_url}/train.csv\n",
        "\n",
        "!wget -q --show-progress -O data_tutorial/grid_stability/test.csv {base_url}/test.csv\n",
        "\n",
        "# Check the files have been downloaded\n",
        "!echo \"Dataset files downloaded:\"\n",
        "!ls -lh data_tutorial/grid_stability/*.csv"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bb9aa84f-ab37-412c-b056-7043b73380fa",
      "metadata": {},
      "source": [
        "<span id=\"import-required-packages\" />\n",
        "\n",
        "### 必要なパッケージをインポートする\n",
        "\n",
        "このセクションでは、チュートリアルを通して使用されるすべての Python パッケージと Qiskit モジュールをインポートします。\n",
        "これらのライブラリには、 `NumPy`、 `pandas`、 `scikit-learn` などのデータハンドリングとモデル評価のためのコア科学ライブラリと、量子強化モデルを実行するための可視化ツールとQiskitコンポーネントが含まれる。\n",
        "また、 IBM Quantum® サービスと接続し、シンギュラリティ Machine Learning 機能にアクセスするために、 `QiskitRuntimeService` と `QiskitFunctionsCatalog` をインポートする。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f8c654f5-8355-4f67-b79d-c2b1c29ccc62",
      "metadata": {},
      "outputs": [],
      "source": [
        "from pprint import pprint\n",
        "from typing import Tuple\n",
        "import warnings\n",
        "\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "from imblearn.over_sampling import RandomOverSampler\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "from sklearn.ensemble import AdaBoostClassifier\n",
        "from sklearn.metrics import (\n",
        "    accuracy_score,\n",
        "    f1_score,\n",
        "    precision_score,\n",
        "    recall_score,\n",
        ")\n",
        "from sklearn.model_selection import train_test_split\n",
        "\n",
        "warnings.filterwarnings(\"ignore\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b389b34-02e8-4a63-ae24-0bf348647b48",
      "metadata": {},
      "source": [
        "<span id=\"set-constant-variables\" />\n",
        "\n",
        "### 定数変数を設定する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "a68bf7df-914c-4b2a-827f-657578503750",
      "metadata": {},
      "outputs": [],
      "source": [
        "IBM_TOKEN = \"\"\n",
        "IBM_INSTANCE_TEST = \"\"\n",
        "IBM_INSTANCE_QUANTUM = \"\"\n",
        "FUNCTION_NAME = \"multiverse/singularity\"\n",
        "RANDOM_STATE: int = 123\n",
        "TRAIN_PATH = \"data_tutorial/grid_stability/train.csv\"\n",
        "TEST_PATH = \"data_tutorial/grid_stability/test.csv\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4709dc1c-b380-49f1-95c7-89197aa5e147",
      "metadata": {},
      "source": [
        "<span id=\"connect-to-ibm-quantum-and-load-the-singularity-function\" />\n",
        "\n",
        "### IBM Quantum に接続し、Singularity 機能をロードする\n",
        "\n",
        "次に、 IBM Quantum サービスで認証し、 Qiskit Functions Catalog から Singularity Machine Learning - Classification 関数をロードする。\n",
        "`QiskitRuntimeService` は、API トークンとインスタンス CRN を使用して IBM Quantum Platform へのセキュアな接続を確立し、量子バックエンドへのアクセスを許可します。\n",
        "`QiskitFunctionsCatalog` を使って特異点関数を名前（`\"multiverse/singularity\"` ）で取り出し、後でそれを呼び出してハイブリッド量子古典計算ができるようにする。\n",
        "セットアップに成功すると、機能が正しくロードされたことを示す確認メッセージが表示されます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bc380c46",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Successfully connected to IBM Qiskit Serverless and loaded the Singularity function.\n",
            "Catalog: <QiskitFunctionsCatalog>\n",
            "Singularity function: QiskitFunction(multiverse/singularity)\n"
          ]
        }
      ],
      "source": [
        "catalog = QiskitFunctionsCatalog(\n",
        "    token=IBM_TOKEN,\n",
        "    instance=IBM_INSTANCE_TEST,\n",
        "    channel=\"ibm_quantum_platform\",\n",
        ")\n",
        "backend = catalog.least_busy()\n",
        "\n",
        "singularity = catalog.load(FUNCTION_NAME)\n",
        "print(\n",
        "    \"Successfully connected to IBM Qiskit Serverless and \"\n",
        "    \"loaded the Singularity function.\"\n",
        ")\n",
        "print(\"Catalog:\", catalog)\n",
        "print(\"Singularity function:\", singularity)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "47d6a559-118a-4aa9-874d-9c009b5da60c",
      "metadata": {},
      "source": [
        "<span id=\"define-helper-functions\" />\n",
        "\n",
        "### ヘルパー関数を定義する\n",
        "\n",
        "主要な実験を実行する前に、データのロードとモデルの評価を効率化する小さなユーティリティ関数をいくつか定義する。\n",
        "\n",
        "* `load_data()` 入力 CSV ファイルを NumPy 配列に読み込み、 `scikit-learn` と量子ワークフローとの互換性を保つためにフィーチャーとラベルを分割する。\n",
        "* `evaluate_predictions()` は、主要なパフォーマンス・メトリクス（正確度、精度、再現率、 F1-score ）を計算し、タイミング情報が提供されている場合は、オプションで実行時間を報告します。\n",
        "\n",
        "これらのヘルパー関数は、ノートブックの後半で繰り返される操作を簡素化し、古典的分類器と量子分類器の両方で一貫したメトリックレポートを保証します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "46bc841e-7365-4508-b6bf-ae57db6050e1",
      "metadata": {},
      "outputs": [],
      "source": [
        "def load_data(data_path: str) -> Tuple[np.ndarray, np.ndarray]:\n",
        "    \"\"\"Load data from the given path to X and y arrays.\"\"\"\n",
        "    df: pd.DataFrame = pd.read_csv(data_path)\n",
        "    return df.iloc[:, :-1].values, df.iloc[:, -1].values\n",
        "\n",
        "\n",
        "def evaluate_predictions(predictions, y_true):\n",
        "    \"\"\"Compute and print accuracy, precision, recall, and F1 score.\"\"\"\n",
        "    accuracy = accuracy_score(y_true, predictions)\n",
        "    precision = precision_score(y_true, predictions)\n",
        "    recall = recall_score(y_true, predictions)\n",
        "    f1 = f1_score(y_true, predictions)\n",
        "    print(\"Accuracy:\", accuracy)\n",
        "    print(\"Precision:\", precision)\n",
        "    print(\"Recall:\", recall)\n",
        "    print(\"F1:\", f1)\n",
        "    return accuracy, precision, recall, f1"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "988ee237",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "## ステップ1：古典的な入力を量子問題にマッピングする\n",
        "\n",
        "まず、ハイブリッド量子古典実験のためのデータセットを準備する。 このステップの目的は、生のグリッド安定性データを、古典的ワークフローと量子ワークフローの両方で一貫して使用できる、バランスの取れたトレーニング、検証、テスト分割に変換することである。 同一のスプリットを維持することで、後のパフォーマンス比較が公平で再現性のあるものになる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1c084cde-a5cf-4661-a00c-aa243c8b0e44",
      "metadata": {},
      "source": [
        "<span id=\"data-loading-and-preprocessing\" />\n",
        "\n",
        "### データの読み込みと前処理\n",
        "\n",
        "まずトレーニング用とテスト用のCSVファイルを読み込み、検証用の分割を作成し、ランダム・オーバーサンプリングを使ってデータセットのバランスをとる。 バランスをとることで、多数派クラスへの偏りを防ぎ、古典的アンサンブルモデルでも量子アンサンブルモデルでも、より安定した学習信号を得ることができる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "0db0e914-a8f2-4a04-bec7-c15bac8104b4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Shapes:\n",
            "  X_train_bal: (5104, 12)\n",
            "  y_train_bal: (5104,)\n",
            "  X_val: (850, 12)\n",
            "  y_val: (850,)\n",
            "  X_test: (750, 12)\n",
            "  y_test: (750,)\n"
          ]
        }
      ],
      "source": [
        "# Load and upload the data\n",
        "X_train, y_train = load_data(TRAIN_PATH)\n",
        "X_test, y_test = load_data(TEST_PATH)\n",
        "X_train, X_val, y_train, y_val = train_test_split(\n",
        "    X_train, y_train, test_size=0.2, random_state=RANDOM_STATE\n",
        ")\n",
        "\n",
        "# Balance the dataset through over-sampling of the positive class\n",
        "ros = RandomOverSampler(random_state=RANDOM_STATE)\n",
        "X_train_bal, y_train_bal = ros.fit_resample(X_train, y_train)\n",
        "\n",
        "print(\"Shapes:\")\n",
        "print(\"  X_train_bal:\", X_train_bal.shape)\n",
        "print(\"  y_train_bal:\", y_train_bal.shape)\n",
        "print(\"  X_val:\", X_val.shape)\n",
        "print(\"  y_val:\", y_val.shape)\n",
        "print(\"  X_test:\", X_test.shape)\n",
        "print(\"  y_test:\", y_test.shape)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b8c214fd-09a8-4fa5-ab83-b0c71ad615d4",
      "metadata": {},
      "source": [
        "<span id=\"classical-baseline-adaboost-reference\" />\n",
        "\n",
        "### 古典的ベースライン: AdaBoost 参照\n",
        "\n",
        "量子最適化を実行する前に、古典的な強力なベースライン（標準的な AdaBoost 分類器）を同じバランスデータで訓練する。 これは、後の比較のための再現可能な基準点を提供し、量子最適化が、よく調整された古典的アンサンブルを超える汎化や効率を向上させるかどうかを定量化するのに役立つ。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "38ecd608-35b4-4e58-8a16-85ef98bf024a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Classical AdaBoost baseline:\n",
            "Accuracy: 0.7893333333333333\n",
            "Precision: 1.0\n",
            "Recall: 0.7893333333333333\n",
            "F1: 0.8822652757078987\n"
          ]
        }
      ],
      "source": [
        "# ----- Classical baseline: AdaBoost -----\n",
        "baseline = AdaBoostClassifier(n_estimators=60, random_state=RANDOM_STATE)\n",
        "baseline.fit(X_train_bal, y_train_bal)\n",
        "baseline_pred = baseline.predict(X_test)\n",
        "print(\"Classical AdaBoost baseline:\")\n",
        "_ = evaluate_predictions(baseline_pred, y_test)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ac6f36e3",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "## ステップ2：量子ハードウェア実行に向けた問題の最適化\n",
        "\n",
        "アンサンブル選択課題は、各弱学習モデルを二値決定変数とする組み合わせ最適化問題として定式化され、目的関数は正則化項を通じて精度とスパース性のバランスをとるように設定される。 この `QuantumEnhancedEnsembleClassifier` 手法は、 IBM ハードウェア上でQAOAを用いてこの問題を解決すると同時に、シミュレータを用いた探索も可能にしています。 ハイブリッドループの制御 `optimizer_options` ：回路を選択したQPUにルーティング `simulator=False` し、探索幅を拡大 `num_solutions` し、（ `classical_optimizer_options` 内部の古典的オプティマイザーについては）収束を制御します。反復回数を60回前後にすることで、品質と実行時間のバランスが良好になります。 量子コンピューティングのオプション（適度な回路深度（`reps`）や標準的なトランスパイレーション作業など）は、さまざまなデバイスにおいて堅牢なパフォーマンスを確保するのに役立ちます。 以下の設定は、ハードウェア実行に使用する「ベストリザルト」プロファイルです。また、を切り替えることで、QPU時間を消費せずにワークフローをドライラン `simulator=True` する、純粋なシミュレーション版を作成することも可能です。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "18c0d3f9-691b-449d-83ca-e6bfce2d6b99",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Configured hardware optimization profile:\n",
            "  simulator: False\n",
            "  num_solutions: 100000\n",
            "  reps: 3\n",
            "  optimization_level: 3\n",
            "  num_transpiler_runs: 30\n",
            "  classical_optimizer: COBYLA\n",
            "  classical_optimizer_options: {'maxiter': 60}\n",
            "  estimator_options: None\n",
            "  sampler_options: None\n"
          ]
        }
      ],
      "source": [
        "# QAOA / runtime configuration for best results on hardware\n",
        "optimizer_options = {\n",
        "    \"simulator\": False,  # set True to test locally without QPU\n",
        "    \"num_solutions\": 100_000,  # broaden search over candidate ensembles\n",
        "    \"reps\": 3,  # QAOA depth (circuit layers)\n",
        "    \"optimization_level\": 3,  # transpilation effort\n",
        "    \"num_transpiler_runs\": 30,  # explore multiple layouts\n",
        "    \"classical_optimizer\": \"COBYLA\",  # robust default for this landscape\n",
        "    \"classical_optimizer_options\": {\n",
        "        \"maxiter\": 60  # practical convergence budget\n",
        "    },\n",
        "    # You can pass backend-specific options;\n",
        "    # leaving None uses least-busy routing\n",
        "    \"estimator_options\": None,\n",
        "    \"sampler_options\": None,\n",
        "}\n",
        "\n",
        "print(\"Configured hardware optimization profile:\")\n",
        "for key, value in optimizer_options.items():\n",
        "    print(f\"  {key}: {value}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "b4d480b3",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "## ステップ3: `Qiskit primitives`を使用して実行する\n",
        "\n",
        "次に、Singularity関数の `create_fit_predict` アクションを使用して、 IBM インフラストラクチャ上で `QuantumEnhancedEnsembleClassifier` をエンドツーエンドで学習、最適化、評価するワークフローを実行します。 この関数はアンサンブルを構築し、 Qiskit primitives を介して量子最適化を適用し、予測とジョブのメタデータ（実行時間とリソース使用量を含む）の両方を返します。 ステップ1からの古典的なデータ分割は再現性のために再利用され、検証データは `fit_params` 、最適化が内部でハイパーパラメータを調整できるようにする。\n",
        "\n",
        "このステップでは、量子アンサンブルの構成をいくつか検討し、重要なパラメータ（特に `num_learners` と `regularization` ）が結果の質とQPUの使用量の両方にどのように影響するかを理解する。\n",
        "\n",
        "* `num_learners` はアンサンブルの幅（そして暗黙のうちに量子ビットの数）を決定し、モデルの容量と計算コストに影響を与える。\n",
        "* `regularization` はスパース性とオーバーフィッティングを制御し、最適化後にどれだけの学習者がアクティブな状態を維持するかを決定する。\n",
        "\n",
        "これらのパラメータを変化させることで、アンサンブルの幅と正則化がどのように相互作用するかを見ることができる。幅を大きくすると、一般的に F1、より多くのQPU時間がかかる。一方、より強い正則化や適応的な正則化は、ほぼ同じハードウェアフットプリントで汎化を改善することができる。 次のサブセクションでは、これらの効果を説明するために3つの代表的なコンフィギュレーションを説明する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8da41d4d-f06d-4b67-a8ee-b07fc0289558",
      "metadata": {},
      "source": [
        "<span id=\"baseline\" />\n",
        "\n",
        "### ベースライン\n",
        "\n",
        "この構成では、 `num_learners = 10` と `regularization = 7` を使用する。\n",
        "\n",
        "* `num_learners` アンサンブルの幅を制御する。事実上、弱学習器の組み合わせ数であり、量子ハードウェア上では、 **必要な量子ビット数**である。 値を大きくすると、組み合わせ探索空間が広がり、精度と再現性が向上するが、回路幅、コンパイル時間、QPU全体の使用量も増加する。\n",
        "* `regularization` は、追加学習者を含む場合のペナルティの強さを設定する。 デフォルトの \"onsite \"正則化では、高い値ほど強いスパース性（保持する学習者の数が少ない）を強制し、低い値ほど複雑なアンサンブルを可能にする。\n",
        "\n",
        "このセットアップは、幅を拡大したり、スパース性を調整したりする前に、小さなアンサンブルがどのように振る舞うかを示す、低コストのベースラインを提供する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "e702c986-fd7f-4ea1-a93c-8cd5ef0c4a0b",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Problem scale and regularization\n",
        "NUM_LEARNERS = 10\n",
        "REGULARIZATION = 7"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "06c261c1-a3c1-42c9-a522-63f3fc01a970",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "-- Submitting quantum-enhanced ensemble job --\n",
            "Action status: ok\n",
            "Action message: Classifier created, fitted, and predicted.\n",
            "Metadata:\n",
            "{'resource_usage': {'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1550.1889700889587},\n",
            "                    'RUNNING: MAPPING': {'CPU_TIME': 267.05158376693726},\n",
            "                    'RUNNING: POST_PROCESSING': {'CPU_TIME': 152.4274561405182},\n",
            "                    'RUNNING: WAITING_QPU': {'CPU_TIME': 3336.8785166740417}}}\n",
            "Accuracy: 0.868\n",
            "Precision: 1.0\n",
            "Recall: 0.868\n",
            "F1: 0.9293361884368309\n"
          ]
        }
      ],
      "source": [
        "# ----- Quantum-enhanced ensemble on IBM hardware -----\n",
        "print(\"\\n-- Submitting quantum-enhanced ensemble job --\")\n",
        "job_1 = singularity.run(\n",
        "    action=\"create_fit_predict\",\n",
        "    name=\"grid_stability_qeec\",\n",
        "    quantum_classifier=\"QuantumEnhancedEnsembleClassifier\",\n",
        "    num_learners=NUM_LEARNERS,\n",
        "    regularization=REGULARIZATION,\n",
        "    optimizer_options=optimizer_options,  # from Step 2\n",
        "    backend_name=backend,  # least-busy compatible backend\n",
        "    instance=IBM_INSTANCE_QUANTUM,\n",
        "    random_state=RANDOM_STATE,\n",
        "    X_train=X_train_bal,\n",
        "    y_train=y_train_bal,\n",
        "    X_test=X_test,\n",
        "    fit_params={\"validation_data\": (X_val, y_val)},\n",
        "    options={\"save\": False},\n",
        ")\n",
        "result_1 = job_1.result()\n",
        "print(\"Action status:\", result_1.get(\"status\"))\n",
        "print(\"Action message:\", result_1.get(\"message\"))\n",
        "print(\"Metadata:\")\n",
        "pprint(result_1.get(\"metadata\"))\n",
        "qeec_pred_job_1 = np.array(result_1[\"data\"][\"predictions\"])\n",
        "_ = evaluate_predictions(qeec_pred_job_1, y_test)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "1bf0a3ae-b5b8-43d7-b72d-5a9cf6c61060",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "Quantum job status: DONE\n"
          ]
        }
      ],
      "source": [
        "status_1 = job_1.status()\n",
        "print(\"\\nQuantum job status:\", status_1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ae62b414-db77-45aa-bf2c-a8537fd7eba0",
      "metadata": {},
      "source": [
        "<span id=\"increase-the-number-of-learners\" />\n",
        "\n",
        "### 学習者の数を増やす\n",
        "\n",
        "ここでは、 `regularization = 7` を維持したまま、 `num_learners` を 10 から 30 に増やす。\n",
        "\n",
        "* 学習者が増えることで、仮説空間が広がり、モデルがより微妙なパターンを捉えることができるようになり、 F1。\n",
        "* ほとんどの場合、10人学習者と30人学習者の実行時間の差はそれほど大きくなく、回路幅の追加による実行コストの大幅な増加はないことを示している。\n",
        "* 品質の向上は、やはり*逓減リターン曲線に*従う。アンサンブルの成長とともに初期の利益は現れるが、学習者の追加による新しい情報の貢献が少なくなるにつれて、利益は頭打ちになる。\n",
        "\n",
        "この実験は、品質と効率のトレードオフを浮き彫りにしている。アンサンブルの幅を大きくすれば、バックエンドとトランスピレーションの条件によっては、大きなランタイム・ペナルティなしに、わずかな精度の向上が得られるかもしれない。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "e5fe64b0-2713-4b65-b768-10fa5d8dbf79",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Problem scale and regularization\n",
        "NUM_LEARNERS = 30\n",
        "REGULARIZATION = 7"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "18a22fed-41c2-4407-88d4-02fbd32f3320",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "-- Submitting quantum-enhanced ensemble job --\n",
            "Action status: ok\n",
            "Action message: Classifier created, fitted, and predicted.\n",
            "QPU Time:\n",
            "{'resource_usage': {'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1095.822762966156},\n",
            "                    'RUNNING: MAPPING': {'CPU_TIME': 680.2116754055023},\n",
            "                    'RUNNING: POST_PROCESSING': {'CPU_TIME': 154.4466371536255},\n",
            "                    'RUNNING: WAITING_QPU': {'CPU_TIME': 80.80395102500916}}}\n",
            "Accuracy: 0.8946666666666667\n",
            "Precision: 1.0\n",
            "Recall: 0.8946666666666667\n",
            "F1: 0.944405348346235\n"
          ]
        }
      ],
      "source": [
        "# ----- Quantum-enhanced ensemble on IBM hardware -----\n",
        "print(\"\\n-- Submitting quantum-enhanced ensemble job --\")\n",
        "job_2 = singularity.run(\n",
        "    action=\"create_fit_predict\",\n",
        "    name=\"grid_stability_qeec\",\n",
        "    quantum_classifier=\"QuantumEnhancedEnsembleClassifier\",\n",
        "    num_learners=NUM_LEARNERS,\n",
        "    regularization=REGULARIZATION,\n",
        "    optimizer_options=optimizer_options,  # from Step 2\n",
        "    backend_name=backend,  # least-busy compatible backend\n",
        "    instance=IBM_INSTANCE_QUANTUM,\n",
        "    random_state=RANDOM_STATE,\n",
        "    X_train=X_train_bal,\n",
        "    y_train=y_train_bal,\n",
        "    X_test=X_test,\n",
        "    fit_params={\"validation_data\": (X_val, y_val)},\n",
        "    options={\"save\": False},\n",
        ")\n",
        "result_2 = job_2.result()\n",
        "print(\"Action status:\", result_2.get(\"status\"))\n",
        "print(\"Action message:\", result_2.get(\"message\"))\n",
        "print(\"QPU Time:\")\n",
        "pprint(result_2.get(\"metadata\"))\n",
        "qeec_pred_job_2 = np.array(result_2[\"data\"][\"predictions\"])\n",
        "_ = evaluate_predictions(qeec_pred_job_2, y_test)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "edd22b98-7ae6-4444-8fe5-7279e9233c57",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "Quantum job status: DONE\n"
          ]
        }
      ],
      "source": [
        "status_2 = job_2.status()\n",
        "print(\"\\nQuantum job status:\", status_2)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5e94784a-3599-4911-ade9-4792b50c31bb",
      "metadata": {},
      "source": [
        "<span id=\"regularization\" />\n",
        "\n",
        "### 正則化\n",
        "\n",
        "この構成では、 `num_learners = 60` 、より直感的にスパース性を管理するために適応的正則化を導入する。\n",
        "\n",
        "* `regularization = \"auto\"` を使うと、オプティマイザは、ペナルティを手動で修正するのではなく、最終的なアンサンブルにおよそ `regularization_ratio * num_learners` の弱い学習者を選択する適切な正則化の強さを自動的に見つける。 これにより、スパース性とアンサンブル・サイズのバランスを管理するための、より便利なインターフェイスが提供される。\n",
        "* `regularization_type = \"alpha\"` はペナルティの適用方法を定義する。 Unlike `onsite`, which is unbounded `[0, ∞]`, `alpha` is bounded between `[0, 1]`, making it easier to tune and interpret. このパラメータは、個別ペナルティとペアワイズペナルティのトレードオフを制御し、よりスムーズな構成範囲を提供する。\n",
        "* `regularization_desired_ratio ≈ 0.82` は、正則化後にアクティブな状態を維持する学習者の割合を指定する。ここでは、約82%の学習者が保持され、最も弱い18%は自動的に切り捨てられる。\n",
        "\n",
        "適応的正則化はコンフィギュレーションを単純化し、バランスのとれたアンサンブルを維持するのに役立つが、必ずしも性能の向上や安定を保証するものではない。 実際の品質は、適切な正則化パラメータを選択することに依存し、クロスバリデーションによって微調整することは計算コストがかかる。 主な利点は、直接的な精度の向上よりも、使いやすさと解釈のしやすさの向上にある。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "209eb51a-e44b-4f94-8975-269ec7e3d1ca",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Problem scale and regularization\n",
        "NUM_LEARNERS = 60\n",
        "REGULARIZATION = \"auto\"\n",
        "REGULARIZATION_TYPE = \"alpha\"\n",
        "REGULARIZATION_RATIO = 0.82"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "eb2aa9db-4427-48de-aae0-c5c1da1cb998",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "-- Submitting quantum-enhanced ensemble job --\n",
            "Action status: ok\n",
            "Action message: Classifier created, fitted, and predicted.\n",
            "Metadata:\n",
            "{'resource_usage': {'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1146.5584812164307},\n",
            "                    'RUNNING: MAPPING': {'CPU_TIME': 1387.7451872825623},\n",
            "                    'RUNNING: POST_PROCESSING': {'CPU_TIME': 171.78878355026245},\n",
            "                    'RUNNING: WAITING_QPU': {'CPU_TIME': 95.41597843170166}}}\n",
            "Accuracy: 0.908\n",
            "Precision: 1.0\n",
            "Recall: 0.908\n",
            "F1: 0.9517819706498952\n"
          ]
        }
      ],
      "source": [
        "# ----- Quantum-enhanced ensemble on IBM hardware -----\n",
        "print(\"\\n-- Submitting quantum-enhanced ensemble job --\")\n",
        "job_3 = singularity.run(\n",
        "    action=\"create_fit_predict\",\n",
        "    name=\"grid_stability_qeec\",\n",
        "    quantum_classifier=\"QuantumEnhancedEnsembleClassifier\",\n",
        "    num_learners=NUM_LEARNERS,\n",
        "    regularization=REGULARIZATION,\n",
        "    regularization_type=REGULARIZATION_TYPE,\n",
        "    regularization_desired_ratio=REGULARIZATION_RATIO,\n",
        "    optimizer_options=optimizer_options,  # from Step 2\n",
        "    backend_name=backend,  # least-busy compatible backend\n",
        "    instance=IBM_INSTANCE_QUANTUM,\n",
        "    random_state=RANDOM_STATE,\n",
        "    X_train=X_train_bal,\n",
        "    y_train=y_train_bal,\n",
        "    X_test=X_test,\n",
        "    fit_params={\"validation_data\": (X_val, y_val)},\n",
        "    options={\"save\": False},\n",
        ")\n",
        "result_3 = job_3.result()\n",
        "print(\"Action status:\", result_3.get(\"status\"))\n",
        "print(\"Action message:\", result_3.get(\"message\"))\n",
        "print(\"Metadata:\")\n",
        "pprint(result_3.get(\"metadata\"))\n",
        "qeec_pred_job_3 = np.array(result_3[\"data\"][\"predictions\"])\n",
        "_ = evaluate_predictions(qeec_pred_job_3, y_test)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "299b36cb-0ed8-4af3-b431-a87daec04c93",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "Quantum job status: DONE\n"
          ]
        }
      ],
      "source": [
        "status_3 = job_3.status()\n",
        "print(\"\\nQuantum job status:\", status_3)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "50b94af2",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-result-in-desired-classical-format\" />\n",
        "\n",
        "## ステップ4：後処理を行い、結果を希望の古典形式で返す\n",
        "\n",
        "現在、古典と量子の両ランからの出力を後処理し、下流の評価のために一貫したフォーマットに変換している。 このステップでは、標準的な測定基準（正確度、精度、再現性、 F1 ）を使用して予測品質を比較し、アンサンブル幅（`num_learners` ）とスパース制御（`regularization` ）が性能と計算動作の両方にどのように影響するかを分析する。\n",
        "\n",
        "古典的な AdaBoost ベースラインは、小規模な学習のためのコンパクトで安定した基準を提供する。 限られたアンサンブルとごくわずかな計算オーバーヘッドで優れた性能を発揮し、仮説空間がまだ扱いやすい場合の伝統的なブースティングの強みを反映している。 量子コンフィギュレーション（`qeec_pred_job_1`、 `qeec_pred_job_2`、 `qeec_pred_job_3` ）は、アンサンブル選択プロセスを変分量子最適化ループに組み込むことで、このベースラインを拡張している。 これにより、システムは指数関数的に大きな学習者の部分集合を重ね合わせながら同時に探索することができ、規模が大きくなるにつれてアンサンブル選択の組み合わせ論的性質により効率的に対処することができる。\n",
        "\n",
        "その結果、 `num_learners` を10から30に増やすと、リコールと F1 が向上することがわかった。これは、より広いアンサンブルによって、弱い学習者間の相互作用がより豊かに捉えられることを裏付けている。 しかし、量子オプティマイザは、古典的な部分集合選択にありがちな指数関数的なブローアップを起こすことなく、より広い構成空間を探索することができるため、基本的なスケーリング挙動は良好なままである。 正則化にはさらにニュアンスが加わる。固定λ=7は一貫したスパース性を強制し、収束を安定させるが、適応的α正則化は学習者間の相関に基づいてスパース性を自動的に調整する。 この動的な刈り込みによって、同じ量子ビット幅で F1、モデルの複雑さと汎化のバランスをとりながら、わずかに高い値を達成することが多い。\n",
        "\n",
        "ベースライン（ AdaBoost ）と直接比較すると、最小の量子コンフィギュレーション（ L=10 ）でも同様の精度が再現され、ハイブリッドパイプラインの正しさが検証された。 量子化幅が大きくなると、特に自動正則化によって、古典的なベースラインをわずかに上回るようになり、計算コストが直線的に増加することなく、リコールと F1。 古典的なアプローチでは部分集合選択の複雑さが指数関数的に増大するのに対し、量子オプティマイザはアンサンブルの**拡大に応じて**扱いやすい性能を維持する。\n",
        "\n",
        "実際には\n",
        "\n",
        "* 小規模なデータセットでの迅速な検証やベンチマークには、 **古典的なベースラインを**使用します。\n",
        "* モデルの幅や特徴量の複雑さが増すと、 **量子アンサンブルを**適用する-QAOAベースの探索は、そのような領域でより優雅にスケールする。\n",
        "* 回路幅を増やすことなく、スパース性と汎化性を維持するために**適応的なα正則化を**採用。\n",
        "* QPUの時間と深さを監視し、品質向上と短期的なハードウェア制約のバランスをとる。\n",
        "\n",
        "これらの実験結果を総合すると、量子最適化アンサンブルは古典的手法を補完するものであり、小さなスケールでベースラインの精度を再現すると同時に、より大きな組合せ学習問題に対して効率的なスケーリングへの道を提供するものであることがわかる。 ハードウェアが進歩すればするほど、このようなスケーリングの利点はさらに大きくなり、アンサンブルベースのモデルの実現可能なサイズと深さは、古典的に実用的なものよりも拡大すると予想される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1cf1d610-f2e2-482c-af05-a882bb380528",
      "metadata": {},
      "source": [
        "<span id=\"evaluate-metrics-for-each-configuration\" />\n",
        "\n",
        "### 各構成のメトリクスを評価する\n",
        "\n",
        "次に、 `evaluate_predictions` ヘルパーを使用して、同じテストセットで精度、正確度、再現率、 F1 を計算し、すべての構成（古典的な AdaBoost ベースラインと3つの量子アンサンブル）を評価する。 この比較により、量子最適化が古典的アプローチと比較してどのようにスケールアップするかが明らかになった。小さな幅では、どちらも同じようなパフォーマンスを示すが、アンサンブルが大きくなるにつれて、量子法はより大きな仮説空間をより効率的に探索できるようになる。 この表は、これらの傾向を一貫性のある定量的な形で捉えたものである。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "ee8cc821-8311-4c84-8f94-ffb2ec3facc3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Accuracy: 0.7893333333333333\n",
            "Precision: 1.0\n",
            "Recall: 0.7893333333333333\n",
            "F1: 0.8822652757078987\n",
            "Accuracy: 0.868\n",
            "Precision: 1.0\n",
            "Recall: 0.868\n",
            "F1: 0.9293361884368309\n",
            "Accuracy: 0.8946666666666667\n",
            "Precision: 1.0\n",
            "Recall: 0.8946666666666667\n",
            "F1: 0.944405348346235\n",
            "Accuracy: 0.908\n",
            "Precision: 1.0\n",
            "Recall: 0.908\n",
            "F1: 0.9517819706498952\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>Config</th>\n",
              "      <th>Accuracy</th>\n",
              "      <th>Precision</th>\n",
              "      <th>Recall</th>\n",
              "      <th>F1</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>AdaBoost (Classical)</td>\n",
              "      <td>0.789333</td>\n",
              "      <td>1.0</td>\n",
              "      <td>0.789333</td>\n",
              "      <td>0.882265</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>QEEC L=10, reg=7</td>\n",
              "      <td>0.868000</td>\n",
              "      <td>1.0</td>\n",
              "      <td>0.868000</td>\n",
              "      <td>0.929336</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>QEEC L=30, reg=7</td>\n",
              "      <td>0.894667</td>\n",
              "      <td>1.0</td>\n",
              "      <td>0.894667</td>\n",
              "      <td>0.944405</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>QEEC L=60, reg=auto (α=0.82)</td>\n",
              "      <td>0.908000</td>\n",
              "      <td>1.0</td>\n",
              "      <td>0.908000</td>\n",
              "      <td>0.951782</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "                         Config  Accuracy  Precision    Recall        F1\n",
              "0          AdaBoost (Classical)  0.789333        1.0  0.789333  0.882265\n",
              "1              QEEC L=10, reg=7  0.868000        1.0  0.868000  0.929336\n",
              "2              QEEC L=30, reg=7  0.894667        1.0  0.894667  0.944405\n",
              "3  QEEC L=60, reg=auto (α=0.82)  0.908000        1.0  0.908000  0.951782"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "results = []\n",
        "\n",
        "# Classical baseline\n",
        "acc_b, prec_b, rec_b, f1_b = evaluate_predictions(baseline_pred, y_test)\n",
        "results.append(\n",
        "    {\n",
        "        \"Config\": \"AdaBoost (Classical)\",\n",
        "        \"Accuracy\": acc_b,\n",
        "        \"Precision\": prec_b,\n",
        "        \"Recall\": rec_b,\n",
        "        \"F1\": f1_b,\n",
        "    }\n",
        ")\n",
        "\n",
        "# Quantum runs\n",
        "for label, preds in [\n",
        "    (\"QEEC L=10, reg=7\", qeec_pred_job_1),\n",
        "    (\"QEEC L=30, reg=7\", qeec_pred_job_2),\n",
        "    (f\"QEEC L=60, reg=auto (α={REGULARIZATION_RATIO})\", qeec_pred_job_3),\n",
        "]:\n",
        "    acc, prec, rec, f1 = evaluate_predictions(preds, y_test)\n",
        "    results.append(\n",
        "        {\n",
        "            \"Config\": label,\n",
        "            \"Accuracy\": acc,\n",
        "            \"Precision\": prec,\n",
        "            \"Recall\": rec,\n",
        "            \"F1\": f1,\n",
        "        }\n",
        "    )\n",
        "\n",
        "\n",
        "df_results = pd.DataFrame(results)\n",
        "df_results"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "704cecf6-2c87-4356-b9be-26f4346c194f",
      "metadata": {},
      "source": [
        "<span id=\"visualize-quality-trends-across-configurations\" />\n",
        "\n",
        "### 構成全体にわたる品質の傾向を可視化する\n",
        "\n",
        "以下のグループ化された棒グラフは、古典的ベースラインと量子アンサンブルで\\*\\*精度と \\*\\***F1** を、古典的ベースラインと量子アンサンブル（`L=10`, `L=30`, `L=60 auto-α` ）で比較しています。 また、量子アンサンブルの幅が大きくなるにつれて、 F1 が徐々に改善される一方で、精度が安定する様子を示しており、古典的な部分集合選択に典型的な指数関数的なコスト増加を伴わずに、ハイブリッド手法が性能スケーリングを維持できることを示している。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "0f15c5fb-2450-4671-9bc2-471043414df2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/sml-classification/extracted-outputs/0f15c5fb-2450-4671-9bc2-471043414df2-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "x = np.arange(len(df_results))\n",
        "width = 0.35\n",
        "plt.figure(figsize=(7.6, 4.6))\n",
        "plt.bar(x - width / 2, df_results[\"Accuracy\"], width=width, label=\"Accuracy\")\n",
        "plt.bar(x + width / 2, df_results[\"F1\"], width=width, label=\"F1\")\n",
        "plt.xticks(x, df_results[\"Config\"], rotation=10)\n",
        "plt.ylabel(\"Score\")\n",
        "plt.title(\"Classical vs Quantum ensemble performance\")\n",
        "plt.legend()\n",
        "plt.ylim(0, 1.0)\n",
        "plt.tight_layout()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "745cd406-5166-4eb9-8506-0eedd71e9b79",
      "metadata": {},
      "source": [
        "<span id=\"interpretation\" />\n",
        "\n",
        "### 解釈\n",
        "\n",
        "このプロットは、予想されたスケーリングパターンを確認するものである。 古典的な AdaBoost は、より小さなアンサンブルに対しては強力な性能を発揮するが、弱い学習者の数が増えるにつれて、その部分集合選択問題が組合せ論的に拡大するため、スケールするのにますますコストがかかるようになる。 量子強化されたモデルは、低い幅では古典的な精度を再現し、アンサンブルサイズが大きくなるにつれて、特に適応的なα正則化の下では、古典的な精度を上回り始める。 これは、量子オプティマイザが重ね合わせによって多数の候補部分集合を並列にサンプリングし評価する能力を持ち、より高い幅でも扱いやすい探索を維持できることを反映している。 現在のハードウェアのオーバーヘッドは、理論的な利得の一部を相殺するが、この傾向は、量子定式化のスケーリング効率の優位性を示している。 実用面では、古典的な手法は軽量なベンチマークに適している。一方、量子拡張アンサンブルは、モデルの次元とアンサンブルサイズが拡大するにつれて、精度、汎化、計算量の増加のトレードオフが改善され、有利になる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a27afb68-f959-4f4a-910c-0aadafb7e18e",
      "metadata": {},
      "source": [
        "<span id=\"appendix-scaling-benefits-and-enhancements\" />\n",
        "\n",
        "## 付録：スケーリングの利点と強化\n",
        "\n",
        "`QuantumEnhancedEnsembleClassifier` のスケーラビリティの利点は、アンサンブル選択プロセスが量子最適化にどのようにマッピングされるかに起因する。\n",
        "AdaBoost、ランダムフォレストなどの古典的なアンサンブル学習法は、最適な部分集合を選択することが指数関数的にスケールする組み合わせ問題であるため、弱い学習者の数が増えるにつれて計算コストが高くなる。\n",
        "\n",
        "対照的に、量子近似最適化アルゴリズム（QAOA）により実装された量子定式化では、重ね合わせた複数のコンフィギュレーションを評価することで、指数関数的に大きな探索空間をより効率的に探索することができる。\n",
        "その結果、学習者数に応じて学習時間が大幅に増加することはなく、アンサンブルの幅が広がっても効率的なモデルを維持することができる。\n",
        "\n",
        "現在のハードウェアでは、ノイズや深さの制限があるが、このワークフローは、古典的なコンポーネントと量子コンポーネントが協力する、近い将来のハイブリッドアプローチを示している。\n",
        "量子プロセッサーが進化するにつれて、こうしたスケーラビリティの利点は、より大きなデータセット、より広範なアンサンブル、より深い回路深度へと拡大することが期待される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ee41a301",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## 参照\n",
        "\n",
        "1. [入門 Qiskit Functions](/docs/guides/functions)\n",
        "2. [マルチバース・コンピューティング・シンギュラリティ Machine Learning](/docs/guides/multiverse-computing-singularity)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2cb5785c",
      "metadata": {},
      "source": [
        "<span id=\"tutorial-survey\" />\n",
        "\n",
        "## チュートリアル調査\n",
        "\n",
        "このチュートリアルに関するフィードバックをお寄せください。 あなたの洞察は、私たちのコンテンツの提供とユーザーエクスペリエンスを向上させるのに役立ちます。\n",
        "\n",
        "[アンケートへのリンク](https://your.feedback.ibm.com/jfe/form/SV_3BLFkNVEuh0QBWm)\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"
    },
    "hours": 2,
    "qpuSeconds": 1200
  },
  "nbformat": 4,
  "nbformat_minor": 5
}