20200316のTensorFlowに関する記事は2件です。

Win10にTensorflow2.1.0, CUDA10.1, cudnn7.6.5を入れる

本記事の内容

Windows10マシンにTensorflow2.1.0 + CUDA10.1 + cuDNN 7.6.5 をインストールする手順をまとめます。

以前のバージョンとの違い

  1. CUDAインストーラーがPATHを通してくれるようになった (環境変数を自分で変更しなくてよくなった)
  2. Visual Studio 2017の C++ compilerでは動かなくなった (VS2019再配布可能パッケージを入れればOK)
  3. CPU版tensorflowもC++ compiler必須になった (VS2019再配布可能パッケージを入れればOK)
  4. ロングネームを有効にしなきゃいけなくなった (必須かどうか未確認)

導入環境

CPU: Intel core-i9 9900K
GPU: RTX2080Ti
OS: Windows10 Pro

入れるもの

Visual Studio 2015~2019 VC++ 再配布可能パッケージ
tensorflow-gpu 2.1.0
CUDA 10.1
cuDNN 7.6.5 for CUDA10.1
Anaconda 2019.03 for Windows 64 bit

CUDA, cuDNN, tensorflowのバージョン選定

今回使うGPUはturingアーキテクチャのRTX2080TiですのでCUDAは10.0以降であれば使えます。
https://en.wikipedia.org/wiki/CUDA

pipでインストールできるtensorflow-gpuビルドは特定のバージョンのCUDA用にビルドされたものですので、例えばwindows用にビルドされたtensorflow-gpu 2.1.0はCUDA10.1でないとそのままでは動きません。自分でビルドすれば別バージョンのCUDAに対応できますが、結構ハードル高いので素直に対応するバージョンのものを入れた方が無難だと思います。tensorflow 2.1.0のリリースノートにCUDA10.1, cuDNN7.6でビルドしていると書かれていますので、今回はCUDA10.1とcuDNN 7.6.5 for CUDA10.1を使用しました。
https://github.com/tensorflow/tensorflow/releases

1. Visual Studio 2015~2019 再配布可能パッケージをインストールする

MicrosoftのサイトからVisual Studio 2015~2019 C++ compiler 再配布可能パッケージをダウンロードしてインストールします
https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads

2. CUDA, cuDNNをインストールする

NVIDIAの公式サイトからダウンロードしてインストールします。僕の環境だとWin10, x86_64になります。
https://developer.nvidia.com/cuda-downloads

インストールを実行します。グラフィックドライバーも一緒に入れてくれます。

以前はここでシステムの環境変数でPATHを通してましたが要らなくなったようです。
nvccコマンドを呼んでみます。

コマンドプロンプト
> nvcc -V

これでバージョン情報が表示されたら正常です。

3. cuDNNをインストールする

公式サイトからダウンロードします。
今回はcuDNN v7.6.5 for CUDA10.1のWindows10用のものを使用しました。
https://developer.nvidia.com/rdp/cudnn-download

ダウンロードしてきたzipファイル内のcudaフォルダ内にあるbin, include, extra を「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1」にコピーします。

これを

ここにコピーですね

4. Anacondaでpython環境をインストール

公式サイトからWindows用python3系64bit版インストーラーをダウンロードしてインストールします。
https://www.anaconda.com/distribution/

5. conda環境を作ってpackageをインストールする

Anaconda Promptを起動してconda環境をつくります。tensorflow2からpython3.7が使えるようになったので今回は3.7でやってみます。以下では「tf」という名前でpython 3.7のconda環境を作成しています。

Anaconda_prompt
(base) > conda create -n tf python=3.7

conda環境をつくったら有効にしてtensorflow-gpuをインストールします。他のpackageをインストールした後にtensorflow-gpuをインストールするとtensorflow-gpuのimportに失敗するようになる事があるので最初にインストールして動作を確認するのがオススメです。

Anaconda_prompt
(base) > conda activate tf
(tf) > pip install tensorflow-gpu==2.1.0
(tf) > python
>>> import tensorflow as tf
>>> tf.config.list_physical_devices('GPU')
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

上記でimportが失敗する場合、C++コンパイラが入ってないかもしれません。
また、tf.config.list_physical_devices('GPU')で空のリスト[]が返ってきた場合、GPUが認識されていません。

6. 機械学習系パッケージをインストールする

Anaconda_prompt
(tf) $ pip install optuna tensorflow-addons numpy pandas xlrd openpyxl sklearn scipy catboost xgboost lightgbm matplotlib seaborn boruta pydot3 graphviz ipywidgets jupyter tqdm pyarrow psutil
Anaconda_prompt
(tf) $ pip install pillow opencv-python

