도움말 Kaggle에 TensorFlow과 그레이트 배리어 리프 (Great Barrier Reef)를 보호하기 도전에 참여

안녕하세요, 많은 세계

TensorFlow.org에서 보기 Google Colab에서 실행 GitHub에서 소스 보기 노트북 다운로드

이 튜토리얼은 기존 신경망이 큐비트 보정 오류를 수정하는 방법을 학습하는 방법을 보여줍니다. 그것은 소개 CIRQ , 편집, 제작하는 파이썬 프레임 워크를하고 시끄러운 중간 규모 양자 호출 (NISQ) 회로, TensorFlow 양자와 방법 CIRQ 인터페이스를 보여줍니다.

설정

pip install tensorflow==2.4.1

TensorFlow Quantum 설치:

pip install tensorflow-quantum
# Update package resources to account for version changes.
import importlib, pkg_resources
importlib.reload(pkg_resources)
<module 'pkg_resources' from '/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/pkg_resources/__init__.py'>

이제 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
2021-10-12 11:16:10.499542: E tensorflow/stream_executor/cuda/cuda_driver.cc:328] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected

1. 기본

1.1 Cirq 및 매개변수화된 양자 회로

TensorFlow 양자 (TFQ)을 탐험하기 전에, 일부에서의 살펴 보자 CIRQ의 기초를. Cirq는 Google의 양자 컴퓨팅을 위한 Python 라이브러리입니다. 이를 사용하여 정적 및 매개변수화된 게이트를 포함한 회로를 정의합니다.

CIRQ는 사용 SymPy의 무료 매개 변수를 나타내는 문자.

a, b = sympy.symbols('a b')

다음 코드는 매개변수를 사용하여 2큐비트 회로를 생성합니다.

# Create two qubits
q0, q1 = cirq.GridQubit.rect(1, 2)

# Create a circuit on these qubits using the parameters you created above.
circuit = cirq.Circuit(
    cirq.rx(a).on(q0),
    cirq.ry(b).on(q1), cirq.CNOT(control=q0, target=q1))

SVGCircuit(circuit)
findfont: Font family ['Arial'] not found. Falling back to DejaVu Sans.

SVG

회로를 평가하기 위해, 당신은 사용할 수 있습니다 cirq.Simulator 인터페이스를. 당신은 전달하여 특정 번호와 회로 무료 매개 변수를 대체 cirq.ParamResolver 객체입니다. 다음 코드는 매개변수화된 회로의 원시 상태 벡터 출력을 계산합니다.

# Calculate a state vector with a=0.5 and b=-0.5.
resolver = cirq.ParamResolver({a: 0.5, b: -0.5})
output_state_vector = cirq.Simulator().simulate(circuit, resolver).final_state_vector
output_state_vector
array([ 0.9387913 +0.j        , -0.23971277+0.j        ,

        0.        +0.06120872j,  0.        -0.23971277j], dtype=complex64)

상태 벡터는 시뮬레이션 외부에서 직접 액세스할 수 없습니다(위의 출력에서 ​​복소수 참고). 물리적으로 현실적이려면 상태 벡터를 기존 컴퓨터가 이해할 수 있는 실수로 변환하는 측정값을 지정해야 합니다. 의 조합을 이용하여 측정 CIRQ 지정 파울리 사업자 \(\hat{X}\), \(\hat{Y}\)및 \(\hat{Z}\). 그림으로, 다음 코드 조치 \(\hat{Z}_0\) 및 \(\frac{1}{2}\hat{Z}_0 + \hat{X}_1\) 그냥 시뮬레이션 상태 벡터에를 :

z0 = cirq.Z(q0)

qubit_map={q0: 0, q1: 1}

z0.expectation_from_state_vector(output_state_vector, qubit_map).real
0.8775825500488281
z0x1 = 0.5 * z0 + cirq.X(q1)

z0x1.expectation_from_state_vector(output_state_vector, qubit_map).real
-0.04063427448272705

1.2 텐서로서의 양자 회로

TensorFlow 양자 (TFQ)가 제공 tfq.convert_to_tensor , 변환 CIRQ 텐서는 개체로하는 기능. 이것은 당신이 우리에게 CIRQ 객체를 보낼 수 있습니다 양자 층양자 작전 . 함수는 Cirq Circuits 및 Cirq Paulis의 목록 또는 배열에서 호출할 수 있습니다.

