Japanese
言語
English
Bengali
French
Hindi
Italian
Japanese
Korean
Malayalam
Russian
Spanish
Tamil
Turkish
Vietnamese
Shortcuts

注釈

このページは docs/tutorials/01_neural_networks.ipynb から生成されました。

量子ニューラル・ネットワーク

このノートブックでは、 Qiskit 機械学習で提供される、さまざまな汎用的な量子ニューラル・ネットワーク (QNN) の実装を紹介します。 このネットワークは、アプリケーションに依存しない計算ユニットとして、様々なユースケースに使用することができます。アプリケーションによっては、特定のタイプのネットワークが適していたり、適していなかったり、特定の方法でセットアップする必要があったりします。ここでは、次のような種類のニューラルネットワークについて、詳しく説明します。

  1. NeuralNetwork: ニューラル・ネットワークのインターフェース。

  2. OflowQNN: 量子力学的観測量の評価に基づくネットワーク。

  3. TwoLayerQNN: 利便性のための特別な OpflowQNN の実装。

  4. CircuitQNN: 量子回路を測定することによって得られたサンプルに基づいたネットワーク。

[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, algorithm_globals

algorithm_globals.random_seed = 42
[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

The NeuralNetwork represents the interface for all neural networks available in Qiskit Machine Learning. It exposes a forward and a backward pass taking the data samples and trainable weights as input. A NeuralNetwork does not contain any training capabilities, these are pushed to the actual algorithms / applications. Thus, a NeuralNetwork also does not store the values for trainable weights. In the following, different implementations of this interfaces are introduced.

nn という NeuralNetwork を想定します。次に、 nn.forward(input, weights) パスは、データのフラット入力と、サイズ nn.num_inputs および nn.num_weights の重みをそれぞれ受け取ります。 NeuralNetwork は入力のバッチ処理をサポートし、対応する形状の出力のバッチを返します。

2. OpflowQNN

OpflowQNN は、Qiskitから(パラメーター化された)演算子を取得し、Qiskitのgradientフレームワークを利用して逆伝搬パスを提供します。このような演算子は、たとえば、パラメーター化された量子状態に関する量子力学における観測量の期待値です。パラメーターを使用して、古典的なデータをロードしたり、トレーニング可能な重みを表すことができます。OpflowQNN を使用すると、演算子のリストとより複雑な構造を使用して、より複雑なQNNを構築することもできます。

[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 = algorithm_globals.random.random(qnn1.num_inputs)
weights1 = algorithm_globals.random.random(qnn1.num_weights)
[7]:
# QNN forward pass
qnn1.forward(input1, weights1)
[7]:
array([[0.08242345]])
[8]:
# QNN batched forward pass
qnn1.forward([input1, input1], weights1)
[8]:
array([[0.08242345],
       [0.08242345]])
[9]:
# QNN backward pass
qnn1.backward(input1, weights1)
[9]:
(None, array([[[0.2970094]]]))
[10]:
# QNN batched backward pass
qnn1.backward([input1, input1], weights1)
[10]:
(None,
 array([[[0.2970094]],

        [[0.2970094]]]))

ListOp で複数の観測量(オブザーバブル)を組み合わせることで、より複雑なQNNを作ることもできます。

[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.08242345, 0.08242345]])
[13]:
# QNN backward pass
qnn2.backward(input1, weights1)
[13]:
(None,
 array([[[0.2970094],
         [0.2970094]]]))

3. TwoLayerQNN

TwoLayerQNN は、\(n\) 量子ビット上の特別な OpflowQNN で、第一にデータを挿入する特徴マップ、第二に学習されるアンサツから構成されています。デフォルトの観測値は \(Z^{\otimes n}\) 、すなわちパリティです。

[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 = algorithm_globals.random.random(qnn3.num_inputs)
weights3 = algorithm_globals.random.random(qnn3.num_weights)
[21]:
# QNN forward pass
qnn3.forward(input3, weights3)
[21]:
array([[0.18276559]])
[22]:
# QNN backward pass
qnn3.backward(input3, weights3)
[22]:
(None,
 array([[[ 0.10231208,  0.10656571,  0.41017902,  0.16528909,
          -0.27780262,  0.41365763]]]))

4. CircuitQNN

CircuitQNN は、(パラメータ化された) QuantumCircuit をベースにしています。これは、入力だけでなくウェイトパラメーターも取ることができ、測定からサンプルを生成します。サンプルは、ビット列に対応する整数インデックスを測定する確率として解釈することも、バイナリー出力のバッチとして直接解釈することもできます。確率の場合、勾配を効率的に推定することができ、 CircuitQNN は逆伝搬パスも提供します。サンプルの場合、微分は不可能であり、逆伝搬パスは (None, None) を返します。

さらに、 CircuitQNN では、サンプルを後処理するための interpret 関数を指定することができます。これは、(ビット列から)測定された整数を受け取り、それを新しいインデックス、すなわち非負の整数にマッピングすることが期待されます。この場合、出力の形を提供する必要があり、それに応じて確率が調整されます。

A CircuitQNN can be configured to return sparse as well as dense probability vectors. If no interpret function is used, the dimension of the probability vector scales exponentially with the number of qubits and a sparse recommendation is usually recommended. In case of an interpret function it depends on the expected outcome. If, for instance, an index is mapped to the parity of the corresponding bitstring, i.e., to 0 or 1, a dense output makes sense and the result will be a probability vector of length 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 出力: 疎な整数の確率

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

4.2 出力: 密なパリティ確率

[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 = algorithm_globals.random.random(qnn6.num_inputs)
weights6 = algorithm_globals.random.random(qnn6.num_weights)
[31]:
# QNN forward pass
qnn6.forward(input6, weights6)
[31]:
array([[0.5, 0.5]])
[32]:
# QNN backward pass
qnn6.backward(input6, weights6)
[32]:
(None,
 array([[[-0.2 ,  0.1 , -0.15, -0.15,  0.15, -0.15],
         [ 0.2 , -0.1 ,  0.15,  0.15, -0.15,  0.15]]]))

4.3 出力: サンプル

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

4.4 出力: パリティー・サンプル

[37]:
# specify circuit QNN
qnn8 = CircuitQNN(qc, [], qc.parameters, sampling=True, interpret=parity, quantum_instance=qi_qasm)
[38]:
# define (random) input and weights
input8 = algorithm_globals.random.random(qnn8.num_inputs)
weights8 = algorithm_globals.random.random(qnn8.num_weights)
[39]:
# QNN forward pass, results in samples of measured bit strings
qnn8.forward(input8, weights8)
[39]:
array([[[0.],
        [1.],
        [1.],
        [0.],
        [1.],
        [0.],
        [0.],
        [0.],
        [1.],
        [1.]]])
[40]:
# QNN backward pass
qnn8.backward(input8, weights8)
[40]:
(None, None)
[43]:
import qiskit.tools.jupyter

%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.19.0
qiskit-aer0.9.0
qiskit-ignis0.7.0
qiskit-ibmq-provider0.17.0
qiskit-aqua0.10.0
qiskit-machine-learning0.3.0
System information
Python3.8.10 (default, Jun 2 2021, 10:49:15) [GCC 9.4.0]
OSLinux
CPUs4
Memory (Gb)7.6849517822265625
Sat Aug 28 01:04:52 2021 IST

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.

[ ]: