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

داده های کوانتومی

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

با استفاده از مقایسه های انجام شده در آموزش MNIST ، این آموزش کار اخیر هوانگ و همکاران را بررسی می کند. که نشان می دهد مجموعه داده های مختلف چگونه بر مقایسه عملکرد تأثیر می گذارند. در این کار ، نویسندگان سعی در درک چگونگی و زمان مدلهای یادگیری ماشین کلاسیک و همچنین (یا بهتر از) مدلهای کوانتومی دارند. این کار همچنین یک جدایی عملکرد تجربی بین مدل یادگیری ماشین کلاسیک و کوانتوم را از طریق یک مجموعه داده با دقت به نمایش می گذارد. شما:

  1. مجموعه داده Fashion-MNIST با ابعاد کاهش یافته را تهیه کنید.
  2. از مدارهای کوانتومی برای برچسب گذاری مجدد مجموعه داده و محاسبه ویژگی های هسته کوانتومی پیش بینی شده (PQK) استفاده کنید.
  3. شبکه عصبی کلاسیک را روی مجموعه داده های دارای برچسب مجدد آموزش دهید و عملکرد را با مدلی که به ویژگی های PQK دسترسی دارد مقایسه کنید.

برپایی

pip -q install tensorflow==2.3.1 tensorflow-quantum
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
import cirq
import sympy
import numpy as np
import tensorflow as tf
import tensorflow_quantum as tfq

# visualization tools
%matplotlib inline
import matplotlib.pyplot as plt
from cirq.contrib.svg import SVGCircuit
np.random.seed(1234)

1. تهیه اطلاعات

در ابتدا با تهیه مجموعه داده fashion-MNIST برای راه اندازی در رایانه کوانتومی شروع خواهید کرد.

1.1 بارگیری مد-MNIST

اولین قدم به دست آوردن مجموعه داده های سنتی fashion-mnist است. این کار را می توان با استفاده از ماژول tf.keras.datasets انجام داد.

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()

# Rescale the images from [0,255] to the [0.0,1.0] range.
x_train, x_test = x_train/255.0, x_test/255.0

print("Number of original training examples:", len(x_train))
print("Number of original test examples:", len(x_test))
Number of original training examples: 60000
Number of original test examples: 10000

مجموعه داده را فیلتر کنید تا فقط تی شرت ها / تاپ ها و لباس ها را حفظ کنید ، سایر کلاس ها را حذف کنید. در همان زمان ، برچسب ، y به boolean تبدیل کنید: درست برای 0 و False برای 3.

def filter_03(x, y):
    keep = (y == 0) | (y == 3)
    x, y = x[keep], y[keep]
    y = y == 0
    return x,y
x_train, y_train = filter_03(x_train, y_train)
x_test, y_test = filter_03(x_test, y_test)

print("Number of filtered training examples:", len(x_train))
print("Number of filtered test examples:", len(x_test))
Number of filtered training examples: 12000
Number of filtered test examples: 2000
print(y_train[0])

plt.imshow(x_train[0, :, :])
plt.colorbar()
True
<matplotlib.colorbar.Colorbar at 0x7f6db42c3460>

png

1.2 کوچک کردن تصاویر

دقیقاً مانند مثال MNIST ، برای قرار گرفتن در محدوده رایانه های کوانتومی فعلی ، باید این تصاویر را کوچک کنید. اما این بار برای کاهش ابعاد به جای عملکردtf.image.resize ، از تغییر شکل PCA استفاده خواهید کرد.

def truncate_x(x_train, x_test, n_components=10):
  """Perform PCA on image dataset keeping the top `n_components` components."""
  n_points_train = tf.gather(tf.shape(x_train), 0)
  n_points_test = tf.gather(tf.shape(x_test), 0)

  # Flatten to 1D
  x_train = tf.reshape(x_train, [n_points_train, -1])
  x_test = tf.reshape(x_test, [n_points_test, -1])

  # Normalize.
  feature_mean = tf.reduce_mean(x_train, axis=0)
  x_train_normalized = x_train - feature_mean
  x_test_normalized = x_test - feature_mean

  # Truncate.
  e_values, e_vectors = tf.linalg.eigh(
      tf.einsum('ji,jk->ik', x_train_normalized, x_train_normalized))
  return tf.einsum('ij,jk->ik', x_train_normalized, e_vectors[:,-n_components:]), \
    tf.einsum('ij,jk->ik', x_test_normalized, e_vectors[:, -n_components:])
