Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Merhaba birçok dünya

TensorFlow.org'da görüntüleyin Google Colab'de çalıştırın Kaynağı GitHub'da görüntüleyin Defteri indirin

Bu eğitim, klasik bir sinir ağının kübit kalibrasyon hatalarını düzeltmeyi nasıl öğrenebileceğini gösterir. O tanıtır Cirq oluşturmak, düzenlemek için bir Python çerçeve ve gürültülü Orta Ölçekli Quantum çağırmak (NISQ) devreler ve TensorFlow Quantum ile nasıl Cirq arayüzleri göstermektedir.

Kurmak

pip install -q tensorflow==2.1.0

TensorFlow Quantum'u yükleyin:

pip install -q tensorflow-quantum
ERROR: After October 2020 you may experience errors when installing or updating packages. This is because pip will change the way that it resolves dependency conflicts.

We recommend you use --use-feature=2020-resolver to test your packages with the new resolver before it becomes the default.

tensorflow-metadata 0.23.0 requires absl-py<0.9,>=0.7, but you'll have absl-py 0.9.0 which is incompatible.
google-api-core 1.22.1 requires protobuf>=3.12.0, but you'll have protobuf 3.8.0 which is incompatible.

Şimdi TensorFlow ve modül bağımlılıklarını içe aktarın:

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. Temel Bilgiler

1.1 Cirq ve parametreli kuantum devreleri

TensorFlow Quantum (TFQ) keşfetmeden önce, bazı Bakalım Cirq temelleri. Cirq, Google'ın kuantum hesaplaması için bir Python kitaplığıdır. Statik ve parametreli kapılar dahil olmak üzere devreleri tanımlamak için kullanırsınız.

Cirq, ücretsiz parametreleri temsil etmek için SymPy sembollerini kullanır.

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

Aşağıdaki kod, parametrelerinizi kullanarak iki kübitlik bir devre oluşturur:

# 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

Devreleri değerlendirmek için cirq.Simulator arayüzünü kullanabilirsiniz. Bir cirq.ParamResolver nesnesini ileterek bir devredeki serbest parametreleri belirli sayılarla değiştirirsiniz. Aşağıdaki kod, parametreli devrenizin ham durum vektör çıkışını hesaplar:

