はじめに
みなさん、こんにちは。IBM Bob + 量子コンピュータの第3弾です。今回は、機械学習モデルを実装してみようと思います。
もっと勉強してからでないと、私には到底無理なんですがIBM Bobが一緒なら量子コンピュータで機械学習モデルを触れるような時代になりました。
今回は、量子SVM + Irisデータで分類問題にチャレンジします。
IBM Quantum の無料アカウントと Python があれば誰でも試せます。
※.量子コンピュータの実機を使うためには、IBM IDとIBM Quantum Platformへのユーザー登録(無料)が必要となります。
各種プログラムはGithubにアップロードしています。ご自由ダウンロードしてください。
リポジトリ構成
.
├── requirements.txt # pip install -r requirements.txt
├── setup_ibmq.py # 接続確認(python setup_ibmq.py API_KEY)
├── data_prep.py # データ前処理
├── qsvm_simulator.py # シミュレーター実行
├── qsvm_real_device.py # 実機実行(python qsvm_real_device.py API_KEY)
└── visualize.py # 結果可視化
目次
1. QSVM の仕組み — 量子の力をどう使うか
1-1. SVM のおさらい
① 一番シンプルなケース — 直線で分けられるとき
SVM の仕事は「2つのグループを仕切る境界線を引くこと」です。
ただし、境界線はどこに引いてもよいわけではありません。SVM は 両グループから最も遠い位置 に境界を引きます。この「余白」を マージン と呼び、マージンが大きいほど未知データに強くなります。
マージンの端にある点(境界に最も近いデータ)を サポートベクター と呼びます。これが名前の由来です。
② 直線で分けられないとき — カーネルの出番
現実のデータはきれいに直線で分けられないことがほとんどです。
このとき SVM は カーネル関数 というトリックを使います。
カーネルのイメージ
平らなテーブルに置かれた丸と四角のコインを分けたいとします。平面では線を引けませんが、テーブルをポンと叩いて空中に浮かせる(= 3次元に持ち上げる)と、高さで分けられる! それがカーネルの発想です。
重要なのは、高次元に実際に移動させる必要はない ということです。カーネル関数は「2点が高次元でどのくらい似ているか(内積)」を直接計算するショートカットなので、計算コストを抑えられます。
1-2. QSVM — カーネル計算を量子回路で行う
古典 SVM では RBF カーネルや多項式カーネルなどが使われますが、QSVM では 量子回路がカーネル関数の役割 を果たします。
量子回路の特徴は、指数的に大きな特徴空間(qubit 数が増えるほど爆発的に広がる空間)へデータを写せることです。古典コンピュータでは表現しきれない特徴空間でカーネルを計算できる可能性があります。
1-3. 類似度(フィデリティ)とは
QSVM のカーネルは「2つのデータを量子回路に通したときの量子状態の重なり具合」です。
データ A を回路に通す → 量子状態 A
データ B を回路に通す → 量子状態 B
重なり具合 = フィデリティ(0〜1)
1.0 → まったく同じ状態(= データが非常に似ている)
0.0 → まったく重ならない(= データが大きく異なる)
これを全訓練データのペアで計算して表にしたものが カーネル行列 です。
カーネル行列(80×80 の例)
データ1 データ2 データ3 ... データ80
データ1 [ 1.00 0.87 0.92 ... 0.12 ] ← 対角は必ず 1.0(自分自身)
データ2 [ 0.87 1.00 0.79 ... 0.08 ]
データ3 [ 0.92 0.79 1.00 ... 0.15 ]
: : : : :
データ80 [ 0.12 0.08 0.15 ... 1.00 ]
← setosa 同士は値が大きい → ← versicolor との間は値が小さい →
ヒートマップで見ると:
列・行インデックス(クラス順にソート済み)
┌──────────┬──────────┐
│ ████████ │ ░░░░░░░░ │ ← 左上: setosa 同士(高類似)
│ ████████ │ ░░░░░░░░ │
├──────────┼──────────┤
│ ░░░░░░░░ │ ████████ │ ← 右下: versicolor 同士(高類似)
│ ░░░░░░░░ │ ████████ │
└──────────┴──────────┘
████ = 濃い(類似度 高)
░░░░ = 薄い(類似度 低)
対角ブロックが濃く、非対角ブロックが薄いほど、2クラスが量子特徴空間でうまく分離できていることを示します。
1-4. QSVM 全体の流れ
Step 1: データ準備
iris の花びら・がく片の計測値 4次元
→ PCA で 2次元に圧縮(qubit 数を節約)
→ [-π, π] にスケーリング(量子回路の角度に合わせる)
Step 2: 量子カーネル行列の計算
訓練データ 80件 × 80件 = 6,400 ペアの類似度を計算
→ 80×80 のカーネル行列 K_train
Step 3: SVC で学習
K_train を scikit-learn の SVC に渡して境界を学習
→ SVC は「どのサポートベクターをどの重みで組み合わせるか」を最適化
Step 4: 予測
テストデータ 20件 × 訓練 80件 のカーネル行列を計算
→ 学習済み SVC で分類 → Accuracy 0.90
2. ZZFeatureMap — 量子特徴マップの正体
今回使用する ZZFeatureMap は、データの値を量子回路の「角度」として埋め込む回路です。
読み方のコツ
左から右へ時間が流れます。
H で重ね合わせを作り、
P でデータを角度として埋め込み、
CNOT + ZZ結合 で 2 qubit をもつれさせてデータ間の相関を表現します。最後の
M 測定して 0/1 に確定させます。
| パラメータ | 今回の値 | 意味 |
|---|---|---|
feature_dimension |
2 | 入力の次元数 = qubit 数(2特徴量 → 2 qubit) |
reps |
1 | 回路のくり返し数。大きいほど複雑になるが、ノイズも増える |
alpha |
1.0 | 位相回転の強さ。デフォルト(2.0)より小さくすることで精度改善 |
なぜ reps=1, alpha=1.0?
グリッドサーチの結果、このパラメータが最もテスト精度(0.90)が高い組み合わせでした。reps=2 や alpha=2.0 では量子カーネルが過剰に複雑になり、精度が下がりました。
以下のようにパラメータを変更しながら最適なパラメータを探しました。
3. 実装コードの解説
① データ前処理(data_prep.py)
量子回路の qubit 数はできるだけ少なくしたいので、データを 2次元に圧縮します。
# iris の setosa(0)と versicolor(1)だけ抽出
mask = iris.target < 2
X, y = iris.data[mask], iris.target[mask]
# PCA で 4次元 → 2次元に圧縮(qubit を節約)
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
# 量子回路に入れるため [-π, π] にスケーリング
scaler = MinMaxScaler(feature_range=(-np.pi, np.pi))
X_scaled = scaler.fit_transform(X_pca)
② シミュレーターで量子カーネルを計算(qsvm_simulator.py)
from qiskit.circuit.library import zz_feature_map
from qiskit.primitives import StatevectorSampler
from qiskit_machine_learning.kernels import FidelityQuantumKernel
from qiskit_machine_learning.state_fidelities import ComputeUncompute
from sklearn.svm import SVC
# 量子特徴マップを作成
feature_map = zz_feature_map(feature_dimension=2, reps=1, alpha=1.0)
# シミュレーターで量子カーネルを計算
sampler = StatevectorSampler() # シミュレーター
fidelity = ComputeUncompute(sampler=sampler) # 類似度の計算方法
qkernel = FidelityQuantumKernel(feature_map=feature_map, fidelity=fidelity)
# 訓練データ全ペアのカーネル行列を計算
K_train = qkernel.evaluate(X_train)
K_test = qkernel.evaluate(X_test, X_train)
# scikit-learn の SVC にカーネル行列を渡して学習
svc = SVC(kernel="precomputed", C=10.0)
svc.fit(K_train, y_train)
y_pred = svc.predict(K_test)
③ 実機で実行(qsvm_real_device.py)
シミュレーターとの違いは Sampler を実機用に差し替えるだけ です。
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
# 待ち行列が最小のバックエンドを自動選択
service = QiskitRuntimeService(channel="ibm_quantum", token=api_key)
backend = service.least_busy(simulator=False, operational=True, min_num_qubits=2)
print(f"使用バックエンド: {backend.name}")
# 実機向けに回路をコンパイル
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
# SamplerV2 = 実機用の量子回路実行エンジン
sampler = SamplerV2(mode=backend)
fidelity = ComputeUncompute(sampler=sampler, pass_manager=pm)
qkernel = FidelityQuantumKernel(feature_map=feature_map, fidelity=fidelity)
# あとはシミュレーターと同じ
K_train = qkernel.evaluate(X_train)
K_test = qkernel.evaluate(X_test, X_train)
4. 実行結果の見方
① シミュレーターの精度
| 指標 | 値 |
|---|---|
| シミュレーター Accuracy | 0.90(20件中 18件正解) |
| 最適パラメータ C | 10.0(5-fold CV で自動選択) |
| CV Accuracy | 0.925 |
Accuracy(正解率)0.90 は、20件のテストデータのうち 18件を正しく分類できたことを示しています。setosa と versicolor はかなり形状が異なる品種なので、量子カーネルでもきちんと分けられています。
② カーネル行列ヒートマップの見方
results/kernel_heatmap.png に保存されます。以下のポイントで読んでください。
- 対角方向(左上ブロック・右下ブロック)が濃い → 同じクラスのデータ同士が似ている = 分類しやすい
- 非対角ブロック(左下・右上)が薄い → 異なるクラスのデータが異なる量子状態に写っている
- 実機版ではノイズの影響でヒートマップが全体的にぼやけることがあります
③ 決定境界の見方
results/decision_boundary.png には PCA で圧縮した 2次元空間上の分類結果が描かれています。
- 青の背景 = setosa(クラス 0)と判定される領域
- オレンジの背景 = versicolor(クラス 1)と判定される領域
- 点線 = 決定境界(ここが分類の境目)
- 丸マーカー = 訓練データ、星マーカー = テストデータ
境界線が直線でないことに注目
量子カーネルを使うことで、直線では分けられないような複雑な境界を表現できます。
5. シミュレーター vs 実機 — 何が違う?
| シミュレーター | IBM Quantum 実機 | |
|---|---|---|
| ノイズ | なし(理想的) | あり(ゲートエラー・デコヒーレンス) |
| 精度 | 0.90(今回) | ノイズにより低下する場合あり |
| 速度 | 即時(ローカル) | 待ち行列あり(数分〜数十分) |
| 用途 | 開発・デバッグ・パラメータ探索 | 本番検証・ノイズ影響の研究 |
| コスト | 無料 | IBM Quantum 無料枠で利用可能 |
実機でのノイズについて
現在の量子コンピュータは NISQ(Noisy Intermediate-Scale Quantum)デバイスと呼ばれ、ゲート操作のたびに小さなエラーが蓄積します。回路が深い(ゲート数が多い)ほどノイズの影響が大きくなるため、reps=1のような浅い回路を使うことが実機での精度確保に重要です。
コンソール出力の読み方(実機実行時)
実際に実機の結果を乗せる予定でしたが、無料アカウントのため制限にかかってしまい、まだ実行できていません。制限が解除されてから実行する予定です。とほほ。。
※. 下記はサンプルです。
使用バックエンド: ibm_kyoto (qubits=127, 待ち行列=3) ← least_busy() で自動選択
トランスパイル後の深さ: 12 ← 小さいほどノイズが少ない
訓練カーネル行列を計算中(実機)...
テストカーネル行列を計算中(実機)...
=============================================
バックエンド : ibm_kyoto
[実機] Accuracy : 0.8000 (16/20)
[シミュレーター] : 0.9000
差分 : -0.1000 (ノイズによる劣化) ← 0.1〜0.2 程度は想定の範囲内
=============================================
6. まとめ
- Qiskit と IBM Quantum Platform を使い、50行程度のコードで QSVM を動かせた
- シミュレーターでの Accuracy は 0.90。iris の 2クラス分類としては十分な精度
-
least_busy()で実機バックエンドを自動選択できる - 実機ではノイズの影響があるが、
reps=1の浅い回路でその影響を抑えられた - 量子カーネルは「古典では難しい特徴空間への写像」が売りだが、現時点では古典 SVM と同等かそれ以下になることも多い。量子優位性の実証はこれからの研究課題
7. 最後に感想
さて、今回は量子機械学習モデルを作成してみました。IBM Bobの登場でやってみたかったことが実現できました。もちろん、勉強を続けて、自分で量子回路を作成できるようにならないといけませんが、遠く険しい道のりです。
ただ、夢の技術だと思っていた量子コンピュータを使った様々な取り組みに対するハードルはかなり下がり、色々な分野の研究や技術開発に活用することが当たり前になる時代がそこまでやってきたと感じます。
今回は以上になります。
参考
IBM Bob紹介ページ
IBM Quantum Platform
その他レコメンド
SPSS Modeler ノードリファレンス目次
SPSS Modeler 逆引きストリーム集
SPSS funさん記事集
IBM 斎藤さんの記事集
SPSS連載ブログバックナンバー
SPSSヒモトクブログなどは以下のTechXchangeのコミュニティに統合されました。
ご興味がある方は、ぜひiBM IDを登録して参加してみてください!!!お待ちしています。
IBM TechXchange Data Science Japan










