تاریخ را ذخیره کنید! Google I / O 18-20 مه بازمی گردد اکنون ثبت نام کنید
این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

سلام ، بسیاری از جهان ها

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub دانلود دفترچه یادداشت

این آموزش نشان می دهد که چگونه یک شبکه عصبی کلاسیک می تواند خطاهای کالیبراسیون کیوبیت را اصلاح کند. این Cirq را معرفی می کند ، یک چارچوب پایتون برای ایجاد ، ویرایش و فراخوانی مدارهای Noisy Intermediate Scale Quantum (NISQ) ، و نحوه رابط Cirq با TensorFlow Quantum را نشان می دهد.

برپایی

pip install -q tensorflow==2.3.1

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. مبانی

1.1 Cirq و مدارهای کوانتومی پارامتر شده

قبل از بررسی TensorFlow Quantum (TFQ) ، بیایید برخی از اصول Cirq را بررسی کنیم . Cirq یک کتابخانه پایتون برای محاسبات کوانتومی از Google است. شما از آن برای تعریف مدارها ، از جمله گیت های استاتیک و پارامتر شده استفاده می کنید.

Cirq از نمادهای SymPy برای نمایش پارامترهای آزاد استفاده می کند.

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

کد زیر با استفاده از پارامترهای شما مدار دو کیوبیتی ایجاد می کند:

# 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 پارامترهای رایگان را در مدار با اعداد مشخص 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 اندازه گیری ها را با استفاده از ترکیب عملگرهای Pauli $ \ 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 Quantum (TFQ) tfq.convert_to_tensor ارائه می tfq.convert_to_tensor ، تابعی که اشیا tfq.convert_to_tensor Cirq را به tfq.convert_to_tensor تبدیل می کند. با این کار می توانید اشیا C 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'>

این اشیا tf.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 است که یک 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.4557516 ]
 [ 0.19779062]
 [-0.52832156]
 [ 0.888587  ]
 [-0.20134428]]

عملیات مشابه در 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.45575225],
       [ 0.19779024],
       [-0.5283203 ],
       [ 0.8885881 ],
       [-0.2013425 ]], dtype=float32)>

2. بهینه سازی کلاسیک کوانتومی ترکیبی

حالا که اصول را مشاهده کردید ، بیایید از TensorFlow Quantum برای ساخت یک شبکه عصبی کوانتومی-کلاسیک ترکیبی استفاده کنیم . شما یک شبکه عصبی کلاسیک را برای کنترل یک کیوبیت واحد آموزش خواهید داد. برای غلبه بر خطای کالیبراسیون سیستماتیک شبیه سازی شده ، کنترل برای به درستی آماده سازی کیوبیت در حالت 0 یا 1 بهینه خواهد شد. این شکل معماری را نشان می دهد:

حتی بدون شبکه عصبی این یک مشکل ساده برای حل است ، اما موضوع شبیه به مشکلات واقعی کنترل کوانتومی است که ممکن است با استفاده از TFQ حل کنید. این نمونه ای از محاسبات کلاسیک کوانتومی با استفاده از tfq.layers.ControlledPQC (Parametrized Quantum Circuit) را در داخل مدل tf.keras.Model .

برای اجرای این آموزش ، این معماری به 3 قسمت تقسیم شده است:

  • مدار ورودی یا مدار دیتاپوینت : سه گیت اول $ 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.54904324, 0.12798752, 0.48068655]], dtype=float32)

2.3 کنترل کننده را به مدار وصل کنید

از tfq برای اتصال کنترل کننده به مدار کنترل شده ، به عنوان یک keras.Model واحد keras.Model . keras.Model .

برای اطلاعات بیشتر در مورد این سبک از تعریف مدل ، به راهنمای API عملکردی Keras مراجعه کنید.

ابتدا ورودی های مدل را تعریف کنید:

# 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 بسته بندی کنید. 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.11818343],
       [ 0.06576699]], 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: [-1.1870269  2.520571   1.9310579]
Which gives an actual expectation of: 0.9146309494972229

For a desired output (expectation) of [-1.] with noisy preparation, the controller
network found the following values for theta: [2.4382339  0.06558019 1.4365435 ]
Which gives an actual expectation of: -0.9835573434829712