# Rank 1 tensor containing 1 circuit.
circuit_tensor = tfq.convert_to_tensor([circuit])

print(circuit_tensor.shape)
print(circuit_tensor.dtype)
(1,)
<dtype: 'string'>

이 암호화하는 CIRQ는 다음과 같이 객체 tf.string 것을 텐서를 tfq 작업이 필요에 디코딩 할.

# Rank 1 tensor containing 2 Pauli operators.
pauli_tensor = tfq.convert_to_tensor([z0, z0x1])
pauli_tensor.shape
TensorShape([2])

1.3 일괄 회로 시뮬레이션

TFQ는 기대값, 샘플 및 상태 벡터를 계산하는 방법을 제공합니다. 지금은 기대 값에의 집중을 할 수 있습니다.

기대 값을 계산하는 최고 레벨 인터페이스이다 tfq.layers.Expectation A는 층 tf.keras.Layer . 가장 간단한 형태에서,이 층은 다수의 파라미터를 통해 회로 시뮬레이션에 해당 cirq.ParamResolvers ; 그러나 TFQ는 TensorFlow 의미 체계에 따라 일괄 처리를 허용하고 효율적인 C++ 코드를 사용하여 회로를 시뮬레이션합니다.

우리를 대체 값의 배치를 만들기 와 a b 매개 변수 :

batch_vals = np.array(np.random.uniform(0, 2 * np.pi, (5, 2)), dtype=np.float32)

Cirq의 매개변수 값에 대한 일괄 회로 실행에는 루프가 필요합니다.

cirq_results = []
cirq_simulator = cirq.Simulator()

for vals in batch_vals:
    resolver = cirq.ParamResolver({a: vals[0], b: vals[1]})
    final_state_vector = cirq_simulator.simulate(circuit, resolver).final_state_vector
    cirq_results.append(
        [z0.expectation_from_state_vector(final_state_vector, {
            q0: 0,
            q1: 1
        }).real])

print('cirq batch results: \n {}'.format(np.array(cirq_results)))
cirq batch results: 
 [[-0.86000198]
 [-0.83201134]
 [-0.93121868]
 [ 0.28362957]
 [ 0.72345072]]

TFQ에서는 동일한 작업이 단순화됩니다.

tfq.layers.Expectation()(circuit,
                         symbol_names=[a, b],
                         symbol_values=batch_vals,
                         operators=z0)
<tf.Tensor: shape=(5, 1), dtype=float32, numpy=
array([[-0.8600013 ],
       [-0.83201194],
       [-0.931218  ],
       [ 0.28362915],
       [ 0.7234506 ]], dtype=float32)>

2. 하이브리드 양자-고전 최적화

이제 기초를 보았으므로, 이제 TensorFlow 양자 하이브리드 양자 - 고전 신경망을 구성하는 데 사용할 수 있습니다. 단일 큐비트를 제어하기 위해 고전적인 신경망을 훈련할 것입니다. 제어는 정확하게 상기 큐빗을 제조 최적화한다 0 또는 1 모사 체계적인 교정 오차를 극복 상태. 이 그림은 아키텍처를 보여줍니다.

신경망이 없어도 이것은 해결하기 쉬운 문제이지만 주제는 TFQ를 사용하여 해결할 수 있는 실제 양자 제어 문제와 유사합니다. 그것은 사용 양자 고전 연산 종단 예를 보여 tfq.layers.ControlledPQC (A)의 (매개 변수화 양자 회로) 층 내부 tf.keras.Model .

이 튜토리얼의 구현을 위해 이 아키텍처는 세 부분으로 나뉩니다.

  • 입력 데이터 포인트 회로 또는 회로 : 처음 세 \(R\) 게이트.
  • 제어 회로는 다른 세 \(R\) 게이트.
  • 컨트롤러 : 제어 회로의 파라미터를 설정 고전 신경망.

2.1 제어 회로 정의

위 그림과 같이 학습 가능한 단일 비트 회전을 정의합니다. 이것은 우리의 제어 회로에 해당합니다.

# Parameters that the classical NN will feed values into.
control_params = sympy.symbols('theta_1 theta_2 theta_3')