DATASET_DIM = 10
x_train, x_test = truncate_x(x_train, x_test, n_components=DATASET_DIM)
print(f'New datapoint dimension:', len(x_train[0]))
New datapoint dimension: 10

آخرین مرحله این است که اندازه مجموعه داده را فقط به 1000 پایگاه داده آموزش و 200 پایگاه داده آزمایش کاهش دهید.

N_TRAIN = 1000
N_TEST = 200
x_train, x_test = x_train[:N_TRAIN], x_test[:N_TEST]
y_train, y_test = y_train[:N_TRAIN], y_test[:N_TEST]
print("New number of training examples:", len(x_train))
print("New number of test examples:", len(x_test))
New number of training examples: 1000
New number of test examples: 200

2. برچسب گذاری مجدد و محاسبه ویژگی های PQK

اکنون می توانید یک مجموعه داده کوانتومی "سبک" را با ترکیب اجزای کوانتوم و برچسب گذاری مجدد مجموعه داده های کوتاه شده MNIST که در بالا ایجاد کرده اید ، آماده کنید. برای اینکه بیشترین تفکیک را بین روش های کوانتومی و کلاسیک داشته باشید ، ابتدا ویژگی های PQK را آماده کرده و سپس بر اساس مقادیر آنها ، برچسب گذاری مجدد می کنید.

2.1 رمزگذاری کوانتومی و ویژگی های PQK

شما مجموعه ای جدید از ویژگی ها را بر اساس x_train ، y_train ، x_test و y_test که به صورت 1-RDM در تمام کیوبیت ها تعریف شده است:

$ V (x _ {\ text {train}} / n _ {\ text {trotter}}) ^ {n _ {\ text {trotter}}} U _ {\ text {1qb}} | 0 \ رانگل $

جایی که $ U_ \ text {1qb} $ دیواری از چرخش های کیوبیت واحد و $ V (\ hat {\ theta}) = e ^ {- i \ sum_i \ hat {\ theta_i} (X_i X_ {i + 1} +) است Y_i Y_ {i + 1} + Z_i Z_ {i + 1})} $

ابتدا می توانید دیواره چرخش های کیوبیت واحد را ایجاد کنید:

def single_qubit_wall(qubits, rotations):
  """Prepare a single qubit X,Y,Z rotation wall on `qubits`."""
  wall_circuit = cirq.Circuit()
  for i, qubit in enumerate(qubits):
    for j, gate in enumerate([cirq.X, cirq.Y, cirq.Z]):
      wall_circuit.append(gate(qubit) ** rotations[i][j])

  return wall_circuit

با مشاهده مدار می توانید سریعاً این کار را تأیید کنید:

SVGCircuit(single_qubit_wall(
    cirq.GridQubit.rect(1,4), np.random.uniform(size=(4, 3))))

svg

در مرحله بعدی می توانید $ V (\ hat {\ theta}) $ را با کمک tfq.util.exponential که می تواند هر cirq.PauliSum رفت و آمد cirq.PauliSum :

def v_theta(qubits):
  """Prepares a circuit that generates V(\theta)."""
  ref_paulis = [
      cirq.X(q0) * cirq.X(q1) + \
      cirq.Y(q0) * cirq.Y(q1) + \
      cirq.Z(q0) * cirq.Z(q1) for q0, q1 in zip(qubits, qubits[1:])
  ]
  exp_symbols = list(sympy.symbols('ref_0:'+str(len(ref_paulis))))
  return tfq.util.exponential(ref_paulis, exp_symbols), exp_symbols

بررسی این مدار ممکن است با مشاهده کمی سخت تر باشد ، اما شما هنوز هم می توانید یک مورد دو کیوبیتی را بررسی کنید تا ببینید چه اتفاقی می افتد:

test_circuit, test_symbols = v_theta(cirq.GridQubit.rect(1, 2))
print(f'Symbols found in circuit:{test_symbols}')
SVGCircuit(test_circuit)
Symbols found in circuit:[ref_0]

svg

اکنون تمام بلوک های ساختمانی مورد نیاز برای تنظیم مدارهای رمزگذاری کامل خود را دارید:

