ホーム » TensorFlow Quantum » TensorFlow Quantum 0.2.0 : Tutorials : 量子畳込みニューラルネットワーク

TensorFlow Quantum 0.2.0 : Tutorials : 量子畳込みニューラルネットワーク

TensorFlow Quantum 0.2.0 Tutorials : 量子畳込みニューラルネットワーク (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 03/19/2020 (0.2.0)

* 本ページは、TensorFlow Quantum の以下のページを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

Tutorials : 量子畳込みニューラルネットワーク

このチュートリアルは単純化された 量子畳込みニューラルネットワーク (QCNN) を実装します、古典的畳込みニューラルネットワークへの提案された量子類推で、これは翻訳的に不変でもあります。

このサンプルは、量子センサーやデバイスからの複雑なシミュレーションのような量子データソースの特定のプロパティをどのように検出するかを実演します。励起を持つあるいは持たないかもしれない クラスタ状態 である量子データソース — QCNN が検出することを学習するものです (ペーパーで使用されたデータソースは SPT 位相分類です)。

 

セットアップ

TensorFlow Quantum をインストールします :

pip install -q tensorflow-quantum

今は TensorFlow とモジュール依存性をインポートします :

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

 

1. QCNN を構築する

1.1 TensorFlow グラフで回路をアセンブルする

TensorFlow Quantum (TFQ) は in-graph 回路構築のために設計された層クラスを提供します。一つの例は tf.keras.Layer から継承した tfq.layers.AddCircuit 層です。この層は次の図で示されるように回路の入力バッチに prepend か append (i.e. 前に追加または後に追加) できます。

次のスニペットはこの層を使用します :

qubit = cirq.GridQubit(0, 0)

# Define some circuits.
circuit1 = cirq.Circuit(cirq.X(qubit))
circuit2 = cirq.Circuit(cirq.H(qubit))

# Convert to a tensor.
input_circuit_tensor = tfq.convert_to_tensor([circuit1, circuit2])

# Define a circuit that we want to append
y_circuit = cirq.Circuit(cirq.Y(qubit))

# Instantiate our layer
y_appender = tfq.layers.AddCircuit()

# Run our circuit tensor through the layer and save the output.
output_circuit_tensor = y_appender(input_circuit_tensor, append=y_circuit)

入力 tensor を検証します :

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)),
    ]),
])]

そして出力 tensor を検証します :

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)),
    ]),
])]

tfq.layers.AddCircuit を使用することなく下のサンプルを実行できる一方で、どれほど複雑な機能が TensorFlow 計算グラフに埋め込めるかを理解する良い機会です。

 

1.2 問題概要

クラスタ状態を準備して (量子が) 「励起」しているか否かを検出するために量子分類器を訓練します。クラスタ状態は非常にもつれていますが、古典的コンピュータのためには必ずしも難しくはありません。明確にするため、これはペーパーで使用されたものよりも単純なデータセットです。

この分類タスクのため深層 MERA-like QCNN を実装します、何故ならば :

  1. QCNN のように、リング上のクラスタ状態は翻訳的に不変です。
  2. クラスタ状態は非常にもつれています。

このアーキテクチャはエンタングルメントを減じ、シングル量子ビットを読み出すことにより分類を得ることに効果的であるはずです。

「励起」クラスタ状態はその任意の量子ビットに適用される cirq.Rx ゲートを持ったクラスタ状態として定義されます。

Qconv と QPool はこのチュートリアルで後で議論されます。

 

1.3 TensorFlow のためにブロックを構築する

この問題を TensorFlow Quantum で解く一つの方法は以下を実装することです :

  1. モデルへの入力は回路 tensor です — 空の回路か励起を示す特定の量子ビット上の X ゲートです。
  2. 残りのモデルの量子コンポーネントは tfq.layers.AddCircuit 層で構築されます。
  3. 推論のために tfq.layers.PQC が使用されます。これはそれを読む励起状態のための 1 か、非励起状態のための -1 のラベルと比較します。

 

1.4 データ

モデルを構築する前に、データを生成できます。この場合クラスタ状態への基底状態になります (元ペーパーはより複雑なデータセットを使用しています)。励起は 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.521π)─── Output: -1
Input: (0, 1): ───Rx(0.073π)─── Output: 1

/tmpfs/src/tf_docs_env/lib/python3.6/site-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__':

 

1.5 層を定義する

今は TensorFlow で上の図で示される層を定義します。

 

1.5.1 クラスタ状態

最初のステップは Cirq を使用して クラスタ状態 を定義します、量子回路をプログラミングするための Google 提供のフレームワークです。これはモデルの静的パートですから、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