えんじょい

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TensorFlow Quantumで量子畳み込みニューラルネットワーク(Quantum Convolutional Neural Network)の例題を見てみる。

はじめに

Googleの提供するTensorFlow QuantumでQCNNの例題がありました。古典のNNを量子で実装ということで例題なので深く考えずにやってみましょう。

参考

Quantum Convolutional Neural Network
https://www.tensorflow.org/quantum/tutorials/qcnn

ライセンスなどは全て準じます。早速やってみます。

ipython入れました。

githubはこちら
https://github.com/minatoyuichiro/tensorflowquantum_hello/blob/master/qcnn.ipynb

google colabはこちら。
https://colab.research.google.com/github/minatoyuichiro/tensorflowquantum_hello/blob/master/qcnn.ipynb

まずはGoogle colabを使っている人はTensorFlowのバージョンを合わせます。

try:
    %tensorflow_version 2.x
except Exception:
    pass
TensorFlow 2.x selected.

次にライブラリを読み込みます

!pip install -q tensorflow-quantum

そして、次にお決まりのツールの読み込みです。一式入れましょう。

import tensorflow as tf
import tensorflow_quantum as tfq

import cirq
import sympy
import numpy as np

# visualization tools
%matplotlib inline
import matplotlib.pyplot as plt
from cirq.contrib.svg import SVGCircuit

QCNNを構築

ここで、TensorFlow Quantum(TFQ)はtf.keras.Layerを継承するtfq.layers.AddCircuitレイヤーを提供していて、回路をprependもしくはappendできます。

qcnn_1.png
引用:https://www.tensorflow.org/quantum/tutorials/qcnn

実際使うと、

qubit = cirq.GridQubit(0, 0)

# いくつか回路を定義する
circuit1 = cirq.Circuit(cirq.X(qubit))
circuit2 = cirq.Circuit(cirq.H(qubit))

# テンソルオブジェクトに変換します
input_circuit_tensor = tfq.convert_to_tensor([circuit1, circuit2])

# appendしたい量子回路を作ります。
y_circuit = cirq.Circuit(cirq.Y(qubit))

# インスタンスにします
y_appender = tfq.layers.AddCircuit()

# 事前に準備したテンソルオブジェクトにappendします
output_circuit_tensor = y_appender(input_circuit_tensor, append=y_circuit)

全体的にTensorFlow Quantumでは、量子回路をテンソル化して操作します。

append前の回路は、

print(tfq.from_tensor(input_circuit_tensor))
[cirq.Circuit([
    cirq.Moment(operations=[
        cirq.X.on(cirq.GridQubit(0, 0)),
    ]),
])
 cirq.Circuit([
    cirq.Moment(operations=[
        cirq.H.on(cirq.GridQubit(0, 0)),
    ]),
])]

append後の回路は、

print(tfq.from_tensor(output_circuit_tensor))
[cirq.Circuit([
    cirq.Moment(operations=[
        cirq.X.on(cirq.GridQubit(0, 0)),
    ]),
    cirq.Moment(operations=[
        cirq.Y.on(cirq.GridQubit(0, 0)),
    ]),
])
 cirq.Circuit([
    cirq.Moment(operations=[
        cirq.H.on(cirq.GridQubit(0, 0)),
    ]),
    cirq.Moment(operations=[
        cirq.Y.on(cirq.GridQubit(0, 0)),
    ]),
])]

続いて例題

クラスター状態を準備し、「励起」されているかどうかを検出するために量子分類器をトレーニングします。クラスタ状態は非常にもつれていますが、古典的なコンピュータにとって必ずしも難しいわけではありません。論文で使用されているデータセットよりも単純なデータセットで分類タスクでは、MERAに似た深いQCNNアーキテクチャを実装します。

2.png

引用:https://www.tensorflow.org/quantum/tutorials/qcnn

「励起」クラスター状態は、その量子ビットのいずれかにcirq.Rxゲートが適用されたクラスター状態として定義されます。 QconvとQPoolについては、このチュートリアルの後半で説明します。

qcnn_3.png

構造はシンプルで、初期のクラスター状態を作ります。量子畳み込みと量子プーリングを通じて計算を行い、測定値の期待値を求め、その期待値の損失関数と教師データからパラメータを導入した量子回路を学習させます。

1.モデルへの入力は回路テンソルです。空の回路か、励起を示す特定のキュービットのXゲートのいずれかです。
2.モデルの残りの量子コンポーネントは、tfq.layers.AddCircuitレイヤーで構築されます。
3.推論には、tfq.layers.PQCレイヤーが使用されます。これは⟨Z^⟩を読み取り、それを励起状態の場合は1のラベルと比較し、非励起状態の場合は-1と比較します。

方針としては過去に見てきた例題と似ているのでそちらを採用しています。

データ