def prepare_pqk_circuits(qubits, classical_source, n_trotter=10):
  """Prepare the pqk feature circuits around a dataset."""
  n_qubits = len(qubits)
  n_points = len(classical_source)

  # Prepare random single qubit rotation wall.
  random_rots = np.random.uniform(-2, 2, size=(n_qubits, 3))
  initial_U = single_qubit_wall(qubits, random_rots)

  # Prepare parametrized V
  V_circuit, symbols = v_theta(qubits)
  exp_circuit = cirq.Circuit(V_circuit for t in range(n_trotter))

  # Convert to `tf.Tensor`
  initial_U_tensor = tfq.convert_to_tensor([initial_U])
  initial_U_splat = tf.tile(initial_U_tensor, [n_points])

  full_circuits = tfq.layers.AddCircuit()(
      initial_U_splat, append=exp_circuit)
  # Replace placeholders in circuits with values from `classical_source`.
  return tfq.resolve_parameters(
      full_circuits, tf.convert_to_tensor([str(x) for x in symbols]),
      tf.convert_to_tensor(classical_source*(n_qubits/3)/n_trotter))

چند کیوبیت را انتخاب کنید و مدارهای رمزگذاری داده را آماده کنید:

qubits = cirq.GridQubit.rect(1, DATASET_DIM + 1)
q_x_train_circuits = prepare_pqk_circuits(qubits, x_train)
q_x_test_circuits = prepare_pqk_circuits(qubits, x_test)

بعد ، ویژگی های PQK را بر اساس 1-RDM مدارهای مجموعه داده فوق محاسبه کرده و نتایج را در rdm ، rdm . tf.Tensor با شکل [n_points, n_qubits, 3] . ورودی های موجود در rdm[i][j][k] = $ \ langle \ psi_i | OP ^ k_j | \ psi_i \ rangle $ جایی که i بیش از نقاط داده ، j index بیش از qubits و k index بیش از $ \ lbrace \ hat {X} ، \ hat {Y} ، \ hat {Z} \ rbrace $ نمایه می کند.

def get_pqk_features(qubits, data_batch):
  """Get PQK features based on above construction."""
  ops = [[cirq.X(q), cirq.Y(q), cirq.Z(q)] for q in qubits]
  ops_tensor = tf.expand_dims(tf.reshape(tfq.convert_to_tensor(ops), -1), 0)
  batch_dim = tf.gather(tf.shape(data_batch), 0)
  ops_splat = tf.tile(ops_tensor, [batch_dim, 1])
  exp_vals = tfq.layers.Expectation()(data_batch, operators=ops_splat)
  rdm = tf.reshape(exp_vals, [batch_dim, len(qubits), -1])
  return rdm
x_train_pqk = get_pqk_features(qubits, q_x_train_circuits)
x_test_pqk = get_pqk_features(qubits, q_x_test_circuits)
print('New PQK training dataset has shape:', x_train_pqk.shape)
print('New PQK testing dataset has shape:', x_test_pqk.shape)
New PQK training dataset has shape: (1000, 11, 3)
New PQK testing dataset has shape: (200, 11, 3)

2.2 برچسب گذاری مجدد بر اساس ویژگی های PQK

اکنون که این ویژگی های تولید شده کوانتومی را در x_train_pqk و x_test_pqk ، وقت آن است که برچسب داده را دوباره برچسب گذاری کنید. برای دستیابی به حداکثر تفکیک بین عملکرد کوانتومی و کلاسیک ، می توانید مجموعه داده را بر اساس اطلاعات طیف موجود در x_train_pqk و x_test_pqk دوباره برچسب x_test_pqk .

def compute_kernel_matrix(vecs, gamma):
  """Computes d[i][j] = e^ -gamma * (vecs[i] - vecs[j]) ** 2 """
  scaled_gamma = gamma / (
      tf.cast(tf.gather(tf.shape(vecs), 1), tf.float32) * tf.math.reduce_std(vecs))
  return scaled_gamma * tf.einsum('ijk->ij',(vecs[:,None,:] - vecs) ** 2)

def get_spectrum(datapoints, gamma=1.0):
  """Compute the eigenvalues and eigenvectors of the kernel of datapoints."""
  KC_qs = compute_kernel_matrix(datapoints, gamma)
  S, V = tf.linalg.eigh(KC_qs)
  S = tf.math.abs(S)
  return S, V
S_pqk, V_pqk = get_spectrum(
    tf.reshape(tf.concat([x_train_pqk, x_test_pqk], 0), [-1, len(qubits) * 3]))

S_original, V_original = get_spectrum(
    tf.cast(tf.concat([x_train, x_test], 0), tf.float32), gamma=0.005)

