Vietnamese
Ngôn ngữ
English
Bengali
French
Hindi
Italian
Japanese
Korean
Malayalam
Russian
Spanish
Tamil
Turkish
Vietnamese
Shortcuts

Ghi chú

Trang này được tạo từ docs/tutorals/01_neural_networks.ipynb.

Mạng Neuron Lượng tử

Notebook này triển khai các mạng neuron lượng tử cơ bản (QNN) khác nhau được cung cấp trong Trình Học máy Qiskit. Các mạng này được tạo ra để là các đơn vị tính toán không phụ thuộc vào bất kỳ ứng dụng cụ thể nào mà có thể được sử dụng cho nhiều trường hợp ứng dụng khác nhau. Tuỳ thuộc vào ứng dụng, sẽ có mạng phù hợp hơn, hoặc không phù hợp bằng, và có thể yêu cầu sắp đặt theo một cách nhất định. Các mạng neuron có sẵn sau đây sẽ được thảo luận chi tiết hơn:

  1. NeuralNetwork: Giao diện cho các mạng neuron.

  2. OpflowQNN: Mạng dựa trên việc đánh giá các đại lượng cơ học lượng tử quan sát được.

  3. TwoLayerQNN: Cách cài đặt OpflowQNN đặc biệt nhằm mục đích thuận tiện.

  4. CircuitQNN: Mạng dựa trên các mẫu có được từ các phép đo trên một mạch lượng tử.

[1]:
import numpy as np

from qiskit import Aer, QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap
from qiskit.opflow import StateFn, PauliSumOp, AerPauliExpectation, ListOp, Gradient
from qiskit.utils import QuantumInstance
[2]:
# set method to calculcate expected values
expval = AerPauliExpectation()

# define gradient method
gradient = Gradient()

# define quantum instances (statevector and sample based)
qi_sv = QuantumInstance(Aer.get_backend('aer_simulator_statevector'))

# we set shots to 10 as this will determine the number of samples later on.
qi_qasm = QuantumInstance(Aer.get_backend('aer_simulator'), shots=10)

1. NeuralNetwork

NeuralNetwork đại diện cho giao điện của tất cả mạng neuron sẵn có trong Trình Học Máy Qiskit. Nó chỉ ra một đường chuyền tới và lui, lấy các mẫu dữ liệu và các biến có thể huấn luyện được làm đầu vào. Một NeuralNetwork không có bất kỳ khả năng huấn luyện nào, những trọng trách này được chuyển giao cho chính các thuật toán/ứng dụng. Do đó, một NeuralNetwork cũng không lưu trữ các giá trị cho các biến có thể huấn luyện được. Mục sau đây sẽ giới thiệu các cách triển khai khác nhau của giao diện này.

Giả sử một NeuralNetwork gọi là nn. Sau đó, đường chuyền nn.forward(input, weights) lấy một trong hai đầu vào, một là cho dữ liệu và và hai là cho trọng lượng của kích thước nn.num_inputsnn.num_weights, tương ứng. NeuralNetwork hỗ trợ đầu dưới dạng các đợt và trả lại các đợt đầu ra với hình dạng tương ứng.

2. OpflowQNN

OpflowQNN lấy một toán tử (được tham số hoá) từ Qiskit và tận dụng khung gradient của Qiskit để cung cấp đường chuyền ngược lại. Một toán tử như vậy có thể là một giá trị trông đợi của một đại lượng quan sát cơ học lượng tử với một trạng thái lượng tử tham số. Các tham số có thể được sử dụng để tải dữ liệu cổ điển cũng như đại diện cho trọng lượng đào tạo được.``OpflowQNN`` cũng cho phép danh sách các toán tử và các cấu trúc phức tạp hơn để xây dựng những QNN phức tạp hơn.

[3]:
from qiskit_machine_learning.neural_networks import OpflowQNN
[4]:
# construct parametrized circuit
params1 = [Parameter('input1'), Parameter('weight1')]
qc1 = QuantumCircuit(1)
qc1.h(0)
qc1.ry(params1[0], 0)
qc1.rx(params1[1], 0)
qc_sfn1 = StateFn(qc1)

# construct cost operator
H1 = StateFn(PauliSumOp.from_list([('Z', 1.0), ('X', 1.0)]))

