量子の重ね合わせを使って任意のデータを表現する AAE 〜実験編〜

$$
\def\bra#1{\mathinner{\left\langle{#1}\right|}}
\def\ket#1{\mathinner{\left|{#1}\right\rangle}}
\def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}
$$
本記事は [実装編](../items/68bd665701b1799ea3fd) の続編として、Approximate Amplitude Encoding (AAE) を使用して、数種類のデータを量子ビットで表現します。
AAE で表現できるデータと、実際に表現したいデータとの差を確認することで、AAE の性質について考えてみたいと思います。（以下、量子ビットで何らかのデータを表現することをエンコードと記述します。）

（注意）
本記事は「AAE を使ってみる」もので、AAE の手法としての優劣を評価するものではありません。記事内で表示している実験結果は一例であり、実装方法やパラメータ値等によっては異なる結果が得られる可能性があります。

## 実験データ一覧

実験でエンコードしようとするデータは以下の通りです。
これらのデータを使って、AAE でどのような精度でエンコードできるか、またパラメータの変更によって精度がどのように変わるかを見ていきます。

実験では指定がない限り、ガウシアンカーネルの $\sigma$ を 0.25、パラメータ付き量子回路(以下、PQC) 部分のレイヤー数を 8 にしています。

|番号|表現するデータ|量子ビット数|エンコードしたいデータ数などの詳細|
|:--:|----|:-----:|-----|
| 1 |正弦波 ($\sin \theta$) | 5 | $0 \le \theta \le 2\pi$ の区間で等間隔に16個の値をサンプリング |
| 2 | 正規分布 ($e^{-x^2 / 2} / \sqrt{2 \pi}$) | 5 | $-3 \le x \le 3$ の区間で等間隔に16個の値をサンプリング |
| 3 | ランダムな値 | 6 | 32個の正のランダム値をサンプリング（補助ビットありでエンコード） |
| 4 | ランダムな値 | 6 | 64個の正のランダム値をサンプリング（補助ビットなしでエンコード） |


### 1. 正弦波

- 実験結果

エンコードするデータ $a$ をサンプリングします。
``` python
x = np.linspace(0, np.pi*2, num=16)
a = np.sin(x)

a = a / np.sqrt(np.sum(a**2))
```

パラメータ学習における MMD 損失の推移はこのようになりました。0.01 を下回るくらいまで低下しています。
![sin-loss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/8b30de0e-66c1-bd4a-8f9f-6535f8c53b6b.png)

元のデータとエンコード結果を並べると次のようになりました。
橙色が元のデータで、青色がエンコードされたデータです。

![sin-result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/cddaacee-b34b-428d-7b49-41d27feffe75.png)

青線のように、すべて負の数としてエンコードされてしまいました。
前半分は符号が異なっていますが、絶対値だけを見ればそれなりに正しくエンコードできているように見えます。

- 考察

$a_j$ の値は
$$
a_j \ge 0 \quad (0 \le j \le 7)
$$
$$
a_j \lt 0 \quad (8 \le j \le 15)
$$

となっており、AAE の実装において最下位ビットを補助ビットとしたので、 $U(\theta)\ket{0}$ は次のようになっているはずです。

$$
U(\theta)\ket{0} = a_0\ket{0000}\ket{0} + a_1\ket{0001}\ket{0} + \cdots + a_7\ket{0111}\ket{0} + a_8\ket{1000}\ket{1} + a_9\ket{1001}\ket{1} + \cdots + a_{15}\ket{1111}\ket{1}
$$

これを見ると、最上位ビットと最下位ビットの値が等しくなっています。すなわち、最上位ビットと最下位ビットの間にエンタングルメントを生じさせる必要があります。しかし、AAE の実装では隣接する量子ビット間のみに CNOT ゲート演算を組み込んでいるため、最上位ビットと最下位ビットの間でうまくエンタングルメントができていないのではないかと推察されます。

また、MMD 損失におけるガウシアンカーネル
$$
\kappa (j, k) = \exp{\Bigl( \frac{-\|j - k\|^2}{2\sigma^2} \Bigr)}
$$
は、$|j - k| = 0$ の場合と $|j - k| = 1$ の場合の差が比較的小さいために、符号が異なった際に損失が大きくならないだろう、という点も関係しているのではないかと思われます。


- 実験その２

そこで、最上位ビットを補助ビットにするような実装に変更して正弦波をエンコードします。
MMD 損失とエンコード結果は以下のようになりました。

![sin-loss2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/30e24258-68c9-32aa-5fdf-e419f0c132f8.png)
![sin-result2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/60e788b0-1478-7cb6-1a8d-5860e5291b5f.png)

残念ながら今度は MMD 損失が 0.08〜0.09 近辺を上下しており、それ以上低下させられませんでした。
エンコード結果を図示したところ、元の正弦波とのズレが明らかに大きくなっています。符号についても改善されたとは言えない結果になっていますが、正負両方の値をとるようになりました。