cirq.GridQubits の矩形のためのクラスタ状態回路を表示します :

SVGCircuit(cluster_state_circuit(cirq.GridQubit.rect(1, 4)))
findfont: Font family ['Arial'] not found. Falling back to DejaVu Sans.

 

1.5.2 QCNN 層

Cong と Lukin QCNN ペーパー を使用してモデルを構成する層を定義します。

2, 3 の必要条件があります :

  • Tucci ペーパー からの 1- と 2-量子ビットのパラメータ化されたユニタリ行列。
  • 一般的なパラメータ化された 2-量子ビット・プーリング演算。
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')))

そして 2-量子ビット・プーリング回路 :

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

 

1.5.2.1 量子畳込み

Cong と Lukin ペーパーでのように、1D 量子畳込みを 1 のストライドを持つ隣接量子ビットの総てのペアへの 2-量子ビットのパラメータ化されたユニタリのアプリケーションとして定義します。

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')))

 

1.5.2.2 Quantum プーリング

量子プーリング層は上で定義された 2-量子ビットプールを使用して $N$ 量子ビットから $\frac{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')))

 

1.6 モデル定義

今は純粋に量子 CNN を構築するために定義された層を使用します。8 量子ビットから始めて、1 にプールダウンし、それから $\langle \hat{Z} \rangle$ を測定します。

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)
Failed to import pydot. You must install pydot and graphviz for `pydotprint` to work.

 

1.7 モデルを訓練する

このサンプルを単純化するために full バッチに渡りモデルを訓練します。

# 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))
/tmpfs/src/tf_docs_env/lib/python3.6/site-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__':

Train on 112 samples, validate on 48 samples
Epoch 1/25
112/112 [==============================] - 9s 80ms/sample - loss: 0.9000 - custom_accuracy: 0.6964 - val_loss: 0.8341 - val_custom_accuracy: 0.7708
Epoch 2/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.8153 - custom_accuracy: 0.7589 - val_loss: 0.7915 - val_custom_accuracy: 0.6875
Epoch 3/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7882 - custom_accuracy: 0.6786 - val_loss: 0.7726 - val_custom_accuracy: 0.6875
Epoch 4/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7570 - custom_accuracy: 0.6786 - val_loss: 0.7746 - val_custom_accuracy: 0.7292
Epoch 5/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7500 - custom_accuracy: 0.8214 - val_loss: 0.7413 - val_custom_accuracy: 0.7708
Epoch 6/25
112/112 [==============================] - 4s 36ms/sample - loss: 0.7262 - custom_accuracy: 0.7857 - val_loss: 0.7177 - val_custom_accuracy: 0.7708
Epoch 7/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7164 - custom_accuracy: 0.7857 - val_loss: 0.7337 - val_custom_accuracy: 0.7708
Epoch 8/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7096 - custom_accuracy: 0.8214 - val_loss: 0.7230 - val_custom_accuracy: 0.7917
Epoch 9/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7040 - custom_accuracy: 0.7857 - val_loss: 0.7200 - val_custom_accuracy: 0.7917
Epoch 10/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7015 - custom_accuracy: 0.8125 - val_loss: 0.7186 - val_custom_accuracy: 0.7500
Epoch 11/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7074 - custom_accuracy: 0.8125 - val_loss: 0.7207 - val_custom_accuracy: 0.8333
Epoch 12/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7030 - custom_accuracy: 0.8036 - val_loss: 0.7212 - val_custom_accuracy: 0.7500
Epoch 13/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7061 - custom_accuracy: 0.8214 - val_loss: 0.7200 - val_custom_accuracy: 0.7917
Epoch 14/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.6991 - custom_accuracy: 0.8125 - val_loss: 0.7059 - val_custom_accuracy: 0.7708
Epoch 15/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.6967 - custom_accuracy: 0.7946 - val_loss: 0.7286 - val_custom_accuracy: 0.7500
Epoch 16/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7054 - custom_accuracy: 0.7768 - val_loss: 0.7114 - val_custom_accuracy: 0.7292
Epoch 17/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7014 - custom_accuracy: 0.8036 - val_loss: 0.7059 - val_custom_accuracy: 0.8125
Epoch 18/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7000 - custom_accuracy: 0.8125 - val_loss: 0.7147 - val_custom_accuracy: 0.7708
Epoch 19/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.7052 - custom_accuracy: 0.7946 - val_loss: 0.7162 - val_custom_accuracy: 0.7708
Epoch 20/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.6977 - custom_accuracy: 0.7768 - val_loss: 0.7132 - val_custom_accuracy: 0.7708
Epoch 21/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.6922 - custom_accuracy: 0.8125 - val_loss: 0.7051 - val_custom_accuracy: 0.8333
Epoch 22/25
112/112 [==============================] - 4s 38ms/sample - loss: 0.6853 - custom_accuracy: 0.8036 - val_loss: 0.6983 - val_custom_accuracy: 0.7917
Epoch 23/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.6894 - custom_accuracy: 0.8125 - val_loss: 0.7099 - val_custom_accuracy: 0.8333
Epoch 24/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.6918 - custom_accuracy: 0.8036 - val_loss: 0.7101 - val_custom_accuracy: 0.7708
Epoch 25/25
112/112 [==============================] - 4s 37ms/sample - loss: 0.6844 - custom_accuracy: 0.8125 - val_loss: 0.7042 - val_custom_accuracy: 0.8125
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()

 

