Korean
언어
English
Bengali
French
Hindi
Italian
Japanese
Korean
Malayalam
Russian
Spanish
Tamil
Turkish
Vietnamese
Shortcuts

참고

이 페이지는 docs/tutorials/04_qgans_for_loading_random_distributions.ipynb 에서 생성되었다.

무작위 분포를 로드하기 위한 qGAN

\(k\) 차원 데이터 샘플을 고려할 때, 우리는 양자 생성적 적대 신경망 (quantum Generative Adversarial Network) (qGAN) 를 골라 데이터의 근본적인 무작위 분포를 학습하고 이를 양자 상태로 직접 로드한다.

\[\big| g_{\theta}\rangle = \sum_{j=0}^{2^n-1} \sqrt{p_{\theta}^{j}}\big| j \rangle\]

여기서 \(p_{\theta}^{j}\) 는 기저 상태의 발생 확률 \(\big| j\rangle\) 을 설명한다.

qGAN 학습의 목표는 학습 데이터 \(X=\left\{x^0, \ldots, x^{k-1} \right\}\) 와 비슷한 확률분포 \(p_{\theta}^{j}\) 를 서술하는 \(\big| g_{\theta}\rangle\) 을 생성하는 것이다. 이 때 , \(j\in \left\{0, \ldots, {2^n-1} \right\}\) 이다.

자세한 사항은 Quantum Generative Adversarial Networks for Learning and Loading Random Distributions Zoufal, Lucchi, Woerner [2019] 을 참조하라.

학습된 qGAN을 사용하는 예제로, 금융 파생상품의 가격 책정 예제가 있다. Option Pricing with qGANs 튜토리얼을 참고하라.

[1]:
import numpy as np

seed = 71
np.random.seed = seed

import matplotlib.pyplot as plt

%matplotlib inline

from qiskit import QuantumRegister, QuantumCircuit, BasicAer
from qiskit.circuit.library import TwoLocal, UniformDistribution

from qiskit.utils import QuantumInstance, algorithm_globals
from qiskit_machine_learning.algorithms import NumPyDiscriminator, QGAN

algorithm_globals.random_seed = seed

훈련 데이터 불러오기

첫째, \(k\) 차원 훈련 데이터 샘플 (여기서 k= 1) 을 로드해야 한다.

다음으로, 데이터 해상도가 설정되고, 즉, 최소/최대 데이터 값들 및 각각의 데이터 차원을 표현하기 위해 사용되는 큐비트들의 수가 설정된다.

[2]:
# Number training data samples
N = 1000

# Load data samples from log-normal distribution with mean=1 and standard deviation=1
mu = 1
sigma = 1
real_data = np.random.lognormal(mean=mu, sigma=sigma, size=N)

# Set the data resolution
# Set upper and lower data values as list of k min/max data values [[min_0,max_0],...,[min_k-1,max_k-1]]
bounds = np.array([0.0, 3.0])
# Set number of qubits per data dimension as list of k qubit values[#q_0,...,#q_k-1]
num_qubits = [2]
k = len(num_qubits)

qGAN 초기화하기

qGAN은 양자생성기 \(G_{\theta}\) , 즉 ansatz와 고전적인 식별자 \(D_{\phi}\) (신경망)로 구성되어 있다.

양자 생성기를 구현하기 위해서는 \(R_Y\) 회전을 구현하는 깊이 1 의 ansatz와 입력 상태로 균일한 분포를 취하는 \(CZ\) 게이트를 선택해야 한다. 특히 \(k>1\) 의 경우 생성기의 매개변수를 신중하게 선택해야 한다. 예를 들어, 더 높은 회로 깊이가 더 복잡한 구조의 표현을 가능하게 하기 때문에 회로 깊이는 \(k>1\) 이어야 한다.

여기서 사용되는 고전적인 판별기는 NumPy를 사용하는 신경망 구현을 기반으로 한다. 또한, Qiskit을 설치할 때 기본 옵션으로 설치되지 않은 PyTorch를 기반으로 한 판별기도 있다. 자세한 정보는 Optional Install 에서 찾아볼 수 있다.

여기서, 두 네트워크는 ADAM 최적화 알고리즘으로 업데이트된다 (ADAM은 기본 qGAN 최적화 프로그램이다).

[3]:
# Set number of training epochs
# Note: The algorithm's runtime can be shortened by reducing the number of training epochs.
num_epochs = 10
# Batch size
batch_size = 100

# Initialize qGAN
qgan = QGAN(real_data, bounds, num_qubits, batch_size, num_epochs, snapshot_dir=None)
qgan.seed = 1
# Set quantum instance to run the quantum generator
quantum_instance = QuantumInstance(
    backend=BasicAer.get_backend("statevector_simulator"), seed_transpiler=seed, seed_simulator=seed
)

# Set entangler map
entangler_map = [[0, 1]]


# Set an initial state for the generator circuit
init_dist = UniformDistribution(sum(num_qubits))

# Set the ansatz circuit
ansatz = TwoLocal(int(np.sum(num_qubits)), "ry", "cz", entanglement=entangler_map, reps=1)

# Set generator's initial parameters - in order to reduce the training time and hence the
# total running time for this notebook
init_params = [3.0, 1.0, 0.6, 1.6]

# You can increase the number of training epochs and use random initial parameters.
# init_params = np.random.rand(ansatz.num_parameters_settable) * 2 * np.pi