モデルを構築する前に、データを生成できます。この場合、クラスター状態への励起になります(元の論文では、より複雑なデータセットを使用していますが、ここでは簡単な例題を使います。)。励起はcirq.Rxゲートで表されます。十分に大きい回転は励起と見なされ、1とラベル付けされ、十分に大きくない回転は-1とラベル付けされ、励起ではないと見なされます。

def generate_data(qubits):
    """Generate training and testing data."""
    n_rounds = 20  # Produces n_rounds * n_qubits datapoints.
    excitations = []
    labels = []
    for n in range(n_rounds):
        for bit in qubits:
            rng = np.random.uniform(-np.pi, np.pi)
            excitations.append(cirq.Circuit(cirq.Rx(rng)(bit)))
            labels.append(1 if (-np.pi / 2) <= rng <= (np.pi / 2) else -1)

    split_ind = int(len(excitations) * 0.7)
    train_excitations = excitations[:split_ind]
    test_excitations = excitations[split_ind:]

    train_labels = labels[:split_ind]
    test_labels = labels[split_ind:]

    return tfq.convert_to_tensor(train_excitations), np.array(train_labels), \
        tfq.convert_to_tensor(test_excitations), np.array(test_labels)

通常の機械学習と同様に、モデルのベンチマークに使用するトレーニングおよびテストセットを作成することがわかります。以下を使用して、いくつかのデータポイントをすばやく確認できます。

sample_points, sample_labels, _, __ = generate_data(cirq.GridQubit.rect(1, 4))
print('Input:', tfq.from_tensor(sample_points)[0], 'Output:', sample_labels[0])
print('Input:', tfq.from_tensor(sample_points)[1], 'Output:', sample_labels[1])
Input: (0, 0): ───Rx(-0.969π)─── Output: -1
Input: (0, 1): ───Rx(-0.97π)─── Output: -1
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:9: DeprecationWarning: Rx was used but is deprecated.
It will be removed in cirq v0.8.0.
Use cirq.rx, instead.

  if __name__ == '__main__':

レイヤーの定義

次に、TensorFlowで上の図に示すレイヤーを定義します。

クラスターの状態

最初のステップは、Googleが提供する量子回路プログラミング用フレームワークであるCirqを使用してクラスター状態を定義することです。これはモデルの静的な部分なので、tfq.layers.AddCircuit機能を使用して埋め込みます。

def cluster_state_circuit(bits):
    """Return a cluster state on the qubits in `bits`."""
    circuit = cirq.Circuit()
    circuit.append(cirq.H.on_each(bits))
    for this_bit, next_bit in zip(bits, bits[1:] + [bits[0]]):
        circuit.append(cirq.CZ(this_bit, next_bit))
    return circuit
SVGCircuit(cluster_state_circuit(cirq.GridQubit.rect(1, 4)))

スクリーンショット 2020-03-16 12.00.58.png

QCNNレイヤー

参考における論文をを使用して、モデルを構成するレイヤーを定義します。

def one_qubit_unitary(bit, symbols):
    """Make a Cirq circuit enacting a rotation of the bloch sphere about the X,
    Y and Z axis, that depends on the values in `symbols`.
    """
    return cirq.Circuit(
        cirq.X(bit)**symbols[0],
        cirq.Y(bit)**symbols[1],
        cirq.Z(bit)**symbols[2])


def two_qubit_unitary(bits, symbols):
    """Make a Cirq circuit that creates an arbitrary two qubit unitary."""
    circuit = cirq.Circuit()
    circuit += one_qubit_unitary(bits[0], symbols[0:3])
    circuit += one_qubit_unitary(bits[1], symbols[3:6])
    circuit += [cirq.ZZ(*bits)**symbols[7]]
    circuit += [cirq.YY(*bits)**symbols[8]]
    circuit += [cirq.XX(*bits)**symbols[9]]
    circuit += one_qubit_unitary(bits[0], symbols[9:12])
    circuit += one_qubit_unitary(bits[1], symbols[12:])
    return circuit


def two_qubit_pool(source_qubit, sink_qubit, symbols):
    """Make a Cirq circuit to do a parameterized 'pooling' operation, which
    attempts to reduce entanglement down from two qubits to just one."""
    pool_circuit = cirq.Circuit()
    sink_basis_selector = one_qubit_unitary(sink_qubit, symbols[0:3])
    source_basis_selector = one_qubit_unitary(source_qubit, symbols[3:6])
    pool_circuit.append(sink_basis_selector)
    pool_circuit.append(source_basis_selector)
    pool_circuit.append(cirq.CNOT(control=source_qubit, target=sink_qubit))
    pool_circuit.append(sink_basis_selector**-1)
    return pool_circuit