# combine operator and circuit to objective function
op1 = ~H1 @ qc_sfn1
print(op1)
ComposedOp([
  OperatorMeasurement(1.0 * Z
  + 1.0 * X),
  CircuitStateFn(
       ┌───┐┌────────────┐┌─────────────┐
  q_0: ┤ H ├┤ RY(input1) ├┤ RX(weight1) ├
       └───┘└────────────┘└─────────────┘
  )
])
[5]:
# construct OpflowQNN with the operator, the input parameters, the weight parameters,
# the expected value, gradient, and quantum instance.
qnn1 = OpflowQNN(op1, [params1[0]], [params1[1]], expval, gradient, qi_sv)
[6]:
# define (random) input and weights
input1 = np.random.rand(qnn1.num_inputs)
weights1 = np.random.rand(qnn1.num_weights)
[7]:
# QNN forward pass
qnn1.forward(input1, weights1)
[7]:
array([[0.81422018]])
[8]:
# QNN batched forward pass
qnn1.forward([input1, input1], weights1)
[8]:
array([[0.81422018],
       [0.81422018]])
[9]:
# QNN backward pass
qnn1.backward(input1, weights1)
[9]:
(array([[[-1.15629599]]]), array([[[0.0008565]]]))
[10]:
# QNN batched backward pass
qnn1.backward([input1, input1], weights1)
[10]:
(array([[[-1.15629599]],

        [[-1.15629599]]]),
 array([[[0.0008565]],

        [[0.0008565]]]))

Kết hợp nhiều đại lượng quan sát được trong một ListOp cũng cho phép tạo ra nhiều mạng neuron lượng tử (QNN) phức tạp hơn

[11]:
op2 = ListOp([op1, op1])
qnn2 = OpflowQNN(op2, [params1[0]], [params1[1]], expval, gradient, qi_sv)
[12]:
# QNN forward pass
qnn2.forward(input1, weights1)
[12]:
array([[0.81422018, 0.81422018]])
[13]:
# QNN backward pass
qnn2.backward(input1, weights1)
[13]:
(array([[[-1.15629599],
         [-1.15629599]]]),
 array([[[0.0008565],
         [0.0008565]]]))

3. TwoLayerQNN

TwoLayerQNN là một OpflowQNN đặc biệt trên \(n\) qubit bao gồm một bản đồ tính năng để chèn dữ liệu và một ansatz được đào tạo. Đại lượng quan sát mặc định là \(Z^{\otimes n}\), hay còn gọi là, tính chẵn lẻ.

[14]:
from qiskit_machine_learning.neural_networks import TwoLayerQNN
[15]:
# specify the number of qubits
num_qubits = 3
[16]:
# specify the feature map
fm = ZZFeatureMap(num_qubits, reps=2)
fm.draw(output='mpl')
[16]:
../_images/tutorials_01_neural_networks_20_0.png
[17]:
# specify the ansatz
ansatz = RealAmplitudes(num_qubits, reps=1)
ansatz.draw(output='mpl')
[17]:
../_images/tutorials_01_neural_networks_21_0.png
[18]:
# specify the observable
observable = PauliSumOp.from_list([('Z'*num_qubits, 1)])
print(observable)
1.0 * ZZZ
[19]:
# define two layer QNN
qnn3 = TwoLayerQNN(num_qubits,
                   feature_map=fm,
                   ansatz=ansatz,
                   observable=observable, quantum_instance=qi_sv)
[20]:
# define (random) input and weights
input3 = np.random.rand(qnn3.num_inputs)
weights3 = np.random.rand(qnn3.num_weights)
[21]:
# QNN forward pass
qnn3.forward(input3, weights3)
[21]:
array([[0.28520667]])
[22]:
# QNN backward pass
qnn3.backward(input3, weights3)
[22]:
(array([[[-0.2933431 , -0.78565729,  0.5416021 ]]]),
 array([[[-0.09093077,  0.02802006, -0.13559047,  0.1814619 ,
           0.11644461, -0.4073129 ]]]))

4. CircuitQNN

CircuitQNN dựa trên một QuantumCircuit (tham số hóa). Hàm này có thể lấy đầu vào cũng như các thông số trọng lượng và tạo ra các mẫu từ phép đo. Các mẫu có thể được hiểu là xác suất để đo chỉ số của số nguyên tương ứng với một chuỗi bit hoặc trực tiếp như một đợt đầu ra nhị phân. Trong trường hợp xác suất, các gradient có thể được ước tính một cách hiệu quả và `` CircuitQNN`` cung cấp đường truyền ngược. Trong trường hợp các mẫu, sự vi phân là không thể và đường truyền trả lại (None, None).

Hơn nữa, CircuitQNN cho phép xác định một hàm interpret để hậu xử lý các mẫu. Điều này được dự kiến sẽ lấy một số nguyên đo được (từ một chuỗi các bit) và ánh xạ nó đến một chỉ số mới, tức là số nguyên không âm. Trong trường hợp này, kích thước đầu ra cần phải được cung cấp và tổng hợp các xác suất sao cho phù hợp.