- 実験その3

符号のエンコードがうまくいかなかったので、すべて正の数になるように値を補正して補助ビットなしでエンコードしてみます。

![sin-loss3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/b608e0a6-27dc-6251-4bfb-f93f845fd396.png)
![sin-result3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/9fc02f8e-89f1-b2fe-4976-db9df7da3228.png)

すべて正の値にして補助ビットを無くした方が正弦波らしいエンコード結果になりました。きれいな正弦波を描いていませんが、値の精度についてもそれほど悪くありません。

その他、ガウシアンカーネルのパラメータ $\sigma$ を 0.25 から 0.1 に変更することで、符号誤りによる損失を大きくしようとしましたが、結果はあまり変わりませんでした。（詳細は省略）


### 2. 正規分布

- 実験結果

エンコードするデータ $a$ を以下のようにサンプリングします。

```python
x = np.linspace(-3, 3, num=16)
a = np.exp(-x**2 / 2) / np.sqrt(2 * np.pi)

a = a / np.sqrt(np.sum(a**2))
```
結果は以下のようになりました。

![exp-loss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/61f1fea0-d091-612e-aabf-07215801ea5e.png)
![exp-result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/617e966e-08e9-be3e-c804-2b72946a0d1c.png)

MMD 損失は 0.08 程度で下げ止まってしまいました。その影響なのか、エンコード結果を比較したグラフについて、サンプリングした正規分布との差が大きくなっています。符号についてもグラフの両端で反転している箇所があります。

単純なデータなのでうまくエンコードできるかと期待していたのですが、結果はあまり良いとは言えないものでした。

### 3. ランダムな値

量子ビットを 1 個増やして 32 個のランダムな正の値をエンコードします。
最下位ビットを補助ビットにして、あえて正負両方に対応した方法でエンコードを行います。

![random-loss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/01c61862-1034-775f-42b9-a9e2417c577a.png)
![random-result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/a17577d1-9863-c61f-adf9-a4b5be033eb9.png)

パラメータ学習において、MMD 損失は 0.01 を下回る程度まで小さくなりました。
エンコード結果、$j \le 15$ では符号も値も精度よくエンコードできていますが、$j \gt 15$ では正弦波をエンコードしたときと同じように符号が反転する結果になりました。

絶対値としては比較的よくエンコードできており、量子ビットを 1 ビット増やす程度では問題ないと言えそうです。


### 4. ランダムな値（データ数を増やしてみる）

最後に 6 量子ビットで 64 個のランダムな正の値をエンコードします。先ほどと同じビット数ですが、補助ビットをなくしてエンコードするデータ数を増やします。

MMD 損失のグラフは省略しますが、0.007 〜 0.01 程度の値になり、そのときのエンコード結果は次のようになりました。尚、PQC のレイヤー数を 10 に増やす等、パラメータを変えて複数回試行しましたが、すべて同じような結果になりました。

グラフを見た目視評価では、値が一致している部分も見受けられますが、実際の値とエンコードした値のズレが大きくなっており、うまくエンコードできていないと思います。

- 考察

データ数が増えたことで $a_j$ の平均値が小さくなったため、うまくエンコードできてなくても MMD 損失の値が小さくなったのではないかと思われます。実験で使用した値を見ても $a_j$ の値は 0.2 以下になっており、小さな誤差でもグラフでは大きくズレているように見えます。
$a_j$ の値はデータ数が増えるにつれて小さくなっていくので、AAE によるエンコードはますます難しくなっていきます。

![mbit-result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603676/42591a1d-99e1-7eb4-4878-988273c419e6.png)

### まとめ

本記事の試行で分かった（といっても予想に過ぎない）ことは以下の通りです。
- うまくエンコードできるかどうか、データに依存する。どんなデータが良いのかは分からない。
- 符号の誤りが起こりやすい。
- MMD 損失が 0.01 より小さくなければならない。量子ビット数が増えれば、MMD 損失はさらに小さくならなければならない。


### 所感

AAE は $n$ 量子ビットで $2^n$ 個のデータを表現できる興味深い手法です。しかし、本記事で試したように MMD 損失が常に小さくなるようにパラメータを学習することは難しく、うまくエンコードできるデータは限定的です。

[実装編](../items/68bd665701b1799ea3fd) で紹介したように、AAE は量子機械学習の領域で多用される PQC を使用しています。PQC は短期的に量子コンピュータを活用できる可能性のある技術として注目されているものです。

ここで AAE は扱うデータ・問題が非常にシンプルなため、PQC を研究するための題材として有用ではないかと期待しています。例えば、効率的な PQC の設計手法や、パラメータ学習における勾配消失問題の理論的な分析に役立てられればと考えています。