2. ハイブリッドモデル

量子畳込みを使用して 8 量子ビットから 1 量子ビットに進まなくてもかまいません — 量子畳込みの 1 or 2 ラウンドは遂行してそして結果を古典的ニューラルネットワークに供給できたでしょう。このセクションは量子古典的ハイブリッドモデルを調査します。

 

2.1 シングル量子フィルタを持つハイブリッドモデル

量子畳込みの 1 層を適用し、総てのビット上で $\langle \hat{Z}_n \rangle$ を読み出し、密結合ニューラルネットワークが続きます。

 

2.1.1 モデル定義

# 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)
Failed to import pydot. You must install pydot and graphviz for `pydotprint` to work.

 

2.1.2 モデルを訓練する

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 [==============================] - 2s 17ms/sample - loss: 0.8153 - custom_accuracy: 0.7054 - val_loss: 0.5564 - val_custom_accuracy: 0.9375
Epoch 2/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.3411 - custom_accuracy: 0.9464 - val_loss: 0.2293 - val_custom_accuracy: 0.9792
Epoch 3/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2589 - custom_accuracy: 0.9375 - val_loss: 0.3495 - val_custom_accuracy: 0.9375
Epoch 4/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2937 - custom_accuracy: 0.9286 - val_loss: 0.3041 - val_custom_accuracy: 0.9375
Epoch 5/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2349 - custom_accuracy: 0.9375 - val_loss: 0.2303 - val_custom_accuracy: 0.9583
Epoch 6/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2100 - custom_accuracy: 0.9732 - val_loss: 0.2183 - val_custom_accuracy: 0.9583
Epoch 7/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2265 - custom_accuracy: 0.9643 - val_loss: 0.2752 - val_custom_accuracy: 0.9583
Epoch 8/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2341 - custom_accuracy: 0.9464 - val_loss: 0.2536 - val_custom_accuracy: 0.9375
Epoch 9/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2451 - custom_accuracy: 0.9643 - val_loss: 0.2470 - val_custom_accuracy: 0.9375
Epoch 10/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2159 - custom_accuracy: 0.9554 - val_loss: 0.3146 - val_custom_accuracy: 0.9583
Epoch 11/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2235 - custom_accuracy: 0.9643 - val_loss: 0.2395 - val_custom_accuracy: 0.9583
Epoch 12/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2073 - custom_accuracy: 0.9821 - val_loss: 0.2392 - val_custom_accuracy: 0.9375
Epoch 13/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2059 - custom_accuracy: 0.9643 - val_loss: 0.2321 - val_custom_accuracy: 0.9583
Epoch 14/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2076 - custom_accuracy: 0.9554 - val_loss: 0.2758 - val_custom_accuracy: 0.9792
Epoch 15/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2035 - custom_accuracy: 0.9821 - val_loss: 0.2312 - val_custom_accuracy: 0.9375
Epoch 16/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.1956 - custom_accuracy: 0.9821 - val_loss: 0.2307 - val_custom_accuracy: 0.9375
Epoch 17/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.1957 - custom_accuracy: 0.9821 - val_loss: 0.2876 - val_custom_accuracy: 0.9583
Epoch 18/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2172 - custom_accuracy: 0.9732 - val_loss: 0.2441 - val_custom_accuracy: 0.9583
Epoch 19/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2082 - custom_accuracy: 0.9643 - val_loss: 0.2372 - val_custom_accuracy: 0.9583
Epoch 20/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.1945 - custom_accuracy: 0.9911 - val_loss: 0.2340 - val_custom_accuracy: 0.9583
Epoch 21/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.1993 - custom_accuracy: 0.9821 - val_loss: 0.2309 - val_custom_accuracy: 0.9583
Epoch 22/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2095 - custom_accuracy: 0.9732 - val_loss: 0.2818 - val_custom_accuracy: 0.9583
Epoch 23/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2153 - custom_accuracy: 0.9732 - val_loss: 0.2753 - val_custom_accuracy: 0.9583
Epoch 24/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.2029 - custom_accuracy: 0.9554 - val_loss: 0.2344 - val_custom_accuracy: 0.9375
Epoch 25/25
112/112 [==============================] - 1s 9ms/sample - loss: 0.1942 - custom_accuracy: 0.9821 - val_loss: 0.2577 - val_custom_accuracy: 0.9583
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()