# Create the parameterized circuit.
qubit = cirq.GridQubit(0, 0)
model_circuit = cirq.Circuit(
    cirq.rz(control_params[0])(qubit),
    cirq.ry(control_params[1])(qubit),
    cirq.rx(control_params[2])(qubit))

SVGCircuit(model_circuit)

SVG

2.2 컨트롤러

이제 컨트롤러 네트워크를 정의합니다.

# The classical neural network layers.
controller = tf.keras.Sequential([
    tf.keras.layers.Dense(10, activation='elu'),
    tf.keras.layers.Dense(3)
])

명령 배치가 주어지면 컨트롤러는 제어 회로에 대한 제어 신호 배치를 출력합니다.

컨트롤러는 무작위로 초기화되므로 이러한 출력은 아직 유용하지 않습니다.

controller(tf.constant([[0.0],[1.0]])).numpy()
array([[ 0.        ,  0.        ,  0.        ],
       [ 0.37945798, -0.31607187,  0.23631476]], dtype=float32)

2.3 컨트롤러를 회로에 연결

사용 tfq 하나로서, 제어 회로 제어기를 연결 keras.Model .

참고 항목 Keras 기능 API 가이드를 모델 정의의이 스타일에 대해 더 많은 것을 위해.

먼저 모델에 대한 입력을 정의합니다.

# This input is the simulated miscalibration that the model will learn to correct.
circuits_input = tf.keras.Input(shape=(),
                                # The circuit-tensor has dtype `tf.string` 
                                dtype=tf.string,
                                name='circuits_input')

# Commands will be either `0` or `1`, specifying the state to set the qubit to.
commands_input = tf.keras.Input(shape=(1,),
                                dtype=tf.dtypes.float32,
                                name='commands_input')

그런 다음 해당 입력에 연산을 적용하여 계산을 정의합니다.

dense_2 = controller(commands_input)

# TFQ layer for classically controlled circuits.
expectation_layer = tfq.layers.ControlledPQC(model_circuit,
                                             # Observe Z
                                             operators = cirq.Z(qubit))
expectation = expectation_layer([circuits_input, dense_2])

지금과 같은이 계산 패키지 tf.keras.Model :

# The full Keras model is built from our layers.
model = tf.keras.Model(inputs=[circuits_input, commands_input],
                       outputs=expectation)

네트워크 아키텍처는 아래 모델의 플롯으로 표시됩니다. 이 모델 플롯을 아키텍처 다이어그램과 비교하여 정확성을 확인합니다.

tf.keras.utils.plot_model(model, show_shapes=True, dpi=70)

png

이 모델은 컨트롤러에 대한 명령과 컨트롤러가 수정하려고 하는 출력의 입력 회로라는 두 가지 입력을 받습니다.

2.4 데이터세트

출력 모델 시도 정확한 올바른 측정 값 \(\hat{Z}\) 각 명령. 명령과 올바른 값은 아래에 정의되어 있습니다.

# The command input values to the classical NN.
commands = np.array([[0], [1]], dtype=np.float32)

# The desired Z expectation value at output of quantum circuit.
expected_outputs = np.array([[1], [-1]], dtype=np.float32)

이것은 이 작업에 대한 전체 교육 데이터 세트가 아닙니다. 데이터 세트의 각 데이터 포인트에는 입력 회로도 필요합니다.

2.4 입력 회로 정의

아래의 입력 회로는 모델이 수정하도록 학습할 임의의 오교정을 정의합니다.

random_rotations = np.random.uniform(0, 2 * np.pi, 3)
noisy_preparation = cirq.Circuit(
  cirq.rx(random_rotations[0])(qubit),
  cirq.ry(random_rotations[1])(qubit),
  cirq.rz(random_rotations[2])(qubit)
)
datapoint_circuits = tfq.convert_to_tensor([
  noisy_preparation
] * 2)  # Make two copied of this circuit

각 데이터 포인트에 대해 하나씩 두 개의 회로 복사본이 있습니다.

datapoint_circuits.shape
TensorShape([2])

2.5 훈련

입력이 정의 사용하면 테스트를 실행 할 수 tfq 모델을.

model([datapoint_circuits, commands]).numpy()
array([[-0.74668354],
       [-0.8791507 ]], dtype=float32)

