データエンコーディング
はじめに・表記法
量子アルゴリズムを使用するためには、古典データを何らかの方法で量子回路に取り込む必要があります。これは一般的にデータのエンコーディングと呼ばれますが、データのローディ ングと呼ばれることもあります。前のレッスンで学んだ特徴マッピング(feature mapping)の概念を思い出してください。特徴マッピングとは、データの特徴をある空間から別の空間へ写す写像です。古典データを量子コンピューターに転送すること自体もある種のマッピングであり、特徴マッピングと呼ぶことができます。実際には、Qiskitに組み込まれている特徴マッピング(z_Feature Map や ZZ Feature Map など)は通常、回転層とエンタングリング層を含み、状態をヒルベルト空間の多くの次元へ拡張します。このエンコーディングプロセスは量子機械学習アルゴリズムの重要な部分であり、その計算能力に直接影響します。
以下に紹介するエンコーディング手法の中には、古典的に効率よくシミュレートできるものもあります。これはとくに、積状態(つまり、量子ビットをエンタングルしない)を生成するエンコーディング手法で容易に確認できます。また、量子的な優位性は、データセットの量子的な複雑さとエンコーディング手法が適切に一致している場合に生まれる可能性が高いことを覚えておいてください。そのため、独自のエンコーディング回路を作成することになる可能性が非常に高いです。ここでは、様々なエンコーディング戦略を比較対照できるように、また何が可能かを示すために、幅広い手法を紹介します。エンコーディング手法の有用性については、いくつか非常に一般的な言明が可能です。たとえば、完全なエンタングリングスキームを持つ efficient_su2(以下参照)は、積状態を生成する手法(z_feature_map など)よりも、データの量子的特徴を捉 える可能性がはるかに高いです。しかしそれは、efficient_su2 があなたのデータセットに対して十分、あるいは十分に適合していて、量子スピードアップをもたらすということを意味するわけではありません。それは、モデル化または分類されるデータの構造を慎重に考慮する必要があります。また、回路の深さとのトレードオフもあります。回路内の量子ビットを完全にエンタングルする多くの特徴マップは非常に深い回路を生成し、現在の量子コンピューターで使用可能な結果を得るには深すぎる場合があります。
表記法
データセットは 個のデータベクトルの集合です:。各ベクトルは 次元、つまり です。これは複素数のデータ特徴にも拡張できます。このレッスンでは、全体の集合 やその特定の要素 などの表記を使用することがあります。しかし、ほとんどの場合、データセットから1度に1つのベクトルをロードすることを想定し、 個の特徴を持つ単一のベクトルを単に と表記することが多いです。
また、 という記号でデータベクトル の特徴マッピング を表すのが一般的です。特に量子コンピューティングでは、量子コンピューティングにおける写像を という表記で表すことが多く、これはこれらの操作のユニタリな性質を強調しています。どちらも特徴マッピングであるため、同じ記号を使うことも正確です。このコースでは次のように使い分けます:
- :機械学習における特徴マッピング全般を議論する際、
- :特徴マッピングの回路実装を議論する際。
正規化と情報損失
古典的機械学習では、訓練データの特徴を「正規化」またはスケール変換することが多く、これによりモデルの性能が向上することがよくあります。一般的な方法の一つは、最小-最大正規化(min-max normalization)または標準化(standardization)を使うことです。最小-最大正規化では、データ行列 の特徴列(たとえば特徴 )を次のように正規化します:
ここで min と max は、データセット 内の 個のデータベクトルにわたる特徴 の最小値と最大値を指します。すべての特徴値は単位区間内に収まります:(すべての 、 について)。
正規化は量子力学・量子コンピューティングにおいても基本的な概念ですが、最小-最大正規化とは少し異なります。量子力学における正規化では、状態ベクトル の長さ(量子コンピューティングの文脈では2-ノルム)が1に等しいことが要求されます:。これにより測定確率の和が1になります。状態は2-ノルムで割ることで正規化されます。すなわち、次のようにスケール変換します:
量子コンピューティングおよび量子力学では、これは人間がデータに課す正規化ではなく、量子状態の根本的な性質です。エンコ ーディング方式によっては、この制約がデータのスケール変換に影響する場合があります。たとえば、振幅エンコーディング(以下参照)では、量子力学の要請により となるようにデータベクトルが正規化され、これはエンコードされるデータのスケーリングに影響します。位相エンコーディングでは、量子ビットの位相角へのエンコーディングによる modulo- 効果による情報損失を防ぐために、特徴値を となるようにスケール変換することが推奨されています[1,2]。
エンコーディングの方法
次のいくつかのセクションでは、 個のデータベクトル(それぞれ 個の特徴を持つ)からなる小さな例の古典データセット を参照します:
上で導入した表記法を使うと、たとえば集合 の第4データベクトルの第1特徴は と表せます。
基底エンコーディング
基底エンコーディングは、古典的な ビット列を 量子ビット系の計算基底状態にエンコードします。たとえば を考えます。これは4ビット列 として表現でき、4量子ビット系では量子状態 として表されます。より一般的に、 ビット列: に対して、対応する 量子ビット状態は (、)です。これは単一の特徴に対するものであることに注意してください。
量子コンピューティングにおける基底エンコーディングは、各古典ビットを個別の量子ビットとして表現し、データの2進数表現を計算基底の量子状態に直接マッピングします。複数の特徴をエンコードする必要がある場合、各特徴はまず2進数形式に変換され、次に個別の量子ビットグループに割り当てられます(特徴ごとに1グループ)。各量子ビットはその特徴の2進数表現における1ビットを反映します。
例として、ベクトル (5, 7, 0) をエンコードしましょう。
すべての特徴が4ビットで格納されているとします(必要以上ですが、1桁の10進整数を任意に表現するには十分です):
5 → 2進数 0101
7 → 2進数 0111
0 → 2進数 0000
これらのビット列はそれぞれ4量子ビットの3つのグループに割り当てられるため、全体の12量子ビット基底状態は次のようになります:
ここで、最初の4量子ビットが第1特徴、次の4量子ビットが第2特徴、最後の4量子ビットが第3特徴を表しま す。以下のコードは、データベクトル (5,7,0) を量子状態に変換し、他の1桁の特徴にも汎用化されています。
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit
from qiskit import QuantumCircuit
# Data point to encode
x = 5 # binary: 0101
y = 7 # binary: 0111
z = 0 # binary: 0000
# Convert each to 4-bit binary list
x_bits = [int(b) for b in format(x, "04b")] # [0,1,0,1]
y_bits = [int(b) for b in format(y, "04b")] # [0,1,1,1]
z_bits = [int(b) for b in format(z, "04b")] # [0,0,0,0]
# Combine all bits
all_bits = x_bits + y_bits + z_bits # [0,1,0,1,0,1,1,1,0,0,0,0]
# Initialize a 12-qubit quantum circuit
qc = QuantumCircuit(12)
# Apply x-gates where the bit is 1
for idx, bit in enumerate(all_bits):
if bit == 1:
qc.x(idx)
qc.draw("mpl")