Một CircuitQNN có thể được thiết lập để trả lại các vectơ xác suất rời rạc cũng như đặc. Nếu không có hàm interpret nào được sử dụng, kích cỡ của chiều của vectơ xác suất sẽ được nhân lên theo hàm mũ với số lượng qubit và sự rời rạc thường được khuyến khích sử dụng. Trong trường hợp của một hàm interpret nó phụ thuộc vào kết quả mong đợi. Nếu, ví dụ, một chỉ số được ánh xạ đến tính chẵn lẻ của chuỗi bit tương ứng, tức là đối với 0 hoặc 1, một đầu ra dày đặc có nghĩa và kết quả sẽ là một vectơ xác suất của độ dài 2.

[23]:
from qiskit_machine_learning.neural_networks import CircuitQNN
[24]:
qc = RealAmplitudes(num_qubits, entanglement='linear', reps=1)
qc.draw(output='mpl')
[24]:
../_images/tutorials_01_neural_networks_29_0.png

4.1: Thông tin đầu ra: xác suất số nguyên thưa thớt

[25]:
# specify circuit QNN
qnn4 = CircuitQNN(qc, [], qc.parameters, sparse=True, quantum_instance=qi_qasm)
[26]:
# define (random) input and weights
input4 = np.random.rand(qnn4.num_inputs)
weights4 = np.random.rand(qnn4.num_weights)
[27]:
# QNN forward pass
qnn4.forward(input4, weights4).todense()  # returned as a sparse matrix
[27]:
array([[0.5, 0. , 0. , 0. , 0.3, 0. , 0. , 0.2]])
[28]:
# QNN backward pass, returns a tuple of sparse matrices
qnn4.backward(input4, weights4)
[28]:
(<COO: shape=(1, 8, 0), dtype=float64, nnz=0, fill_value=0.0>,
 <COO: shape=(1, 8, 6), dtype=float64, nnz=22, fill_value=0.0>)

4.2: Thông tin đầu ra: xác suất chẵn lẻ dày đặc

[29]:
# specify circuit QNN
parity = lambda x: '{:b}'.format(x).count('1') % 2
output_shape = 2  # this is required in case of a callable with dense output
qnn6 = CircuitQNN(qc, [], qc.parameters, sparse=False, interpret=parity, output_shape=output_shape,
                  quantum_instance=qi_qasm)
[30]:
# define (random) input and weights
input6 = np.random.rand(qnn6.num_inputs)
weights6 = np.random.rand(qnn6.num_weights)
[31]:
# QNN forward pass
qnn6.forward(input6, weights6)
[31]:
array([[0.8, 0.2]])
[32]:
# QNN backward pass
qnn6.backward(input6, weights6)
[32]:
(array([], shape=(1, 2, 0), dtype=float64),
 array([[[-1.00000000e-01,  5.55111512e-17, -5.00000000e-02,
           1.38777878e-17, -2.00000000e-01,  5.00000000e-02],
         [ 1.00000000e-01,  0.00000000e+00,  5.00000000e-02,
          -5.55111512e-17,  2.00000000e-01, -5.00000000e-02]]]))

4.3 Thông tin đầu ra: Các mẫu

[33]:
# specify circuit QNN
qnn7 = CircuitQNN(qc, [], qc.parameters, sampling=True,
                  quantum_instance=qi_qasm)
[34]:
# define (random) input and weights
input7 = np.random.rand(qnn7.num_inputs)
weights7 = np.random.rand(qnn7.num_weights)
[35]:
# QNN forward pass, results in samples of measured bit strings mapped to integers
qnn7.forward(input7, weights7)
[35]:
array([[[4.],
        [4.],
        [7.],
        [1.],
        [7.],
        [4.],
        [4.],
        [4.],
        [0.],
        [0.]]])
[36]:
# QNN backward pass
qnn7.backward(input7, weights7)
[36]:
(None, None)

4.4: Thông tin đầu ra: Các mẫu chẵn lẻ

[37]:
# specify circuit QNN
qnn8 = CircuitQNN(qc, [], qc.parameters, sampling=True, interpret=parity,
                  quantum_instance=qi_qasm)
[38]:
# define (random) input and weights
input8 = np.random.rand(qnn8.num_inputs)
weights8 = np.random.rand(qnn8.num_weights)
[39]:
# QNN forward pass, results in samples of measured bit strings
qnn8.forward(input8, weights8)
[39]:
array([[[1.],
        [0.],
        [1.],
        [0.],
        [0.],
        [0.],
        [0.],
        [0.],
        [0.],
        [0.]]])
[40]:
# QNN backward pass
qnn8.backward(input8, weights8)
[40]:
(None, None)
[41]:
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:25:48 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.

[ ]: