LoginSignup
8
5

More than 3 years have passed since last update.

TensorFlow Quantumで量子回路学習をやる

Last updated at Posted at 2020-03-10

TensorFlowQuantumが公開されたので早速遊んでみた。
tutorialsにmnistの識別のサンプルコードがあったので(手書き数字の識別と言っていいのか?ってくらい元データをダウンスケールしているが、、、そのため別の題材で識別問題に挑戦中)、それを参考に、TensorFlowQuantumを使って回帰問題に取り組んでみた。コードはgithub.com/koke-saka/quantum-machine-learning

機械学習については素人のため、機械学習的に危ういところがあったら、優しく指摘してほしい。

QuantumCircuitLearning

量子回路の構造を制限することで勾配計算を可能にしたQuantumCircuitLearningの実装がQuantumNativeDojoにあり、それを参考に三角関数の学習をTensorFlowQuantumでやってみる。

学習データの準備

詳細はgithub.com/koke-saka/quantum-machine-learningへ。
とりあえず200個のサンプルを用意し、ランダムに150個を訓練セット、50個をテストセットに振り分けた。

入力状態の作成

mnistの学習ではスレッショルドをひいて画像を2値画像にしてそれをqubitの0,1に対応させていた。(正確には1の場合にXゲートをかましていた)
ここではQuantumNativeDojoにならい $\arcsin(x)$ と$\arccos(x^2)$をそれぞれRY、RXゲートの回転角に対応させて、入力状態のエンコードを行った。TensorFlowQuantumではどうやら予めその状態を準備しておくようだ。(Qulacsでは逐一回路を作り直していた気がする。)

def convert_to_circuit(x):
    """Encode truncated classical image into quantum datapoint."""
    y = np.arcsin(x)
    z = np.arccos(x**2)
    qubits = cirq.GridQubit.rect(5, 1)
    circuit = cirq.Circuit()
    for i in range(5):
        circuit.append(cirq.ry(y).on(qubits[i]))
        circuit.append(cirq.rz(z).on(qubits[i]))
    return circuit


x_train_circ = [convert_to_circuit(x) for x in x_train]
x_test_circ = [convert_to_circuit(x) for x in x_test]
x_train_tfcirc = tfq.convert_to_tensor(x_train_circ)
x_test_tfcirc = tfq.convert_to_tensor(x_test_circ)

convert_to_circuit()は自前で用意する必要がある。tutorial/mnistの該当部分を見ると理解が深まると思う。
convert_to_tensor()したやつを今後の学習で用いる。

パラメトリック量子回路(ニューラルネットワーク)の作成

未解決

readoutとdataqubitsは別々に用意する必要があるのか不明。
QuantumNativeDojoのように出力量子ビットにも入力をエンコードしたいのだが、今の所できないでいる。

とりあえずの実装

def create_quantum_model(c_depth=3):
    data_qubits = cirq.GridQubit.rect(5,1)
    readout = cirq.GridQubit(-1,-1)
    circuit = cirq.Circuit()


    builder = CircuitLayerBuilder(
        data_qubits = data_qubits,
        readout = readout
    )

    for i in range(c_depth):
        builder.add_entangler(circuit,5)
        builder.add_layer(circuit, gate = cirq.XX, prefix='xx'+str(i))
        builder.add_layer(circuit, gate = cirq.ZZ, prefix='zz'+str(i))
        builder.add_layer(circuit, gate = cirq.XX, prefix='xx1'+str(i))

    return circuit, cirq.Z(readout)

model_circuit, model_readout = create_quantum_model()

クラスCircuitLayerBuilderについてはgithubを参照。隣接する量子ビットにCZゲートをかますadd_entanglerを自前で用意。

こんな感じで量子回路ができる。
image.png

モデルの作成、学習

モデルを作成する準備が整った。モデルを作って学習させてみよう。
回帰問題のため、損失関数はmseにした。

model = tf.keras.Sequential([
    # The input is the data-circuit, encoded as a tf.string
    tf.keras.layers.Input(shape=(), dtype=tf.string),
    # The PQC layer returns the expected value of the readout gate, range [-1,1].
    tfq.layers.PQC(model_circuit, model_readout),
])

model.compile(
    loss=tf.keras.losses.mse,
    optimizer=tf.keras.optimizers.Adam(),
    metrics=['mae'])

qnn_history = model.fit(
      x_train_tfcirc, y_train,
      batch_size=25,
      epochs=EPOCHS,
      verbose=1,
      validation_data=(x_test_tfcirc,y_test)
)

テストセットと予測値の比較が下の図である。
image.png

なんとなく学習できているようだが、最大最小が小さく出ているのが気になる。readoutはパウリのZ行列の期待値なので1から-1の間を取りうるはずなのだが、、

終わりに

とりあえず、TensorFlowQuantumで遊ぶことはできた。不具合の原因は今後考えることにする。TensorFlowQuantum触ってみるかってなる人が増えればと嬉しい。

8
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5