ارزش عملکرد از دست دادن در حین آموزش ، ایده ای تقریبی از میزان یادگیری مدل ارائه می دهد. هرچه افت کمتری داشته باشد ، مقادیر انتظار در سلول فوق به desired_values . اگر چندان به مقادیر پارامتر توجه ندارید ، همیشه می توانید خروجی های بالا را با استفاده از tfq :

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

3 آموزش آماده سازی موقعیت های ویژه اپراتورهای مختلف

انتخاب $ \ pm \ hat {Z} $ eigenstate مربوط به 1 و 0 دلخواه بود. به همین آسانی می خواستید 1 مطابقت با eigenstate $ + \ hat {Z} $ و 0 مربوط به eigenstate $ - \ 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 واحد 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 آموزش

اکنون که ورودی و خروجی جدید خود را دارید می توانید با استفاده از keras یک بار دیگر آموزش دهید.

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 970us/step - loss: 2.5384
Epoch 2/30
1/1 [==============================] - 0s 728us/step - loss: 1.6466
Epoch 3/30
1/1 [==============================] - 0s 710us/step - loss: 1.1451
Epoch 4/30
1/1 [==============================] - 0s 672us/step - loss: 0.8246
Epoch 5/30
1/1 [==============================] - 0s 677us/step - loss: 0.5611
Epoch 6/30
1/1 [==============================] - 0s 619us/step - loss: 0.3559
Epoch 7/30
1/1 [==============================] - 0s 571us/step - loss: 0.2129
Epoch 8/30
1/1 [==============================] - 0s 600us/step - loss: 0.1164
Epoch 9/30
1/1 [==============================] - 0s 601us/step - loss: 0.0545
Epoch 10/30
1/1 [==============================] - 0s 614us/step - loss: 0.0224
Epoch 11/30
1/1 [==============================] - 0s 624us/step - loss: 0.0103
Epoch 12/30
1/1 [==============================] - 0s 595us/step - loss: 0.0079
Epoch 13/30
1/1 [==============================] - 0s 572us/step - loss: 0.0107
Epoch 14/30
1/1 [==============================] - 0s 593us/step - loss: 0.0192
Epoch 15/30
1/1 [==============================] - 0s 588us/step - loss: 0.0345
Epoch 16/30
1/1 [==============================] - 0s 618us/step - loss: 0.0544
Epoch 17/30
1/1 [==============================] - 0s 638us/step - loss: 0.0730
Epoch 18/30
1/1 [==============================] - 0s 622us/step - loss: 0.0843
Epoch 19/30
1/1 [==============================] - 0s 602us/step - loss: 0.0820
Epoch 20/30
1/1 [==============================] - 0s 600us/step - loss: 0.0663
Epoch 21/30
1/1 [==============================] - 0s 610us/step - loss: 0.0458
Epoch 22/30
1/1 [==============================] - 0s 621us/step - loss: 0.0281
Epoch 23/30
1/1 [==============================] - 0s 610us/step - loss: 0.0153
Epoch 24/30
1/1 [==============================] - 0s 622us/step - loss: 0.0074
Epoch 25/30
1/1 [==============================] - 0s 628us/step - loss: 0.0031
Epoch 26/30
1/1 [==============================] - 0s 656us/step - loss: 0.0011
Epoch 27/30
1/1 [==============================] - 0s 663us/step - loss: 2.9912e-04
Epoch 28/30
1/1 [==============================] - 0s 627us/step - loss: 6.1668e-05
Epoch 29/30
1/1 [==============================] - 0s 588us/step - loss: 1.3870e-05
Epoch 30/30
1/1 [==============================] - 0s 663us/step - loss: 1.4859e-05
plt.plot(history.history['loss'])
plt.title("Learning to Control a Qubit")
plt.xlabel("Iterations")
plt.ylabel("Error in Control")
plt.show()

png

عملکرد ضرر به صفر رسیده است.

controller به صورت یک مدل مستقل در دسترس است. با کنترل کننده تماس بگیرید و پاسخ آن را به هر سیگنال فرمان بررسی کنید. برای مقایسه صحیح این خروجی ها با محتویات random_rotations های random_rotations زیادی random_rotations .

controller.predict(np.array([0,1]))
array([[-2.4193525 , -0.11989626, -0.5875844 ],
       [-2.5004668 , -1.613323  , -3.0799127 ]], dtype=float32)