理解度チェック
以下の問いを読んで答えを考えてから、三角印をクリックして解答を確認してください。
例のデータセット の第1ベクトルをエンコードするコードを書いてください:
基底エンコーディングを使用して。
解答:
import math
from qiskit import QuantumCircuit
# Data point to encode
x = 4 # binary: 0100
y = 8 # binary: 1000
z = 5 # binary: 0101
# Convert each to 4-bit binary list
x_bits = [int(b) for b in format(x, '04b')] # [0,1,0,0]
y_bits = [int(b) for b in format(y, '04b')] # [1,0,0,0]
z_bits = [int(b) for b in format(z, '04b')] # [0,1,0,1]
# Combine all bits
all_bits = x_bits + y_bits + z_bits # [0,1,0,0,1,0,0,0,0,1,0,1]
# Initialize a 12-qubit quantum circuit
qc = QuantumCircuit(12)
# Apply x-gates where the bit is 1
for idx, bit in enumerate(all_bits):
if bit == 1:
qc.x(idx)
qc.draw('mpl')
振幅エンコーディング
振幅エンコーディングは、データを量子状態の振幅にエンコードします。正規化された古典的な 次元データベクトル を、 量子ビット量子状態 の振幅として表現します:
ここで は前と同じデータベクトルの次元数、 は の 番目の要素、 は 番目の計算基底状態です。 はエンコードするデータから決定される正規化定数です。これは量子力学が課す正規化条件です:
一般に、これは各特徴についてすべてのデータベクトルにわたって行う最小-最大正規化とは異なる条件です。これをどのように扱うかは問題によって異なりますが、上記の量子力学的な正規化条件は避けて通れません。
振幅エンコーディングでは、データベクトルの各特徴が異なる量子状態の振幅として格納されます。 量子ビット系は 個の振幅を提供するため、 個の特徴の振幅エンコーディングには 量子ビットが必要です。
例として、例のデータセット の第1ベクトル を振幅エンコーディングでエンコードしてみましょう。得られたベクトルを正規化すると:
となり、結果として得られる2量子ビット量子状態は:
上の例では、ベクトルの特徴数 は2の累乗ではありません。 が2の累乗でない場合は、 を満たす量子ビット数 を選び、振幅ベクトルを情報を持たない定数(ここではゼロ)で埋めます。
基底エンコーディングと同様に、データセットをエンコードする状態を計算したら、Qiskitの initialize 関数を使ってそれを準備することができます:
import math
desired_state = [
1 / math.sqrt(105) * 4,
1 / math.sqrt(105) * 8,
1 / math.sqrt(105) * 5,
1 / math.sqrt(105) * 0,
]
qc = QuantumCircuit(2)
qc.initialize(desired_state, [0, 1])
qc.decompose(reps=5).draw(output="mpl")
振幅エンコーディングの利点は、前述のとおりエンコードに必要な量子ビット数が 個だけで済むことです。しかし、後続のアルゴリズムは量子状態の振幅に対して演算する必要があり、量子状態の準備・測定の手法は一般に効率的ではない傾向があります。
理解度チェック
以下の問いを読んで答えを考えてから、三角印をクリッ クして解答を確認してください。
以下のベクトル(例のデータセットから2つのベクトルを組み合わせたもの)のエンコードに対して、正規化された状態を書き下してください:
振幅エンコーディングを使用して。
解答:
6つの数をエンコードするには、振幅をエンコードできる状態が少なくとも6つ必要です。これには3量子ビットが必要です。未知の正規化因子 を使って、次のように書けます:
なお、
したがって、
同じデータベクトル に対して、振幅エンコーディングを使ってこれらのデータ特徴をロードする回路を作成するコードを書いてください。
解答:
desired_state = [
9 / math.sqrt(270),
8 / math.sqrt(270),
6 / math.sqrt(270),
2 / math.sqrt(270),
9 / math.sqrt(270),
2 / math.sqrt(270),
0,
0,
]
print(desired_state)
qc = QuantumCircuit(3)
qc.initialize(desired_state, [0, 1, 2])
qc.decompose(reps=8).draw(output="mpl")
[0.5477225575051662, 0.48686449556014766, 0.36514837167011077, 0.12171612389003691, 0.5477225575051662, 0.12171612389003691, 0, 0]
非常に大きなデータベクトルを扱う必要があるかもしれません。次のベクトルを考えてください:
正規化を自動化し、振幅エンコーディングのための量子回路を生成するコードを書いてください。
解答:
多くの可能な解答があります。以下は途中のいくつかのステップを出力するコードです:
import numpy as np
from math import sqrt
init_list = [4, 8, 5, 9, 8, 6, 2, 9, 2, 5, 7, 0, 3, 7, 5]
qubits = round(np.log(len(init_list)) / np.log(2) + 0.4999999999)
need_length = 2**qubits
pad = need_length - len(init_list)
for i in range(0, pad):
init_list.append(0)
init_array = np.array(init_list) # Unnormalized data vector
length = sqrt(
sum(init_array[i] ** 2 for i in range(0, len(init_array)))
) # Vector length
norm_array = init_array / length # Normalized array
print("Normalized array:")
print(norm_array)
print()
qubit_numbers = []
for i in range(0, qubits):
qubit_numbers.append(i)
print(qubit_numbers)
qc = QuantumCircuit(qubits)
qc.initialize(norm_array, qubit_numbers)
qc.decompose(reps=7).draw(output="mpl")
Normalized array: [0.17342199 0.34684399 0.21677749 0.39019949 0.34684399 0.26013299 0.086711 0.39019949 0.086711 0.21677749 0.30348849 0. 0.1300665 0.30348849 0.21677749 0. ]
[0, 1, 2, 3]