まずはお決まりの1量子ビットの状態準備回路を見ます

SVGCircuit(one_qubit_unitary(cirq.GridQubit(0, 0), sympy.symbols('x0:3')))

スクリーンショット 2020-03-16 12.01.44.png

次に2量子ビットの任意量子状態を作る回路もチェックします。

SVGCircuit(two_qubit_unitary(cirq.GridQubit.rect(1, 2), sympy.symbols('x0:15')))

スクリーンショット 2020-03-16 12.02.21.png

SVGCircuit(two_qubit_pool(*cirq.GridQubit.rect(1, 2), sympy.symbols('x0:6')))

上記は面白くて、2量子ビットのもつれ回路を1量子ビットの量子状態へと落としこむプーリングです。

スクリーンショット 2020-03-19 16.51.57.png

量子畳み込み層

上記を使って、1次元の量子畳み込み回路を配置します。

def quantum_conv_circuit(bits, symbols):
    """Quantum Convolution Layer following the above diagram.
    Return a Cirq circuit with the cascade of `two_qubit_unitary` applied
    to all pairs of qubits in `bits` as in the diagram above.
    """
    circuit = cirq.Circuit()
    for first, second in zip(bits[0::2], bits[1::2]):
        circuit += two_qubit_unitary([first, second], symbols)
    for first, second in zip(bits[1::2], bits[2::2] + [bits[0]]):
        circuit += two_qubit_unitary([first, second], symbols)
    return circuit

チェックすると、、、

SVGCircuit(
    quantum_conv_circuit(cirq.GridQubit.rect(1, 8), sympy.symbols('x0:15')))

スクリーンショット 2020-03-16 12.03.49.png
(部分的に割愛)

量子プーリング層

量子プール層は、上記で定義した2量子ビットプールを使用して、N量子ビットからN/2量子ビットにプールします。

def quantum_pool_circuit(source_bits, sink_bits, symbols):
    """A layer that specifies a quantum pooling operation.
    A Quantum pool tries to learn to pool the relevant information from two
    qubits onto 1.
    """
    circuit = cirq.Circuit()
    for source, sink in zip(source_bits, sink_bits):
        circuit += two_qubit_pool(source, sink, symbols)
    return circuit

確認

test_bits = cirq.GridQubit.rect(1, 8)

SVGCircuit(
    quantum_pool_circuit(test_bits[:4], test_bits[4:], sympy.symbols('x0:6')))

スクリーンショット 2020-03-16 12.05.01.png

(部分的に割愛)

8量子ビットからスタートして、最終的に1量子ビットをZ基底で期待値を計算する回路を構築します。

def create_model_circuit(qubits):
    """Create sequence of alternating convolution and pooling operators 
    which gradually shrink over time."""
    model_circuit = cirq.Circuit()
    symbols = sympy.symbols('qconv0:63')
    # Cirq uses sympy.Symbols to map learnable variables. TensorFlow Quantum
    # scans incoming circuits and replaces these with TensorFlow variables.
    model_circuit += quantum_conv_circuit(qubits, symbols[0:15])
    model_circuit += quantum_pool_circuit(qubits[:4], qubits[4:],
                                          symbols[15:21])
    model_circuit += quantum_conv_circuit(qubits[4:], symbols[21:36])
    model_circuit += quantum_pool_circuit(qubits[4:6], qubits[6:],
                                          symbols[36:42])
    model_circuit += quantum_conv_circuit(qubits[6:], symbols[42:57])
    model_circuit += quantum_pool_circuit([qubits[6]], [qubits[7]],
                                          symbols[57:63])
    return model_circuit


# Create our qubits and readout operators in Cirq.
cluster_state_bits = cirq.GridQubit.rect(1, 8)
readout_operators = cirq.Z(cluster_state_bits[-1])

# Build a sequential model enacting the logic in 1.3 of this notebook.
# Here you are making the static cluster state prep as a part of the AddCircuit and the
# "quantum datapoints" are coming in the form of excitation
excitation_input = tf.keras.Input(shape=(), dtype=tf.dtypes.string)
cluster_state = tfq.layers.AddCircuit()(
    excitation_input, prepend=cluster_state_circuit(cluster_state_bits))

quantum_model = tfq.layers.PQC(create_model_circuit(cluster_state_bits),
                               readout_operators)(cluster_state)

qcnn_model = tf.keras.Model(inputs=[excitation_input], outputs=[quantum_model])

# Show the keras plot of the model
tf.keras.utils.plot_model(qcnn_model,
                          show_shapes=True,
                          show_layer_names=False,
                          dpi=70)

ダウンロード.png

モデルのトレーニング

モデルをバッチでトレーニングします。

# Generate some training data.
train_excitations, train_labels, test_excitations, test_labels = generate_data(
    cluster_state_bits)