見れるように、非常に控えめな古典的援助により、ハイブリッドモデルは通常は純粋な量子バージョンよりも早く収束します。

 

2.2 マルチ量子フィルタを持つハイブリッド畳込み

今はマルチ量子畳込みとそれらを結合する古典的ニューラルネットワークを使用するアーキテクチャを試しましょう。

 

2.2.1 モデル定義

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)
Failed to import pydot. You must install pydot and graphviz for `pydotprint` to work.

 

2.2.2 モデルを訓練する

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 [==============================] - 3s 31ms/sample - loss: 0.9056 - custom_accuracy: 0.5982 - val_loss: 0.7414 - val_custom_accuracy: 0.7708
Epoch 2/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.6125 - custom_accuracy: 0.7768 - val_loss: 0.3953 - val_custom_accuracy: 0.8958
Epoch 3/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2967 - custom_accuracy: 0.9196 - val_loss: 0.2199 - val_custom_accuracy: 0.9583
Epoch 4/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2299 - custom_accuracy: 0.9643 - val_loss: 0.3186 - val_custom_accuracy: 0.9375
Epoch 5/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2521 - custom_accuracy: 0.9643 - val_loss: 0.2378 - val_custom_accuracy: 0.9792
Epoch 6/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2026 - custom_accuracy: 0.9911 - val_loss: 0.2087 - val_custom_accuracy: 0.9792
Epoch 7/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2090 - custom_accuracy: 0.9643 - val_loss: 0.3530 - val_custom_accuracy: 0.8958
Epoch 8/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2213 - custom_accuracy: 0.9821 - val_loss: 0.2496 - val_custom_accuracy: 0.9583
Epoch 9/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2120 - custom_accuracy: 0.9821 - val_loss: 0.2079 - val_custom_accuracy: 0.9583
Epoch 10/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2031 - custom_accuracy: 0.9643 - val_loss: 0.2319 - val_custom_accuracy: 0.9792
Epoch 11/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2244 - custom_accuracy: 0.9732 - val_loss: 0.2170 - val_custom_accuracy: 0.9583
Epoch 12/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2070 - custom_accuracy: 0.9911 - val_loss: 0.2239 - val_custom_accuracy: 1.0000
Epoch 13/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2096 - custom_accuracy: 0.9911 - val_loss: 0.2161 - val_custom_accuracy: 0.9583
Epoch 14/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2055 - custom_accuracy: 0.9911 - val_loss: 0.2395 - val_custom_accuracy: 0.9375
Epoch 15/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2158 - custom_accuracy: 1.0000 - val_loss: 0.2054 - val_custom_accuracy: 0.9583
Epoch 16/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2225 - custom_accuracy: 0.9554 - val_loss: 0.2311 - val_custom_accuracy: 0.9583
Epoch 17/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.1916 - custom_accuracy: 0.9821 - val_loss: 0.2121 - val_custom_accuracy: 0.9792
Epoch 18/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.1959 - custom_accuracy: 0.9732 - val_loss: 0.2517 - val_custom_accuracy: 0.9792
Epoch 19/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2069 - custom_accuracy: 0.9643 - val_loss: 0.2497 - val_custom_accuracy: 0.9375
Epoch 20/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2071 - custom_accuracy: 0.9911 - val_loss: 0.2162 - val_custom_accuracy: 1.0000
Epoch 21/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.1911 - custom_accuracy: 0.9911 - val_loss: 0.2114 - val_custom_accuracy: 0.9583
Epoch 22/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.1994 - custom_accuracy: 0.9911 - val_loss: 0.2173 - val_custom_accuracy: 0.9583
Epoch 23/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.1924 - custom_accuracy: 0.9643 - val_loss: 0.2548 - val_custom_accuracy: 0.9583
Epoch 24/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.2113 - custom_accuracy: 0.9911 - val_loss: 0.2084 - val_custom_accuracy: 0.9583
Epoch 25/25
112/112 [==============================] - 2s 14ms/sample - loss: 0.1952 - custom_accuracy: 0.9821 - val_loss: 0.2699 - 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()

 

以上






AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com