振幅エンコーディングは基底エンコーディングに比べて優れている点がありますか?あれば説明してください。
解答:
いくつかの答えが考えられます。一つの答えは、基底状態の固定された順序があるため、この振幅エンコーディングはエンコードされた数値の順序を保持するということです。また、多くの場合、より密にエンコードされることになります。
振幅エンコーディングの利点は、 次元( 特徴)のデータベクトル のエンコードに 量子ビットしか必要としないことです。しかし、振幅エンコーディングは一般に非効率な手続きであり、任意の状態準備が必要で、CNOTゲートの数が指数関数的になります。言い換えると、状態準備の多項式実行時間複雑性は次元数に対して (ここで 、 は量子ビット数)です。振幅エンコーディングは「空間における指数的な節約を、時間における指数的な増大のコストで提供する」[3]ものです。ただし、特定のケースでは実行時間を に改善できる場合もあります[4]。エンドツーエンドの量子スピードアップのためには、データロードの実行時間複雑性を考慮する 必要があります。
角度エンコーディング
角度エンコーディングは、量子サポートベクターマシン(QSVM)や変分量子回路(VQC)など、Pauliフィーチャーマップを使用する多くのQMLモデルで注目されています。角度エンコーディングは、以下で紹介する位相エンコーディングや高密度角度エンコーディングと密接に関連しています。ここでは「角度エンコーディング」を、軸からの回転、すなわち例えばゲートやゲートによって実現されるにおける回転を指す用語として使います[1,3]。実際には、任意の回転またはその組み合わせでデータをエンコードすることができますが、が文献でよく使われるため、ここではそれを重点的に説明します。
単一の量子ビットに適用すると、角度エンコーディングはデータ値に比例したY軸回転を与えます。データセット内の番目のデータベクトルの単一の(番目の)特徴量 のエンコーディングについて考えてみましょう:
あるいは、ゲートを使って角度エンコーディングを行うこともできますが、エンコードされた状態はと比べて複素相対位相を持つことになります。
角度エンコーディングは、前述の2つの方法とはいくつかの点で異なります。角度エンコーディングでは:
- 各特徴量の値が対応する量子ビットにマッピングされ()、量子ビットは積状態のままです。
- データ点の特徴量全体ではなく、1つの数値が一度にエンコードされます。
- 個のデータ特徴量に対して個の量子ビットが必要です()。多くの場合、等号が成立します。がどのように可能かは、次のいくつかのセクションで見ていきます。
- 生成される回路は一定の深さを持ちます(トランスパイル前の深さは通常1です)。
一定の深さの量子回路は、現在の量子ハードウェアに特に適しています。を使ってデータをエンコードするもう1つの特徴(特にY軸角度エンコーディングを選択した場合)は、特定の用途に有用な実数値の量子状態を生成することです。Y軸回転の場合、実数値の角度によってY軸回転ゲートでデータがマッピングされます(Qiskit RYGate)。位相エンコーディング(後述)と同様に、情報損失やその他の望ましくない影響を防ぐため、となるようにデータをスケール変換することをお勧めします。
以下のQiskitコードは、単一の量子ビットを初期状態からデータ値をエンコードするように回転させます。
from qiskit.quantum_info import Statevector
from math import pi
qc = QuantumCircuit(1)
state1 = Statevector.from_instruction(qc)
qc.ry(pi / 2, 0) # Phase gate rotates by an angle pi/2
state2 = Statevector.from_instruction(qc)
states = state1, state2
状態ベクトルへの作用を可視化するための関数を定義します。関数定義の詳細は重要ではありませんが、状態ベクトルとその変化を可視化できることは重要です。
import numpy as np
from qiskit.visualization.bloch import Bloch
from qiskit.visualization.state_visualization import _bloch_multivector_data
def plot_Nstates(states, axis, plot_trace_points=True):
"""This function plots N states to 1 Bloch sphere"""
bloch_vecs = [_bloch_multivector_data(s)[0] for s in states]
if axis is None:
bloch_plot = Bloch()
else:
bloch_plot = Bloch(axes=axis)
bloch_plot.add_vectors(bloch_vecs)
if len(states) > 1:
def rgba_map(x, num):
g = (0.95 - 0.05) / (num - 1)
i = 0.95 - g * num
y = g * x + i
return (0.0, y, 0.0, 0.7)
num = len(states)
bloch_plot.vector_color = [rgba_map(x, num) for x in range(1, num + 1)]
bloch_plot.vector_width = 3
bloch_plot.vector_style = "simple"
if plot_trace_points:
def trace_points(bloch_vec1, bloch_vec2):
# bloch_vec = (x,y,z)
n_points = 15
thetas = np.arccos([bloch_vec1[2], bloch_vec2[2]])
phis = np.arctan2(
[bloch_vec1[1], bloch_vec2[1]], [bloch_vec1[0], bloch_vec2[0]]
)
if phis[1] < 0:
phis[1] = phis[1] + 2 * pi
angles0 = np.linspace(phis[0], phis[1], n_points)
angles1 = np.linspace(thetas[0], thetas[1], n_points)
xp = np.cos(angles0) * np.sin(angles1)
yp = np.sin(angles0) * np.sin(angles1)
zp = np.cos(angles1)
pnts = [xp, yp, zp]
bloch_plot.add_points(pnts)
bloch_plot.point_color = "k"
bloch_plot.point_size = [4] * len(bloch_plot.points)
bloch_plot.point_marker = ["o"]
for i in range(len(bloch_vecs) - 1):
trace_points(bloch_vecs[i], bloch_vecs[i + 1])
bloch_plot.sphere_alpha = 0.05
bloch_plot.frame_alpha = 0.15
bloch_plot.figsize = [4, 4]
bloch_plot.render()
plot_Nstates(states, axis=None, plot_trace_points=True)
これは単一のデータベクトルの1つの特徴量に過ぎませんでした。番目のデータベクトルに対して個の特徴量を個の量子ビットの回転角にエンコードする場合、エンコードされた積状態は次のようになります:
これは次の式と等価であることに注意してください:
理解度チェック
以下の問題を読み、答えを考えてから、三角形をクリックして解答を確認してください。
上記の方法に従い、角度エンコーディングを使ってデータベクトル をエンコードしてください。
解答:
qc = QuantumCircuit(3)
qc.ry(0, 0)
qc.ry(2 * math.pi / 4, 1)
qc.ry(2 * math.pi / 2, 2)
qc.draw(output="mpl")
上記の角度エンコーディングを使って5つの特徴量をエンコードするには、何個の量子ビットが必要ですか?
解答: 5
位相エンコーディング
位相エンコーディングは、上述の角度エンコーディングと非常に似ています。量子ビットの位相角は、+軸から軸回りの実数値の角度です。データは位相回転でマッピングされ、です(詳細はQiskit PhaseGateを参照)。情報損失やその他の望ましくない影響を防ぐため、となるようにデータをスケール変換することをお勧めします[1,2]。
量子ビットはよく状態に初期化されますが、これは位相回転演算子の固有状態であるため、位相エンコーディングを実装するためにはまず量子ビットの状態を回転させる必要があります。そのため、アダマールゲートで状態を初期化することが適切です:。単一量子ビットへの位相エンコーディングは、データ値に比例した相対位相を与えることを意味します:
位相エンコーディングの手順は、各特徴量の値を対応する量子ビットの位相にマッピングします()。全体として、位相エンコーディングのアダマール層を含む回路深さは2であり、効率的なエンコーディング方式となっています。位相エンコードされた多量子ビット状態(個の特徴量に対して個の量子ビット)は積状態です:
以下のQiskitコードは、まずアダマールゲートで単一量子ビットの初期状態を準備し、次に位相ゲートを使って再度回転させ、データ特徴量をエンコードします。
qc = QuantumCircuit(1)
qc.h(0) # Hadamard gate rotates state down to Bloch equator
state1 = Statevector.from_instruction(qc)
qc.p(pi / 2, 0) # Phase gate rotates by an angle pi/2
state2 = Statevector.from_instruction(qc)
states = state1, state2
qc.draw("mpl", scale=1)
先ほど定義したplot_Nstates関数を使って、における回転を可視化することができます。
plot_Nstates(states, axis=None, plot_trace_points=True)
ブロッホ球のプロットは、でのZ軸回転を示しています。薄緑色の矢印が最終状態を示しています。
位相エンコーディングは、特におよびフィーチャーマップや、一般的なPauliフィーチャーマップなど、多くの量子フィーチャーマップで使用されています。
理解度チェック
以下の問題を読み、答えを考えてから、三角形をクリックして解答を確認してください。
上記の位相エンコーディングを使って8つの特徴量を保存するには、何個の量子ビットが必要ですか?
解答: 8
位相エンコーディングを使っ てベクトル をエンコードするコードを書いてください。
解答:
答えは多数あるかもしれません。こちらは一例です:
phase_data = [4, 8, 5, 9, 8, 6, 2, 9, 2, 5, 7, 0]
qc = QuantumCircuit(len(phase_data))
for i in range(0, len(phase_data)):
qc.h(i)
qc.rz(phase_data[i] * 2 * math.pi / float(max(phase_data)), i)
qc.draw(output="mpl")
高密度角度エンコーディング
高密度角度エンコーディング(DAE)は、角度エンコーディングと位相エンコーディングを組み合わせたものです。DAEでは、1つの量子ビットに2つの特徴量の値をエンコードすることができます:1つをY軸回転角で、もう1つを軸回転角で: 。2つの特徴量を次のようにエンコードします:
2つのデータ特徴量を1つの量子ビットにエンコードすることで、エンコードに必要な量子ビット数が削減されます。これをより多くの特徴量に拡張すると、データベクトルは次のようにエンコードできます:
DAEは、ここで使われている正弦波関数の代わりに、2つの特徴量の任意の関数に一般化することができます。これは一般量子ビットエンコーディング[7]と呼ばれています。
DAEの例として、以下のコードは特徴量とのエンコーディングを行い、可視化します。
qc = QuantumCircuit(1)
state1 = Statevector.from_instruction(qc)
qc.ry(3 * pi / 8, 0)
state2 = Statevector.from_instruction(qc)
qc.rz(7 * pi / 4, 0)
state3 = Statevector.from_instruction(qc)
states = state1, state2, state3
plot_Nstates(states, axis=None, plot_trace_points=True)
理解度チェック
以下の問題を読み、答えを考えてから、三角形をクリックして解答を確認してください。
上記の説明に基づいて、高密度エンコーディングを使って6つの特徴量をエンコードするには何個の量子ビットが必要ですか?
解答: 3
高密度角度エンコーディングを使ってベクトル をロードするコードを書いてください。
解答:
エンコーディングスキームで未使用のパラメーターが1つ残る問題を避けるため、リストに「0」をパディングしていることに注意してください。
dense_data = [4, 8, 5, 9, 8, 6, 2, 9, 2, 5, 7, 0, 3, 7, 5, 0]
qc = QuantumCircuit(int(len(dense_data) / 2))
entry = 0
for i in range(0, int(len(dense_data) / 2)):
qc.ry(dense_data[entry] * 2 * math.pi / float(max(dense_data)), i)
entry = entry + 1
qc.rz(dense_data[entry] * 2 * math.pi / float(max(dense_data)), i)
entry = entry + 1
qc.draw(output="mpl")
組み込みフィーチャーマップによるエンコーディング
任意の点でのエンコーディング
角度エンコーディング、位相エンコーディング、高密度エンコーディングはいずれも、各量子ビットに特徴量をエンコードした積状態(または1量子ビットに2特徴量)を準備します。これは基底エンコーディングや振幅エンコーディングとは異なります。それらの方法はエンタングル状態を利用するため、データ特徴量と量子ビットの間に1対1の対応関係がありません。振幅エンコーディングでは、例えば、ある特徴量が状態の振幅として、別の特徴量がの振幅として格納されることがあります。一般的に、積状態でエンコードする方法は浅い回路になり、各量子ビットに1〜2個の特徴量を格納できます。エンタングルメントを利用して量子ビットではなく状態に特徴量を関連付ける方法は、より深い回路になりますが、平均的に1量子ビットあたりより多くの特徴量を格納できます。
しかし、エンコーディングは振幅エンコーディングのように完全に積状態である必要も、完全にエンタングル状態である必要もありません。実際、Qiskitに組み込まれている多くのエンコーディングスキームでは、最初だけでなく、エンタングル層の前後にもデータをエンコードすることができます。これは「データ再アップロード」として知られています。関連する研究については、参考文献[5]および[6]を参照してください。
このセクションでは、いくつかの組み込みエンコーディングスキームを使用して可視化します。このセクションのすべての方法は、個の量子ビット上の個のパラメーター化ゲートの回転として個の特徴量をエンコードします()。特定の量子ビット数に対してデータロードを最大化することが唯一の考慮事項ではないことに注意してください。多くの場合、回路の深さは量子ビット数よりもさらに重要な考慮事項となります。
Efficient SU2
エンタングルメントを用いたエンコードの一般的かつ有用な例として、Qiskit の efficient_su2 回路があります。この回路は、例えばわずか 2 量子ビットで 8 個の特徴量をエンコードできるという優れた特性を持っています。まずこれを確認し、どのようにして可能なのかを理解してみましょう。
from qiskit.circuit.library import efficient_su2
circuit = efficient_su2(num_qubits=2, reps=1, insert_barriers=True)
circuit.decompose().draw(output="mpl")
状態を記述する際、Qiskit の慣例に従い、最下位の量子ビットを または のように右端に配置します。このような状態はすぐに非常に複雑になるため、状態を陽に書き下すことはほとんど行われません。この稀な例がその理由を説明するのに役立つでしょう。
系は 状態から始まります。最初のバリア( と表記する地点)までの状態は次のようになります。
これはすでに見たデンスエンコードです。次に CNOT ゲートを経て、2 番目のバリア()での状態は次のようになります。
最後の 1 量子ビット回転を適用して同じ状態をまとめると、次の最終状態が得られます。