# Custom accuracy metric.
@tf.function
def custom_accuracy(y_true, y_pred):
    y_true = tf.squeeze(y_true)
    y_pred = tf.map_fn(lambda x: 1.0 if x >= 0 else -1.0, y_pred)
    return tf.keras.backend.mean(tf.keras.backend.equal(y_true, y_pred))


qcnn_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.02),
                   loss=tf.losses.mse,
                   metrics=[custom_accuracy])

history = qcnn_model.fit(x=train_excitations,
                         y=train_labels,
                         batch_size=16,
                         epochs=25,
                         verbose=1,
                         validation_data=(test_excitations, test_labels))
 if __name__ == '__main__':
Train on 112 samples, validate on 48 samples
Epoch 1/25
112/112 [==============================] - 14s 125ms/sample - loss: 0.8766 - custom_accuracy: 0.7411 - val_loss: 0.8094 - val_custom_accuracy: 0.7917
Epoch 2/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.7996 - custom_accuracy: 0.7054 - val_loss: 0.7990 - val_custom_accuracy: 0.7917
Epoch 3/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.7797 - custom_accuracy: 0.7679 - val_loss: 0.7630 - val_custom_accuracy: 0.8750
Epoch 4/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.7362 - custom_accuracy: 0.8214 - val_loss: 0.7261 - val_custom_accuracy: 0.8125
Epoch 5/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.7074 - custom_accuracy: 0.8304 - val_loss: 0.7191 - val_custom_accuracy: 0.8125
Epoch 6/25
112/112 [==============================] - 12s 108ms/sample - loss: 0.6907 - custom_accuracy: 0.8571 - val_loss: 0.7137 - val_custom_accuracy: 0.8333
Epoch 7/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.6703 - custom_accuracy: 0.8750 - val_loss: 0.6875 - val_custom_accuracy: 0.8958
Epoch 8/25
112/112 [==============================] - 12s 108ms/sample - loss: 0.6318 - custom_accuracy: 0.8750 - val_loss: 0.6069 - val_custom_accuracy: 0.8750
Epoch 9/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.5373 - custom_accuracy: 0.8929 - val_loss: 0.5046 - val_custom_accuracy: 0.9167
Epoch 10/25
112/112 [==============================] - 12s 108ms/sample - loss: 0.4933 - custom_accuracy: 0.9643 - val_loss: 0.4708 - val_custom_accuracy: 0.9375
Epoch 11/25
112/112 [==============================] - 12s 108ms/sample - loss: 0.4444 - custom_accuracy: 0.9643 - val_loss: 0.4499 - val_custom_accuracy: 0.9375
Epoch 12/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4354 - custom_accuracy: 0.9732 - val_loss: 0.4470 - val_custom_accuracy: 0.9375
Epoch 13/25
112/112 [==============================] - 12s 108ms/sample - loss: 0.4236 - custom_accuracy: 0.9643 - val_loss: 0.4421 - val_custom_accuracy: 0.9167
Epoch 14/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4127 - custom_accuracy: 0.9643 - val_loss: 0.4240 - val_custom_accuracy: 0.9167
Epoch 15/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4081 - custom_accuracy: 0.9732 - val_loss: 0.4237 - val_custom_accuracy: 0.9375
Epoch 16/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4124 - custom_accuracy: 0.9732 - val_loss: 0.4237 - val_custom_accuracy: 0.9375
Epoch 17/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4078 - custom_accuracy: 0.9821 - val_loss: 0.4273 - val_custom_accuracy: 0.9583
Epoch 18/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4114 - custom_accuracy: 0.9821 - val_loss: 0.4312 - val_custom_accuracy: 0.9167
Epoch 19/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4150 - custom_accuracy: 0.9821 - val_loss: 0.4270 - val_custom_accuracy: 0.9792
Epoch 20/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4115 - custom_accuracy: 0.9821 - val_loss: 0.4302 - val_custom_accuracy: 0.9167
Epoch 21/25
112/112 [==============================] - 12s 108ms/sample - loss: 0.4114 - custom_accuracy: 0.9732 - val_loss: 0.4287 - val_custom_accuracy: 0.9375
Epoch 22/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4214 - custom_accuracy: 0.9821 - val_loss: 0.4309 - val_custom_accuracy: 0.9583
Epoch 23/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4031 - custom_accuracy: 0.9821 - val_loss: 0.4195 - val_custom_accuracy: 0.9167
Epoch 24/25
112/112 [==============================] - 12s 107ms/sample - loss: 0.4081 - custom_accuracy: 0.9821 - val_loss: 0.4235 - val_custom_accuracy: 0.9167
Epoch 25/25
112/112 [==============================] - 12s 106ms/sample - loss: 0.4118 - custom_accuracy: 0.9732 - val_loss: 0.4245 - val_custom_accuracy: 0.9375
plt.plot(history.history['loss'][1:], label='Training')
plt.plot(history.history['val_loss'][1:], label='Validation')
plt.title('Training a Quantum CNN to Detect Excited Cluster States')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