print('Eigenvectors of pqk kernel matrix:', V_pqk)
print('Eigenvectors of original kernel matrix:', V_original)
Eigenvectors of pqk kernel matrix: tf.Tensor(
[[-2.09569391e-02  1.05973557e-02  2.16634180e-02 ...  2.80352887e-02
   1.55521873e-02  2.82677952e-02]
 [-2.29303762e-02  4.66355234e-02  7.91163836e-03 ... -6.14174758e-04
  -7.07804322e-01  2.85902526e-02]
 [-1.77853629e-02 -3.00758495e-03 -2.55225878e-02 ... -2.40783971e-02
   2.11018627e-03  2.69009806e-02]
 ...
 [ 6.05797209e-02  1.32483775e-02  2.69536003e-02 ... -1.38843581e-02
   3.05043962e-02  3.85345481e-02]
 [ 6.33309558e-02 -3.04112374e-03  9.77444276e-03 ...  7.48321265e-02
   3.42793856e-03  3.67484428e-02]
 [ 5.86028099e-02  5.84433973e-03  2.64811981e-03 ...  2.82612257e-02
  -3.80136147e-02  3.29943895e-02]], shape=(1200, 1200), dtype=float32)
Eigenvectors of original kernel matrix: tf.Tensor(
[[ 0.03835681  0.0283473  -0.01169789 ...  0.02343717  0.0211248
   0.03206972]
 [-0.04018159  0.00888097 -0.01388255 ...  0.00582427  0.717551
   0.02881948]
 [-0.0166719   0.01350376 -0.03663862 ...  0.02467175 -0.00415936
   0.02195409]
 ...
 [-0.03015648 -0.01671632 -0.01603392 ...  0.00100583 -0.00261221
   0.02365689]
 [ 0.0039777  -0.04998879 -0.00528336 ...  0.01560401 -0.04330755
   0.02782002]
 [-0.01665728 -0.00818616 -0.0432341  ...  0.00088256  0.00927396
   0.01875088]], shape=(1200, 1200), dtype=float32)

اکنون هر آنچه برای برچسب گذاری مجدد مجموعه داده لازم دارید را دارید! اکنون می توانید با نمودار جریان مشورت کنید تا بهتر درک کنید که چگونه هنگام برچسب گذاری مجدد مجموعه داده ، تفکیک عملکرد را به حداکثر برسانید:

به منظور به حداکثر رساندن تفکیک بین مدلهای کوانتومی و کلاسیک ، سعی خواهید کرد تفاوت هندسی بین مجموعه داده اصلی و ماتریسهای هسته ویژگیهای PQK $ g (K_1 || K_2) = \ sqrt {|| \ sqrt {K_2} K_1 ^ {- 1} \ sqrt {K_2} || _ \ infty} $ با استفاده از S_pqk, V_pqk و S_original, V_original . مقدار زیادی $ g $ تضمین می کند که در ابتدا در نمودار جریان به سمت راست به سمت یک مزیت پیش بینی در حالت کوانتومی حرکت می کنید.

def get_stilted_dataset(S, V, S_2, V_2, lambdav=1.1):
  """Prepare new labels that maximize geometric distance between kernels."""
  S_diag = tf.linalg.diag(S ** 0.5)
  S_2_diag = tf.linalg.diag(S_2 / (S_2 + lambdav) ** 2)
  scaling = S_diag @ tf.transpose(V) @ \
            V_2 @ S_2_diag @ tf.transpose(V_2) @ \
            V @ S_diag

  # Generate new lables using the largest eigenvector.
  _, vecs = tf.linalg.eig(scaling)
  new_labels = tf.math.real(
      tf.einsum('ij,j->i', tf.cast(V @ S_diag, tf.complex64), vecs[-1])).numpy()
  # Create new labels and add some small amount of noise.
  final_y = new_labels > np.median(new_labels)
  noisy_y = (final_y ^ (np.random.uniform(size=final_y.shape) > 0.95))
  return noisy_y
y_relabel = get_stilted_dataset(S_pqk, V_pqk, S_original, V_original)
y_train_new, y_test_new = y_relabel[:N_TRAIN], y_relabel[N_TRAIN:]

3. مقایسه مدل ها

اکنون که مجموعه داده خود را آماده کردید ، زمان مقایسه عملکرد مدل فرا رسیده است. هنگامی که به ویژگی های PQK موجود در x_train_pqk دسترسی پیدا کردید ، دو شبکه عصبی پیشخوان کوچک ایجاد خواهید کرد و عملکرد را مقایسه می کنید.