# Set generator circuit by adding the initial distribution infront of the ansatz
g_circuit = ansatz.compose(init_dist, front=True)

# Set quantum generator
qgan.set_generator(generator_circuit=g_circuit, generator_init_params=init_params)
# The parameters have an order issue that following is a temp. workaround
qgan._generator._free_parameters = sorted(g_circuit.parameters, key=lambda p: p.name)
# Set classical discriminator neural network
discriminator = NumPyDiscriminator(len(num_qubits))
qgan.set_discriminator(discriminator)

qGAN 학습 실행하기

훈련 중에 식별자 및 생성기의 매개변수는 다음과 같은 손실 함수가 번갈아 업데이트된다.

\[L_G\left(\phi, \theta\right) = -\frac{1}{m}\sum\limits_{l=1}^{m}\left[\log\left(D_{\phi}\left(g^{l}\right)\right)\right]\]

그리고

\[L_D\left(\phi, \theta\right) = \frac{1}{m}\sum\limits_{l=1}^{m}\left[\log D_{\phi}\left(x^{l}\right) + \log\left(1-D_{\phi}\left(g^{l}\right)\right)\right],\]

예를 들어, \(m\) 은 배치 사이즈 (batch size) 를 의미하고 \(g^l\) 는 양자 생성기 (quantum generator) 에 의해 발생된 데이터 샘플들을 의미한다.

이 노트북의 목적상, 알려진 초기 포인트(init_params) 를 선택함으로써 본 교육을 보다 간략하게 진행하였음을 유념해주길 바란다. 이러한 사전 지식이 없으면 교육에 시간이 다소 걸릴 수 있다.

[4]:
# Run qGAN
result = qgan.run(quantum_instance)
[5]:
print("Training results:")
for key, value in result.items():
    print(f"  {key} : {value}")
Training results:
  params_d : [ 0.03697158  0.61015372 -0.48103428 ... -0.1661673  -0.20186384
 -0.08584337]
  params_g : [2.95229918 0.9522102  0.55218478 1.64793094]
  loss_d : 0.6925
  loss_g : [0.7246]
  rel_entr : 0.107

학습 진행 및 결과

이제, 학습하는 동안 생성기의 및 식별자의 손실 함수의 전개 뿐만 아니라 훈련된 및 타겟 분포 사이의 상대적 엔트로피의 진행을 플로팅한다.

마지막으로, 학습된 분포의 누적 분포 함수 (CDF) 를 타겟 분포의 CDF와 비교한다.

[6]:
# Plot progress w.r.t the generator's and the discriminator's loss function
t_steps = np.arange(num_epochs)
plt.figure(figsize=(6, 5))
plt.title("Progress in the loss function")
plt.plot(
    t_steps, qgan.g_loss, label="Generator loss function", color="mediumvioletred", linewidth=2
)
plt.plot(
    t_steps, qgan.d_loss, label="Discriminator loss function", color="rebeccapurple", linewidth=2
)
plt.grid()
plt.legend(loc="best")
plt.xlabel("time steps")
plt.ylabel("loss")
plt.show()
../_images/tutorials_04_qgans_for_loading_random_distributions_10_0.png
[7]:
# Plot progress w.r.t relative entropy
plt.figure(figsize=(6, 5))
plt.title("Relative Entropy")
plt.plot(
    np.linspace(0, num_epochs, len(qgan.rel_entr)), qgan.rel_entr, color="mediumblue", lw=4, ls=":"
)
plt.grid()
plt.xlabel("time steps")
plt.ylabel("relative entropy")
plt.show()
../_images/tutorials_04_qgans_for_loading_random_distributions_11_0.png
[8]:
# Plot the CDF of the resulting distribution against the target distribution, i.e. log-normal
log_normal = np.random.lognormal(mean=1, sigma=1, size=100000)
log_normal = np.round(log_normal)
log_normal = log_normal[log_normal <= bounds[1]]
temp = []
for i in range(int(bounds[1] + 1)):
    temp += [np.sum(log_normal == i)]
log_normal = np.array(temp / sum(temp))

plt.figure(figsize=(6, 5))
plt.title("CDF (Cumulative Distribution Function)")
samples_g, prob_g = qgan.generator.get_output(qgan.quantum_instance, shots=10000)
samples_g = np.array(samples_g)
samples_g = samples_g.flatten()
num_bins = len(prob_g)
plt.bar(samples_g, np.cumsum(prob_g), color="royalblue", width=0.8, label="simulation")
plt.plot(
    np.cumsum(log_normal), "-o", label="log-normal", color="deepskyblue", linewidth=4, markersize=12
)
plt.xticks(np.arange(min(samples_g), max(samples_g) + 1, 1.0))
plt.grid()
plt.xlabel("x")
plt.ylabel("p(x)")
plt.legend(loc="best")
plt.show()
../_images/tutorials_04_qgans_for_loading_random_distributions_12_0.png
[9]:
import qiskit.tools.jupyter

%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
QiskitNone
Terra0.17.0.dev0+346ffa8
Aer0.8.0
Ignis0.6.0.dev0+d6f1ad7
AquaNone
IBM Q Provider0.13.0.dev0+10f19e0
System information
Python3.8.8 (default, Feb 24 2021, 13:46:16) [Clang 10.0.0 ]
OSDarwin
CPUs6
Memory (Gb)16.0
Wed Mar 31 23:30:54 2021 CEST

This code is a part of Qiskit

© Copyright IBM 2017, 2021.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.