- 投稿日:2020-03-16T17:26:39+09:00
Win10にTensorflow2.1.0, CUDA10.1, cudnn7.6.5を入れる
本記事の内容
Windows10マシンにTensorflow2.1.0 + CUDA10.1 + cuDNN 7.6.5 をインストールする手順をまとめます。
以前のバージョンとの違い
- CUDAインストーラーがPATHを通してくれるようになった (環境変数を自分で変更しなくてよくなった)
- Visual Studio 2017の C++ compilerでは動かなくなった (VS2019再配布可能パッケージを入れればOK)
- CPU版tensorflowもC++ compiler必須になった (VS2019再配布可能パッケージを入れればOK)
- ロングネームを有効にしなきゃいけなくなった (必須かどうか未確認)
導入環境
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 bitCUDA, cuDNN, tensorflowのバージョン選定
今回使うGPUはturingアーキテクチャのRTX2080TiですのでCUDAは10.0以降であれば使えます。
https://en.wikipedia.org/wiki/CUDApipでインストールできる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/releases1. 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.7conda環境をつくったら有効にして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 psutilAnaconda_prompt(tf) $ pip install pillow opencv-pythonえんじょい
- 投稿日:2020-03-16T12:07:37+09:00
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.ipynbgoogle colabはこちら。
https://colab.research.google.com/github/minatoyuichiro/tensorflowquantum_hello/blob/master/qcnn.ipynbまずはGoogle colabを使っている人はTensorFlowのバージョンを合わせます。
try: %tensorflow_version 2.x except Exception: passTensorFlow 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 SVGCircuitQCNNを構築
ここで、TensorFlow Quantum(TFQ)はtf.keras.Layerを継承するtfq.layers.AddCircuitレイヤーを提供していて、回路をprependもしくはappendできます。
引用: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アーキテクチャを実装します。
引用:https://www.tensorflow.org/quantum/tutorials/qcnn
「励起」クラスター状態は、その量子ビットのいずれかにcirq.Rxゲートが適用されたクラスター状態として定義されます。 QconvとQPoolについては、このチュートリアルの後半で説明します。
構造はシンプルで、初期のクラスター状態を作ります。量子畳み込みと量子プーリングを通じて計算を行い、測定値の期待値を求め、その期待値の損失関数と教師データからパラメータを導入した量子回路を学習させます。
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 circuitSVGCircuit(cluster_state_circuit(cirq.GridQubit.rect(1, 4)))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')))次に2量子ビットの任意量子状態を作る回路もチェックします。
SVGCircuit(two_qubit_unitary(cirq.GridQubit.rect(1, 2), sympy.symbols('x0:15')))SVGCircuit(two_qubit_pool(*cirq.GridQubit.rect(1, 2), sympy.symbols('x0:6')))上記は面白くて、2量子ビットのもつれ回路を1量子ビットの量子状態へと落としこむプーリングです。
量子畳み込み層
上記を使って、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')))量子プーリング層
量子プール層は、上記で定義した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')))(部分的に割愛)
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)モデルのトレーニング
モデルをバッチでトレーニングします。
# 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.9375plt.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回噛ませた後に全ての量子ビットを測定して、古典NNにかけるやつをやってみます。
モデルはシンプル、
# 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)トレーニングします。
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()結果として、古典NNを噛ませることにより、ハイブリッドモデルは通常、純粋な量子バージョンよりも速く収束します。
複数の量子フィルターを使用したハイブリッド畳み込み
次に、複数の量子畳み込みと古典的なニューラルネットワークを使用してそれらを結合するアーキテクチャを試してみます。
モデルの構築は愚直に、、、
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)トレーニングします。
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.9583plt.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()まだまだ量子NNは発展余地がありそうです。でも、意外とQCNNも成績よいすね。。。