# 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
output_state_vector
array([ 0.9387913 +0.j        , -0.23971277+0.j        ,

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

Durum vektörlerine simülasyon dışında doğrudan erişilemez (yukarıdaki çıktıdaki karmaşık sayılara dikkat edin). Fiziksel olarak gerçekçi olmak için, bir durum vektörünü klasik bilgisayarların anlayabileceği gerçek bir sayıya dönüştüren bir ölçüm belirlemelisiniz. Cirq, Pauli operatörleri $ \ hat {X} $, $ \ hat {Y} $ ve $ \ hat {Z} $ kombinasyonlarını kullanarak ölçümleri belirtir. Örnek olarak, aşağıdaki kod az önce simüle ettiğiniz durum vektörü üzerinde $ \ hat {Z} _0 $ ve $ \ frac {1} {2} \ hat {Z} _0 + \ hat {X} _1 $ değerlerini ölçer:

z0 = cirq.Z(q0)

qubit_map={q0: 0, q1: 1}

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

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

1.2 Tensörler olarak kuantum devreleri

TensorFlow Quantum (TFQ), Cirq nesnelerini tensörlere dönüştüren bir işlev olan tfq.convert_to_tensor işlevini sağlar. Bu, Cirq nesnelerini kuantum katmanlarımıza ve kuantum operasyonlarımıza göndermenizi sağlar. İşlev, Cirq Circuits ve Cirq Paulis listelerinde veya dizilerinde çağrılabilir:

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

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

Bu, Cirq nesnelerini, gerektiğinde tfq işlemlerinin kodunu çözen tf.string tensörleri olarak kodlar.

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

1.3 Dozaj devresi simülasyonu

TFQ, beklenti değerlerini, örnekleri ve durum vektörlerini hesaplamak için yöntemler sağlar. Şimdilik beklenti değerlerine odaklanalım.

Beklenti değerlerini hesaplamak için en üst düzey arayüz, tfq.layers.Expectation olan tf.keras.Layer . En basit şekliyle, bu katman birçok cirq.ParamResolvers üzerinde parametreleştirilmiş bir devreyi simüle cirq.ParamResolvers ; ancak TFQ, TensorFlow semantiğini takip eden toplu işlemlere izin verir ve devreler verimli C ++ kodu kullanılarak simüle edilir.

a ve b parametrelerimizin yerini alacak bir grup değer oluşturun:

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

Cirq'deki parametre değerleri üzerinden gruplama devresi yürütme bir döngü gerektirir:

cirq_results = []
cirq_simulator = cirq.Simulator()

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

print('cirq batch results: \n {}'.format(np.array(cirq_results)))
cirq batch results: 
 [[-0.83266681]
 [ 0.99945712]
 [-0.93167216]
 [-0.0446538 ]
 [ 0.81493288]]

Aynı işlem TFQ'da basitleştirilmiştir:

tfq.layers.Expectation()(circuit,
                         symbol_names=[a, b],
                         symbol_values=batch_vals,
                         operators=z0)
<tf.Tensor: shape=(5, 1), dtype=float32, numpy=
array([[-0.83266693],
       [ 0.9994572 ],
       [-0.9316722 ],
       [-0.04465387],
       [ 0.81493276]], dtype=float32)>

2. Hibrit kuantum-klasik optimizasyon

Artık temelleri gördüğünüze göre, hibrit bir kuantum-klasik sinir ağı oluşturmak için TensorFlow Quantum'u kullanalım. Tek bir kübiti kontrol etmek için klasik bir sinir ağı eğiteceksiniz. Kontrol simüle edilmiş bir sistematik kalibrasyon hatasının üstesinden gelerek 0 veya 1 durumunda kübiti doğru şekilde hazırlamak için optimize edilecektir. Bu şekil mimariyi göstermektedir:

Bir sinir ağı olmasa bile, bu çözülmesi kolay bir problemdir, ancak tema TFQ kullanarak çözebileceğiniz gerçek kuantum kontrol problemlerine benzer. Bir tfq.layers.ControlledPQC içindeki tfq.layers.ControlledPQC (Parametreli Kuantum Devresi) katmanını kullanarak kuantum klasik hesaplamanın uçtan uca bir örneğini tf.keras.Model .

Bu öğreticinin uygulanması için, bu mimari 3 bölüme ayrılmıştır:

  • Giriş devresi veya veri noktası devresi : İlk üç $ R $ geçidi.
  • Kontrollü devre : Diğer üç $ R $ geçidi.
  • Kontrolör : Kontrol edilen devrenin parametrelerini ayarlayan klasik sinir ağı.

2.1 Kontrollü devre tanımı

Yukarıdaki şekilde gösterildiği gibi öğrenilebilir bir tek bit dönüşü tanımlayın. Bu, kontrollü devremize karşılık gelecektir.

# 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 Kontrolör

Şimdi denetleyici ağını tanımlayın:

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

Bir grup komut verildiğinde, kontrolör, kontrol edilen devre için bir grup kontrol sinyali verir.

Denetleyici rastgele başlatılır, bu nedenle bu çıktılar henüz yararlı değildir.

controller(tf.constant([[0.0],[1.0]])).numpy()
array([[0.        , 0.        , 0.        ],
       [0.54516   , 0.22012806, 0.09697416]], dtype=float32)

2.3 Kontrolörü devreye bağlayın

Denetleyiciyi kontrol edilen devreye tek bir keras.Model olarak bağlamak için tfq kullanın.

Bu model tanımlama stili hakkında daha fazla bilgi için Keras Functional API kılavuzuna bakın.

Önce modelin girdilerini tanımlayın:

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

Ardından, hesaplamayı tanımlamak için işlemleri bu girişlere uygulayın.

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

Şimdi bu hesaplamayı tf.keras.Model olarak tf.keras.Model :

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

Ağ mimarisi, aşağıdaki modelin grafiği ile belirtilmiştir. Doğruluğu doğrulamak için bu model planını mimari diyagramla karşılaştırın.

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

png

Bu model iki giriş alır: Denetleyici için komutlar ve denetleyicinin çıkışını düzeltmeye çalıştığı giriş devresi.

2.4 Veri kümesi

Model, her komut için $ \ hat {Z} $ 'ın doğru ölçüm değerini vermeyi dener. Komutlar ve doğru değerler aşağıda tanımlanmıştır.

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

Bu, bu görev için tüm eğitim veri kümesi değildir. Veri kümesindeki her veri noktası ayrıca bir giriş devresine ihtiyaç duyar.

2.4 Giriş devresi tanımı

Aşağıdaki giriş devresi, modelin düzeltmeyi öğreneceği rastgele yanlış kalibrasyonu tanımlar.

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

Devrenin, her veri noktası için bir tane olmak üzere iki kopyası vardır.

datapoint_circuits.shape
TensorShape([2])

2.5 Eğitim

Tanımlanan girdiler ile tfq modelini test edebilirsiniz.

model([datapoint_circuits, commands]).numpy()
array([[ 0.00428568],
       [-0.13666134]], dtype=float32)

Şimdi bu değerleri expected_outputs çıktılara göre ayarlamak için standart bir eğitim süreci çalıştırın.

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

Bu arsadan, sinir ağının sistematik yanlış kalibrasyonun üstesinden gelmeyi öğrendiğini görebilirsiniz.

2.6 Çıkışları doğrulayın

Şimdi, kübit kalibrasyon hatalarını düzeltmek için eğitimli modeli kullanın. Cirq ile:

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
    expectation = z0.expectation_from_wavefunction(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: {expectation}\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: [ 0.6296288  1.1365356 -1.5962224]
Which gives an actual expectation of: 0.9621249437332153

For a desired output (expectation) of [-1.] with noisy preparation, the controller
network found the following values for theta: [1.0543389 1.18372   0.7693251]
Which gives an actual expectation of: -0.9606054425239563


Eğitim sırasında kayıp fonksiyonunun değeri, modelin ne kadar iyi öğrendiğine dair kabaca bir fikir verir. Kayıp ne kadar desired_values , yukarıdaki hücredeki beklenti değerleri desired_values değerlere o kadar yakın desired_values . Parametre değerleriyle o kadar ilgilenmiyorsanız, her zaman yukarıdan çıktıları tfq kullanarak kontrol edebilirsiniz:

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

3 Farklı operatörlerin özdurumlarını hazırlamayı öğrenmek

1 ve 0'a karşılık gelen $ \ pm \ hat {Z} $ eigenstates'in seçimi gelişigüzeldi. 1'in $ + \ hat {Z} $ eigenstate'e ve 0'ın $ - \ hat {X} $ eigenstate'e karşılık gelmesini kolaylıkla isteyebilirdiniz. Bunu gerçekleştirmenin bir yolu, aşağıdaki şekilde gösterildiği gibi, her komut için farklı bir ölçüm operatörü belirlemektir:

Bu, tfq.layers.Expectation kullanılmasını gerektirir. Şimdi girdiniz üç nesneyi içerecek şekilde büyüdü: devre, komut ve operatör. Çıktı yine de beklenti değeridir.

3.1 Yeni model tanımı

Bu görevi gerçekleştirmek için modele bir göz atalım:

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

İşte denetleyici ağı:

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

Devre ve denetleyiciyi tek bir keras.Model birleştirin. keras.Model kullanarak 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 Veri kümesi

Şimdi model_circuit için model_circuit her veri noktası için ölçmek istediğiniz operatörleri de dahil 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 Eğitim

Artık yeni giriş ve çıkışlarınıza sahip olduğunuza göre keras'ı kullanarak bir kez daha eğitebilirsiniz.

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)
Train on 2 samples
Epoch 1/30
2/2 [==============================] - 1s 311ms/sample - loss: 1.0348
Epoch 2/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.6338
Epoch 3/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.4026
Epoch 4/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.3120
Epoch 5/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.2221
Epoch 6/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.1057
Epoch 7/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0341
Epoch 8/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0091
Epoch 9/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0020
Epoch 10/30
2/2 [==============================] - 0s 2ms/sample - loss: 6.2119e-04
Epoch 11/30
2/2 [==============================] - 0s 2ms/sample - loss: 0.0038
Epoch 12/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0114
Epoch 13/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0174
Epoch 14/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0158
Epoch 15/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0115
Epoch 16/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0119
Epoch 17/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0179
Epoch 18/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0245
Epoch 19/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0272
Epoch 20/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0247
Epoch 21/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0189
Epoch 22/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0125
Epoch 23/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0076
Epoch 24/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0047
Epoch 25/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0033
Epoch 26/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0025
Epoch 27/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0019
Epoch 28/30
2/2 [==============================] - 0s 1ms/sample - loss: 0.0013
Epoch 29/30
2/2 [==============================] - 0s 1ms/sample - loss: 8.3354e-04
Epoch 30/30
2/2 [==============================] - 0s 1ms/sample - loss: 5.6316e-04

plt.plot(history.history['loss'])
plt.title("Learning to Control a Qubit")
plt.xlabel("Iterations")
plt.ylabel("Error in Control")
plt.show()

png

Kayıp işlevi sıfıra düştü.

controller bağımsız bir model olarak mevcuttur. Denetleyiciyi arayın ve her komut sinyaline verdiği yanıtı kontrol edin. Bu çıktıları random_rotations içerikleriyle doğru bir şekilde karşılaştırmak biraz çalışma random_rotations .

controller.predict(np.array([0,1]))
array([[ 1.9317125 , -0.03036583, -0.46449944],
       [ 2.1391845 ,  1.4074974 , -0.42245713]], dtype=float32)