지금으로이 값을 조정하기 위해 표준 교육 과정을 실행 expected_outputs .

optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)
loss = tf.keras.losses.MeanSquaredError()
model.compile(optimizer=optimizer, loss=loss)
history = model.fit(x=[datapoint_circuits, commands],
                    y=expected_outputs,
                    epochs=30,
                    verbose=0)
plt.plot(history.history['loss'])
plt.title("Learning to Control a Qubit")
plt.xlabel("Iterations")
plt.ylabel("Error in Control")
plt.show()

png

이 플롯에서 신경망이 체계적인 오보정을 극복하는 방법을 배웠음을 알 수 있습니다.

2.6 출력 확인

이제 훈련된 모델을 사용하여 큐비트 보정 오류를 수정합니다. Cirq와 함께:

def check_error(command_values, desired_values):
  """Based on the value in `command_value` see how well you could prepare
  the full circuit to have `desired_value` when taking expectation w.r.t. Z."""
  params_to_prepare_output = controller(command_values).numpy()
  full_circuit = noisy_preparation + model_circuit

  # Test how well you can prepare a state to get expectation the expectation
  # value in `desired_values`
  for index in [0, 1]:
    state = cirq_simulator.simulate(
        full_circuit,
        {s:v for (s,v) in zip(control_params, params_to_prepare_output[index])}
    ).final_state_vector
    expt = cirq.Z(qubit).expectation_from_state_vector(state, {qubit: 0}).real
    print(f'For a desired output (expectation) of {desired_values[index]} with'
          f' noisy preparation, the controller\nnetwork found the following '
          f'values for theta: {params_to_prepare_output[index]}\nWhich gives an'
          f' actual expectation of: {expt}\n')


check_error(commands, expected_outputs)
For a desired output (expectation) of [1.] with noisy preparation, the controller
network found the following values for theta: [-2.3688276   3.655123    0.24446163]
Which gives an actual expectation of: 0.9826769232749939

For a desired output (expectation) of [-1.] with noisy preparation, the controller
network found the following values for theta: [2.3142653  0.05689991 0.72213745]
Which gives an actual expectation of: -0.988701581954956

훈련 중 손실 함수의 값은 모델이 얼마나 잘 학습하고 있는지에 대한 대략적인 아이디어를 제공합니다. 상기 셀의 낮은 손실 가까울 기대 값이다 desired_values . 당신은 같은 매개 변수 값과 관련되지 않은 경우, 당신은 항상 사용 위에서 출력을 확인할 수 있습니다 tfq :

model([datapoint_circuits, commands])
<tf.Tensor: shape=(2, 1), dtype=float32, numpy=
array([[ 0.9826765 ],
       [-0.98870134]], dtype=float32)>

3 다른 연산자의 고유 상태를 준비하는 방법 학습

의 선택 \(\pm \hat{Z}\) 1과 0에 대응하는 고유 상태는 임의이다. 당신은 쉽게 가지고에 해당하는 1 원 수 \(+ \hat{Z}\) 받는 해당하는 고유 상태 0 \(-\hat{X}\) 고유 상태. 이를 수행하는 한 가지 방법은 아래 그림에 표시된 대로 각 명령에 대해 다른 측정 연산자를 지정하는 것입니다.

이것은 사용이 필요 tfq.layers.Expectation . 이제 입력에 회로, 명령 및 연산자의 세 가지 개체가 포함됩니다. 출력은 여전히 ​​기대값입니다.

3.1 새로운 모델 정의

이 작업을 수행하기 위한 모델을 살펴보겠습니다.

# Define inputs.
commands_input = tf.keras.layers.Input(shape=(1),
                                       dtype=tf.dtypes.float32,
                                       name='commands_input')
circuits_input = tf.keras.Input(shape=(),
                                # The circuit-tensor has dtype `tf.string` 
                                dtype=tf.dtypes.string,
                                name='circuits_input')
operators_input = tf.keras.Input(shape=(1,),
                                 dtype=tf.dtypes.string,
                                 name='operators_input')

컨트롤러 네트워크는 다음과 같습니다.

# Define classical NN.
controller = tf.keras.Sequential([
    tf.keras.layers.Dense(10, activation='elu'),
    tf.keras.layers.Dense(3)
])

회로 단일 제어기에 결합 keras.Model 사용 tfq :