ダウンロード (1).png

いい感じです

単一量子フィルターでの量子古典ハイブリッド

続いて、量子フィルターを1回噛ませた後に全ての量子ビットを測定して、古典NNにかけるやつをやってみます。

qcnn_5.png

モデルはシンプル、

# 1-local operators to read out
readouts = [cirq.Z(bit) for bit in cluster_state_bits[4:]]


def multi_readout_model_circuit(qubits):
    """Make a model circuit with less quantum pool and conv operations."""
    model_circuit = cirq.Circuit()
    symbols = sympy.symbols('qconv0:21')
    model_circuit += quantum_conv_circuit(qubits, symbols[0:15])
    model_circuit += quantum_pool_circuit(qubits[:4], qubits[4:],
                                          symbols[15:21])
    return model_circuit


# Build a model enacting the logic in 2.1 of this notebook.
excitation_input_dual = tf.keras.Input(shape=(), dtype=tf.dtypes.string)

cluster_state_dual = tfq.layers.AddCircuit()(
    excitation_input_dual, prepend=cluster_state_circuit(cluster_state_bits))

quantum_model_dual = tfq.layers.PQC(
    multi_readout_model_circuit(cluster_state_bits),
    readouts)(cluster_state_dual)

d1_dual = tf.keras.layers.Dense(8)(quantum_model_dual)

d2_dual = tf.keras.layers.Dense(1)(d1_dual)

hybrid_model = tf.keras.Model(inputs=[excitation_input_dual], outputs=[d2_dual])

# Display the model architecture
tf.keras.utils.plot_model(hybrid_model,
                          show_shapes=True,
                          show_layer_names=False,
                          dpi=70)

ダウンロード (2).png

トレーニングします。

hybrid_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.02),
                     loss=tf.losses.mse,
                     metrics=[custom_accuracy])

hybrid_history = hybrid_model.fit(x=train_excitations,
                                  y=train_labels,
                                  batch_size=16,
                                  epochs=25,
                                  verbose=1,
                                  validation_data=(test_excitations,
                                                   test_labels))
Train on 112 samples, validate on 48 samples
Epoch 1/25
112/112 [==============================] - 4s 34ms/sample - loss: 1.0191 - custom_accuracy: 0.4554 - val_loss: 0.9589 - val_custom_accuracy: 0.5208
Epoch 2/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.9005 - custom_accuracy: 0.5536 - val_loss: 0.7559 - val_custom_accuracy: 0.7917
Epoch 3/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.6214 - custom_accuracy: 0.8393 - val_loss: 0.5050 - val_custom_accuracy: 0.8750
Epoch 4/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.3698 - custom_accuracy: 0.9464 - val_loss: 0.2517 - val_custom_accuracy: 0.9375
Epoch 5/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.2177 - custom_accuracy: 0.9643 - val_loss: 0.2159 - val_custom_accuracy: 1.0000
Epoch 6/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.2071 - custom_accuracy: 0.9643 - val_loss: 0.1775 - val_custom_accuracy: 0.9792
Epoch 7/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.2302 - custom_accuracy: 0.9375 - val_loss: 0.2072 - val_custom_accuracy: 1.0000
Epoch 8/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1793 - custom_accuracy: 0.9643 - val_loss: 0.2014 - val_custom_accuracy: 0.9583
Epoch 9/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1916 - custom_accuracy: 0.9554 - val_loss: 0.2167 - val_custom_accuracy: 0.9583
Epoch 10/25
112/112 [==============================] - 3s 27ms/sample - loss: 0.1956 - custom_accuracy: 0.9554 - val_loss: 0.2083 - val_custom_accuracy: 1.0000
Epoch 11/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1877 - custom_accuracy: 0.9732 - val_loss: 0.1755 - val_custom_accuracy: 0.9792
Epoch 12/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1870 - custom_accuracy: 0.9821 - val_loss: 0.1894 - val_custom_accuracy: 0.9583
Epoch 13/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1752 - custom_accuracy: 0.9911 - val_loss: 0.1833 - val_custom_accuracy: 0.9583
Epoch 14/25
112/112 [==============================] - 3s 27ms/sample - loss: 0.1776 - custom_accuracy: 0.9732 - val_loss: 0.1891 - val_custom_accuracy: 1.0000
Epoch 15/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1749 - custom_accuracy: 0.9911 - val_loss: 0.1904 - val_custom_accuracy: 0.9375
Epoch 16/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1835 - custom_accuracy: 0.9643 - val_loss: 0.1922 - val_custom_accuracy: 0.9583
Epoch 17/25
112/112 [==============================] - 3s 27ms/sample - loss: 0.1925 - custom_accuracy: 0.9821 - val_loss: 0.1868 - val_custom_accuracy: 1.0000
Epoch 18/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1836 - custom_accuracy: 0.9821 - val_loss: 0.1944 - val_custom_accuracy: 0.9583
Epoch 19/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1712 - custom_accuracy: 0.9821 - val_loss: 0.1811 - val_custom_accuracy: 0.9792
Epoch 20/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1874 - custom_accuracy: 0.9821 - val_loss: 0.1945 - val_custom_accuracy: 0.9167
Epoch 21/25
112/112 [==============================] - 3s 27ms/sample - loss: 0.2068 - custom_accuracy: 0.9554 - val_loss: 0.1742 - val_custom_accuracy: 0.9792
Epoch 22/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1918 - custom_accuracy: 0.9732 - val_loss: 0.2596 - val_custom_accuracy: 0.9583
Epoch 23/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.2036 - custom_accuracy: 0.9554 - val_loss: 0.2397 - val_custom_accuracy: 0.9583
Epoch 24/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1898 - custom_accuracy: 0.9821 - val_loss: 0.1818 - val_custom_accuracy: 0.9792
Epoch 25/25
112/112 [==============================] - 3s 26ms/sample - loss: 0.1843 - custom_accuracy: 0.9643 - val_loss: 0.1831 - val_custom_accuracy: 0.9375

結果表示

plt.plot(history.history['val_custom_accuracy'], label='QCNN')
plt.plot(hybrid_history.history['val_custom_accuracy'], label='Hybrid CNN')
plt.title('Quantum vs Hybrid CNN performance')
plt.xlabel('Epochs')
plt.legend()
plt.ylabel('Validation Accuracy')
plt.show()

ダウンロード (3).png

結果として、古典NNを噛ませることにより、ハイブリッドモデルは通常、純粋な量子バージョンよりも速く収束します。

複数の量子フィルターを使用したハイブリッド畳み込み

次に、複数の量子畳み込みと古典的なニューラルネットワークを使用してそれらを結合するアーキテクチャを試してみます。

qcnn_6.png

モデルの構築は愚直に、、、

excitation_input_multi = tf.keras.Input(shape=(), dtype=tf.dtypes.string)

cluster_state_multi = tfq.layers.AddCircuit()(
    excitation_input_multi, prepend=cluster_state_circuit(cluster_state_bits))

# apply 3 different filters and measure expectation values

quantum_model_multi1 = tfq.layers.PQC(
    multi_readout_model_circuit(cluster_state_bits),
    readouts)(cluster_state_multi)

quantum_model_multi2 = tfq.layers.PQC(
    multi_readout_model_circuit(cluster_state_bits),
    readouts)(cluster_state_multi)

quantum_model_multi3 = tfq.layers.PQC(
    multi_readout_model_circuit(cluster_state_bits),
    readouts)(cluster_state_multi)

# concatenate outputs and feed into a small classical NN
concat_out = tf.keras.layers.concatenate(
    [quantum_model_multi1, quantum_model_multi2, quantum_model_multi3])

dense_1 = tf.keras.layers.Dense(8)(concat_out)

dense_2 = tf.keras.layers.Dense(1)(dense_1)

multi_qconv_model = tf.keras.Model(inputs=[excitation_input_multi],
                                   outputs=[dense_2])

# Display the model architecture
tf.keras.utils.plot_model(multi_qconv_model,
                          show_shapes=True,
                          show_layer_names=True,
                          dpi=70)

ダウンロード (4).png

トレーニングします。

multi_qconv_model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=0.02),
    loss=tf.losses.mse,
    metrics=[custom_accuracy])

multi_qconv_history = multi_qconv_model.fit(x=train_excitations,
                                            y=train_labels,
                                            batch_size=16,
                                            epochs=25,
                                            verbose=1,
                                            validation_data=(test_excitations,
                                                             test_labels))
Train on 112 samples, validate on 48 samples
Epoch 1/25
112/112 [==============================] - 10s 91ms/sample - loss: 0.6057 - custom_accuracy: 0.8393 - val_loss: 0.2694 - val_custom_accuracy: 0.9167
Epoch 2/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.2410 - custom_accuracy: 0.9196 - val_loss: 0.1797 - val_custom_accuracy: 0.9375
Epoch 3/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.1958 - custom_accuracy: 0.9821 - val_loss: 0.2076 - val_custom_accuracy: 1.0000
Epoch 4/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.1943 - custom_accuracy: 0.9821 - val_loss: 0.2426 - val_custom_accuracy: 0.9583
Epoch 5/25
112/112 [==============================] - 8s 76ms/sample - loss: 0.2230 - custom_accuracy: 0.9554 - val_loss: 0.2305 - val_custom_accuracy: 0.9792
Epoch 6/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.1982 - custom_accuracy: 0.9732 - val_loss: 0.2325 - val_custom_accuracy: 0.9375
Epoch 7/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.2078 - custom_accuracy: 0.9643 - val_loss: 0.2103 - val_custom_accuracy: 0.9583
Epoch 8/25
112/112 [==============================] - 8s 76ms/sample - loss: 0.1760 - custom_accuracy: 0.9821 - val_loss: 0.1868 - val_custom_accuracy: 1.0000
Epoch 9/25
112/112 [==============================] - 9s 76ms/sample - loss: 0.1732 - custom_accuracy: 0.9732 - val_loss: 0.1745 - val_custom_accuracy: 1.0000
Epoch 10/25
112/112 [==============================] - 8s 76ms/sample - loss: 0.1745 - custom_accuracy: 0.9911 - val_loss: 0.1895 - val_custom_accuracy: 0.9583
Epoch 11/25
112/112 [==============================] - 9s 76ms/sample - loss: 0.1686 - custom_accuracy: 0.9911 - val_loss: 0.1859 - val_custom_accuracy: 0.9792
Epoch 12/25
112/112 [==============================] - 9s 76ms/sample - loss: 0.1675 - custom_accuracy: 0.9911 - val_loss: 0.1853 - val_custom_accuracy: 0.9583
Epoch 13/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.1724 - custom_accuracy: 0.9911 - val_loss: 0.2022 - val_custom_accuracy: 0.9583
Epoch 14/25
112/112 [==============================] - 9s 77ms/sample - loss: 0.2089 - custom_accuracy: 0.9554 - val_loss: 0.2369 - val_custom_accuracy: 1.0000
Epoch 15/25
112/112 [==============================] - 9s 76ms/sample - loss: 0.2023 - custom_accuracy: 0.9554 - val_loss: 0.1921 - val_custom_accuracy: 0.9583
Epoch 16/25
112/112 [==============================] - 8s 76ms/sample - loss: 0.1711 - custom_accuracy: 0.9911 - val_loss: 0.1731 - val_custom_accuracy: 0.9583
Epoch 17/25
112/112 [==============================] - 9s 76ms/sample - loss: 0.2053 - custom_accuracy: 0.9732 - val_loss: 0.1959 - val_custom_accuracy: 0.9583
Epoch 18/25
112/112 [==============================] - 9s 76ms/sample - loss: 0.2074 - custom_accuracy: 0.9732 - val_loss: 0.2016 - val_custom_accuracy: 0.9792
Epoch 19/25
112/112 [==============================] - 8s 76ms/sample - loss: 0.1797 - custom_accuracy: 0.9732 - val_loss: 0.2167 - val_custom_accuracy: 0.9583
Epoch 20/25
112/112 [==============================] - 8s 76ms/sample - loss: 0.1810 - custom_accuracy: 0.9732 - val_loss: 0.1843 - val_custom_accuracy: 0.9583
Epoch 21/25
112/112 [==============================] - 9s 76ms/sample - loss: 0.1756 - custom_accuracy: 0.9911 - val_loss: 0.1999 - val_custom_accuracy: 1.0000
Epoch 22/25
112/112 [==============================] - 8s 76ms/sample - loss: 0.1803 - custom_accuracy: 0.9821 - val_loss: 0.1989 - val_custom_accuracy: 0.9167
Epoch 23/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.1716 - custom_accuracy: 0.9821 - val_loss: 0.1884 - val_custom_accuracy: 0.9583
Epoch 24/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.1614 - custom_accuracy: 1.0000 - val_loss: 0.1874 - val_custom_accuracy: 0.9583
Epoch 25/25
112/112 [==============================] - 8s 75ms/sample - loss: 0.1640 - custom_accuracy: 0.9911 - val_loss: 0.1937 - val_custom_accuracy: 0.9583
plt.plot(history.history['val_custom_accuracy'][:25], label='QCNN')
plt.plot(hybrid_history.history['val_custom_accuracy'][:25], label='Hybrid CNN')
plt.plot(multi_qconv_history.history['val_custom_accuracy'][:25],
         label='Hybrid CNN \n Multiple Quantum Filters')
plt.title('Quantum vs Hybrid CNN performance')
plt.xlabel('Epochs')
plt.legend()
plt.ylabel('Validation Accuracy')
plt.show()

ダウンロード (5).png

まだまだ量子NNは発展余地がありそうです。でも、意外とQCNNも成績よいすね。。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む