3.1 مدل پیشرفته PQK ایجاد کنید

با استفاده از ویژگی های استاندارد کتابخانه tf.keras اکنون می توانید مدلی را در پایگاه داده x_train_pqk و y_train_new ایجاد و آموزش دهید:

def create_pqk_model():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Dense(32, activation='sigmoid', input_shape=[len(qubits) * 3,]))
    model.add(tf.keras.layers.Dense(16, activation='sigmoid'))
    model.add(tf.keras.layers.Dense(1))
    return model

pqk_model = create_pqk_model()
pqk_model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              optimizer=tf.keras.optimizers.Adam(learning_rate=0.003),
              metrics=['accuracy'])

pqk_model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 32)                1088      
_________________________________________________________________
dense_1 (Dense)              (None, 16)                528       
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 17        
=================================================================
Total params: 1,633
Trainable params: 1,633
Non-trainable params: 0
_________________________________________________________________
pqk_history = pqk_model.fit(tf.reshape(x_train_pqk, [N_TRAIN, -1]),
          y_train_new,
          batch_size=32,
          epochs=1000,
          verbose=0,
          validation_data=(tf.reshape(x_test_pqk, [N_TEST, -1]), y_test_new))

3.2 یک مدل کلاسیک ایجاد کنید

مشابه کد بالا ، اکنون می توانید یک مدل کلاسیک نیز ایجاد کنید که به ویژگی های PQK در مجموعه داده های سخت شما دسترسی ندارد. این مدل را می توان با استفاده از x_train و y_label_new آموزش y_label_new .

def create_fair_classical_model():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Dense(32, activation='sigmoid', input_shape=[DATASET_DIM,]))
    model.add(tf.keras.layers.Dense(16, activation='sigmoid'))
    model.add(tf.keras.layers.Dense(1))
    return model

model = create_fair_classical_model()
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              optimizer=tf.keras.optimizers.Adam(learning_rate=0.03),
              metrics=['accuracy'])

model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_3 (Dense)              (None, 32)                352       
_________________________________________________________________
dense_4 (Dense)              (None, 16)                528       
_________________________________________________________________
dense_5 (Dense)              (None, 1)                 17        
=================================================================
Total params: 897
Trainable params: 897
Non-trainable params: 0
_________________________________________________________________
classical_history = model.fit(x_train,
          y_train_new,
          batch_size=32,
          epochs=1000,
          verbose=0,
          validation_data=(x_test, y_test_new))

3.3 مقایسه عملکرد

اکنون که این دو مدل را آموزش داده اید می توانید به سرعت شکاف های عملکردی را در داده های اعتبار سنجی بین این دو ترسیم کنید. به طور معمول هر دو مدل به 0.9 اطمینان در داده های آموزش می رسند. با این حال ، در مورد داده های اعتبار سنجی مشخص می شود که فقط اطلاعات موجود در ویژگی های PQK برای تعمیم مدل به خوبی در موارد غیبی کافی است.

plt.figure(figsize=(10,5))
plt.plot(classical_history.history['accuracy'], label='accuracy_classical')
plt.plot(classical_history.history['val_accuracy'], label='val_accuracy_classical')
plt.plot(pqk_history.history['accuracy'], label='accuracy_quantum')
plt.plot(pqk_history.history['val_accuracy'], label='val_accuracy_quantum')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
<matplotlib.legend.Legend at 0x7f6d846ecee0>

png

4. نتیجه گیری مهم

چندین نتیجه مهم وجود دارد که می توانید از این آزمایش و آزمایش MNIST بگیرید:

  1. بسیار بعید است که مدل های کوانتومی امروز عملکرد مدل کلاسیک را بر روی داده های کلاسیک شکست دهند. به خصوص در مجموعه داده های کلاسیک امروزی که می توانند بیش از یک میلیون پایگاه داده داشته باشند.

  2. فقط به این دلیل که داده ها ممکن است از مدار کوانتومی شبیه سازی کلاسیک سخت حاصل شود ، لزوماً یادگیری داده ها را برای یک مدل کلاسیک سخت نمی کند.

  3. مجموعه داده هایی (در نهایت ماهیت کوانتومی) که بدون در نظر گرفتن معماری مدل یا الگوریتم های آموزشی مورد استفاده ، فراگیری آن برای مدل های کوانتومی آسان و یادگیری آن برای مدل های کلاسیک دشوار است.