dense_2 = controller(commands_input)

# Since you aren't using a PQC or ControlledPQC you must append
# your model circuit onto the datapoint circuit tensor manually.
full_circuit = tfq.layers.AddCircuit()(circuits_input, append=model_circuit)
expectation_output = tfq.layers.Expectation()(full_circuit,
                                              symbol_names=control_params,
                                              symbol_values=dense_2,
                                              operators=operators_input)

# Contruct your Keras model.
two_axis_control_model = tf.keras.Model(
    inputs=[circuits_input, commands_input, operators_input],
    outputs=[expectation_output])

3.2 데이터세트

이제 당신은 또한 당신이 당신이 제공 각각의 데이터 포인트에 대한 측정하고자하는 사업자 포함됩니다 model_circuit :

# The operators to measure, for each command.
operator_data = tfq.convert_to_tensor([[cirq.X(qubit)], [cirq.Z(qubit)]])

# The command input values to the classical NN.
commands = np.array([[0], [1]], dtype=np.float32)

# The desired expectation value at output of quantum circuit.
expected_outputs = np.array([[1], [-1]], dtype=np.float32)

3.3 훈련

이제 새 입력과 출력이 있으므로 케라스를 사용하여 다시 한 번 훈련할 수 있습니다.

optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)
loss = tf.keras.losses.MeanSquaredError()

two_axis_control_model.compile(optimizer=optimizer, loss=loss)

history = two_axis_control_model.fit(
    x=[datapoint_circuits, commands, operator_data],
    y=expected_outputs,
    epochs=30,
    verbose=1)
Epoch 1/30
1/1 [==============================] - 0s 336ms/step - loss: 1.3425
Epoch 2/30
1/1 [==============================] - 0s 3ms/step - loss: 1.0469
Epoch 3/30
1/1 [==============================] - 0s 3ms/step - loss: 0.7611
Epoch 4/30
1/1 [==============================] - 0s 3ms/step - loss: 0.4976
Epoch 5/30
1/1 [==============================] - 0s 2ms/step - loss: 0.3565
Epoch 6/30
1/1 [==============================] - 0s 2ms/step - loss: 0.2611
Epoch 7/30
1/1 [==============================] - 0s 2ms/step - loss: 0.1574
Epoch 8/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0850
Epoch 9/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0568
Epoch 10/30
1/1 [==============================] - 0s 3ms/step - loss: 0.0536
Epoch 11/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0608
Epoch 12/30
1/1 [==============================] - 0s 3ms/step - loss: 0.0648
Epoch 13/30
1/1 [==============================] - 0s 3ms/step - loss: 0.0581
Epoch 14/30
1/1 [==============================] - 0s 3ms/step - loss: 0.0473
Epoch 15/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0396
Epoch 16/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0348
Epoch 17/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0310
Epoch 18/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0278
Epoch 19/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0258
Epoch 20/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0249
Epoch 21/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0230
Epoch 22/30
1/1 [==============================] - 0s 3ms/step - loss: 0.0189
Epoch 23/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0132
Epoch 24/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0078
Epoch 25/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0040
Epoch 26/30
1/1 [==============================] - 0s 2ms/step - loss: 0.0019
Epoch 27/30
1/1 [==============================] - 0s 2ms/step - loss: 8.9138e-04
Epoch 28/30
1/1 [==============================] - 0s 2ms/step - loss: 5.2909e-04
Epoch 29/30
1/1 [==============================] - 0s 3ms/step - loss: 4.9192e-04
Epoch 30/30
1/1 [==============================] - 0s 2ms/step - loss: 6.7420e-04
plt.plot(history.history['loss'])
plt.title("Learning to Control a Qubit")
plt.xlabel("Iterations")
plt.ylabel("Error in Control")
plt.show()

png

손실 함수가 0으로 떨어졌습니다.

controller 독립형 모델로 사용할 수 있습니다. 컨트롤러를 호출하고 각 명령 신호에 대한 응답을 확인합니다. 그것은 정확하게의 내용이 출력을 비교하기 위해 몇 가지 작업을 할 random_rotations .

controller.predict(np.array([0,1]))
array([[-2.846111  , -0.89885163, -1.3263428 ],
       [-1.2928145 , -0.22680755, -0.6467615 ]], dtype=float32)