Tamil
மொழிகள்
English
Bengali
French
Hindi
Italian
Japanese
Korean
Malayalam
Russian
Spanish
Tamil
Turkish
Vietnamese
Shortcuts

Note

இந்தப் பக்கம் docs/tutorials/05_torch_connector.ipynb இலிருந்து உருவாக்கப்பட்டது.

டார்ச் இணைப்பான் மற்றும் கலப்பின QNN கள்

இந்த பயிற்சிகள் Qiskit-ன் TorchConnector வகுப்பை அறிமுகப்படுத்துகிறது, மேலும் TorchConnector Qiskit பொறி கற்றலிருந்து எந்த ஒரு நியூரல் நெட்வொர்க் ஐ ஒரு இயற்கையான ஒருங்கிணைப்பை அனுமதிக்கிறது. TorchConnector ஒரு Qiskit NeuralNetwork ஐ எடுத்து அதை PyTorch தொகுதி ஆக கிடைக்கச் செய்கிறது. இதன் விளைவாக தொகுதி PyTorch கிளாசிக்கல் கட்டமைப்புகளில் தடையின்றி இணைக்கப்படலாம் மற்றும் கூடுதல் பரிசீலனைகள் இல்லாமல் கூட்டாக பயிற்சி பெறலாம், நாவல் hybrid quantum-classical பொறி கற்றல் கட்டமைப்புகளின் வளர்ச்சி மற்றும் சோதனைக்கு உதவுகிறது.

உள்ளடக்கம்:

பகுதி 1: எளிய வகைப்பாடு & பின்னடைவு

இந்த பயிற்சிகளின் முதல் பகுதி எளிய வகைப்பாடு மற்றும் பின்னடைவு பணிகளுக்கு பைடார்ச்சின் தானியங்கி வேறுபாடு இயந்திரத்தை (torch.autograd, link) பயன்படுத்தி எப்படி குவாண்டம் neural network-களைப் பயிற்றுவிக்க முடியும் என்பதைக் காட்டுகிறது.

  1. வகைப்பாடு

    1. PyTorch மற்றும் OpflowQNN உடன் வகைப்பாடு

    2. PyTorch மற்றும் CircuitQNN உடன் வகைப்பாடு

  2. பின்னடைவு

    1. PyTorch மற்றும் OpflowQNN உடன் பின்னடைவு

பகுதி 2: MNIST வகைப்பாடு, கலப்பின QNN கள்

இந்த பயிற்சிகளின் இரண்டாம் பாகம் ஒரு (குவாண்டம்) நியூரல்நெட்வொர்க் ஐ ஒரு இலக்கு PyTorch பணிப்பாய்வு (இந்த வழக்கில், ஒரு பொதுவான CNN கட்டமைப்பு) ஒரு கலப்பின குவாண்டம்-கிளாசிக்கல் முறையில் MNIST தரவை வகைப்படுத்த விளக்குகிறது.


[1]:
# Necessary imports

import numpy as np
import matplotlib.pyplot as plt

from torch import Tensor
from torch.nn import Linear, CrossEntropyLoss, MSELoss
from torch.optim import LBFGS

from qiskit  import Aer, QuantumCircuit
from qiskit.utils import QuantumInstance
from qiskit.opflow import AerPauliExpectation
from qiskit.circuit import Parameter
from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap
from qiskit_machine_learning.neural_networks import CircuitQNN, TwoLayerQNN
from qiskit_machine_learning.connectors import TorchConnector

# declare quantum instance
qi = QuantumInstance(Aer.get_backend('aer_simulator_statevector'))

பகுதி 1: எளிய வகைப்பாடு மற்றும் பின்னடைவு

1. வகைப்பாடு

முதலில், TorchConnector ஒரு குவாண்டம் NeuralNetwork ஐ எவ்வாறு பயிற்சி அளிக்க அனுமதிக்கிறது என்பதை PyTorch இன் தானியங்கி வேறுபாடு இயந்திரத்தைப் பயன்படுத்தி ஒரு வகைப்படுத்தல் பணிகளைத் தீர்க்க உதவுகிறது. இதை விளக்கும் பொருட்டு, binary classification தோராயமாக உருவாக்கப்பட்ட தரவுத்தொகுப்பில் செய்வோம்.

[2]:
# Generate random dataset

# Set seed for random dataset
np.random.seed(5)

# Select dataset dimension (num_inputs) and size (num_samples)
num_inputs = 2
num_samples = 20

# Generate random input coordinates (X) and binary labels (y)
X = 2*np.random.rand(num_samples, num_inputs) - 1
y01 = 1*(np.sum(X, axis=1) >= 0)  # in { 0,  1}, y01 will be used for CircuitQNN example
y = 2*y01-1                       # in {-1, +1}, y will be used for OplowQNN example

# Convert to torch Tensors
X_ = Tensor(X)
y01_ = Tensor(y01).reshape(len(y)).long()
y_ = Tensor(y).reshape(len(y), 1)

# Plot dataset
for x, y_target in zip(X, y):
    if y_target == 1:
        plt.plot(x[0], x[1], 'bo')
    else:
        plt.plot(x[0], x[1], 'go')
plt.plot([-1, 1], [1, -1], '--', color='black')
plt.show()
../_images/tutorials_05_torch_connector_4_0.png

A. PyTorch மற்றும் OpflowQNN உடன் வகைப்பாடு

ஒரு OpflowQNN ஐ PyTorch உடன் இணைப்பது ஒப்பீட்டளவில் நேரடியானது. முந்தைய பயிற்சிகளில் அறிமுகப்படுத்தப்பட்ட OpflowQNN இன் துணை வழக்கு TwoLayerQNN ஐப் பயன்படுத்தி இங்கே விளக்குகிறோம்.

[3]:
# Set up QNN
# Note: we are not providing them explicitly in this examples,
# but TwoLayerQNN requires a feature_map and ansatz to work.
# By default, these parameters are set to  ZZFeatureMap
# and RealAmplitudes (respectively).
qnn1 = TwoLayerQNN(num_qubits=num_inputs, quantum_instance=qi)
print(qnn1.operator)

# Set up PyTorch module
# Note: If we don't explicitly declare the initial weights
# they are chosen uniformly at random from [-1, 1].
np.random.seed(10)
initial_weights = 0.1*(2*np.random.rand(qnn1.num_weights) - 1)
model1 = TorchConnector(qnn1, initial_weights=initial_weights)
print("Initial weights: ", initial_weights)
ComposedOp([
  OperatorMeasurement(1.0 * ZZ),
  CircuitStateFn(
       ┌────────────────────┐┌──────────────────────────────────────────────────┐
  q_0: ┤0                   ├┤0                                                 ├
       │  nlocal(x[0],x[1]) ││  nlocal(θ[0],θ[1],θ[2],θ[3],θ[4],θ[5],θ[6],θ[7]) │
  q_1: ┤1                   ├┤1                                                 ├
       └────────────────────┘└──────────────────────────────────────────────────┘
  )
])
Initial weights:  [ 0.05426413 -0.09584961  0.02672965  0.04976078 -0.0002986  -0.05504067
 -0.06038743  0.05210614]
[4]:
# Test with a single input
model1(X_[0, :])
[4]:
tensor([-0.0547], grad_fn=<_TorchNNFunctionBackward>)
ஆப்டிமைசெர்

எந்த இயந்திர கற்றல் மாதிரியையும் பயிற்றுவிப்பதற்கான ஆப்டிமைசரின் தேர்வு எங்கள் பயிற்சியின் முடிவின் வெற்றியை தீர்மானிப்பதில் முக்கியமானதாக இருக்கும். TorchConnector ஐப் பயன்படுத்தும் போது, [torch.optim] தொகுப்பில் (இணைப்பு) வரையறுக்கப்பட்ட அனைத்து ஆப்டிமைசர் வழிமுறைகளையும் அணுகலாம். பிரபலமான இயந்திர கற்றல் கட்டமைப்புகளில் பயன்படுத்தப்படும் மிகவும் பிரபலமான வழிமுறைகளில் Adam, SDG, அல்லது Adagrad ஆகியவை அடங்கும். எவ்வாறாயினும், இந்த டுடோரியலுக்கு நாம் L-BFGS அல்காரிதம் (torch.optim.LBFGS) ஐப் பயன்படுத்துவோம்.

Loss Function

Loss function பொறுத்தவரை, டார்ச்.என்என் இலிருந்து பைடார்ச்சின் முன் வரையறுக்கப்பட்ட தொகுதிகளையும் நாம் பயன்படுத்திக் கொள்ளலாம், அதாவது, கிராஸ்-என்ட்ரோபி அல்லது சராசரி சதுர பிழை இழப்புகள்.

💡விளக்கம்:, இந்த பரிந்துரை வகைப்படுத்தல் நெட்வொர்க்கின் வெளியீடு [0,1] வரம்பில் ஒரு வகுப்பு நிகழ்தகவு மதிப்பு என்ற அனுமானத்தின் கீழ் வழங்கப்படுகிறது (பொதுவாக இது ஒரு Softmax அடுக்கு மூலம் அடையப்படுகிறது). TwoLayerQNN க்கான பின்வரும் உதாரணம் அத்தகைய லேயரை உள்ளடக்கவில்லை, மேலும் வெளியீட்டில் எந்த மேப்பிங்கையும் நாங்கள் பயன்படுத்தவில்லை (பின்வரும் பிரிவு CircuitQNN உடன் சமநிலை மேப்பிங்கின் உதாரணத்தைக் காட்டுகிறது), QNN வெளியீடு வரம்பில் எந்த மதிப்பையும் எடுக்கலாம் [-1,1]. நீங்கள் ஆச்சரியப்படுகிறீர்கள் என்றால், இந்த குறிப்பிட்ட உதாரணம் MSELoss ஐ வகைப்படுத்தலுக்குப் பயன்படுத்துவதற்கு இது விதிமுறையாக இல்லாவிட்டாலும் (ஆனால் வெவ்வேறு இழப்புச் செயல்பாடுகளை பரிசோதிக்கவும், பயிற்சி முடிவுகளை எப்படி பாதிக்கலாம் என்பதைப் பார்க்கவும் நாங்கள் ஊக்குவிக்கிறோம்).

[5]:
# Define optimizer and loss
optimizer = LBFGS(model1.parameters())
f_loss = MSELoss(reduction='sum')

# Start training
model1.train()   # set model to training mode


# Note from (https://pytorch.org/docs/stable/optim.html):
# Some optimization algorithms such as LBFGS need to
# reevaluate the function multiple times, so you have to
# pass in a closure that allows them to recompute your model.
# The closure should clear the gradients, compute the loss,
# and return it.
def closure():
    optimizer.zero_grad()          # Initialize/clear gradients
    loss = f_loss(model1(X_), y_)  # Evaluate loss function
    loss.backward()                # Backward pass
    print(loss.item())             # Print loss
    return loss

# Run optimizer step4
optimizer.step(closure)
29.08934783935547
22.97238540649414
16.25204849243164
29.874549865722656
15.212966918945312
15.903762817382812
14.69144058227539
15.069099426269531
14.648868560791016
14.838859558105469
14.472648620605469
17.432323455810547
17.68243408203125
22.356327056884766
15.594417572021484
35.22927474975586
35.516239166259766
29.633190155029297
31.025428771972656
19.802261352539062
[5]:
tensor(29.0893, grad_fn=<MseLossBackward>)
[6]:
# Evaluate model and compute accuracy
y_predict = []
for x, y_target in zip(X, y):
    output = model1(Tensor(x))
    y_predict += [np.sign(output.detach().numpy())[0]]

print('Accuracy:', sum(y_predict == y)/len(y))

# Plot results
# red == wrongly classified
for x, y_target, y_p in zip(X, y, y_predict):
    if y_target == 1:
        plt.plot(x[0], x[1], 'bo')
    else:
        plt.plot(x[0], x[1], 'go')
    if y_target != y_p:
        plt.scatter(x[0], x[1], s=200, facecolors='none', edgecolors='r', linewidths=2)
plt.plot([-1, 1], [1, -1], '--', color='black')
plt.show()
Accuracy: 0.55
../_images/tutorials_05_torch_connector_10_1.png

சிவப்பு வட்டங்கள் தவறாக வகைப்படுத்தப்பட்ட தரவு புள்ளிகளைக் குறிக்கின்றன.

B. PyTorch மற்றும் CircuitQNN உடன் வகைப்பாடு

PyTorch உடன் ஒரு CircuitQNN ஐ இணைப்பதற்கு OpflowQNN ஐ விட சற்று அதிக கவனம் தேவை. சரியான அமைப்பு இல்லாமல், பின்னடைவு சாத்தியமில்லை.

குறிப்பாக, நெட்வொர்க்கின் முன்னோக்கி பாஸில் அடர்த்தியான சாத்தியக்கூறுகளை நாங்கள் திருப்பித் தருகிறோம் என்பதை உறுதி செய்ய வேண்டும் (spares=False). இந்த அளவுரு இயல்பாக False என அமைக்கப்பட்டுள்ளது, எனவே அது மாற்றப்படவில்லை என்பதை நாம் உறுதி செய்ய வேண்டும்.

⚠️ கவனம்: தனிப்பயன் விளக்கச் செயல்பாட்டை நாம் வரையறுத்தால் (எடுத்துக்காட்டில்: சமநிலை), விரும்பிய வெளியீட்டு வடிவத்தை வெளிப்படையாக வழங்க நினைவில் கொள்ள வேண்டும் (எடுத்துக்காட்டில்: 2). CircuitQNN க்கான ஆரம்ப அளவுரு அமைவு பற்றிய மேலும் தகவலுக்கு, தயவுசெய்து அதிகாரப்பூர்வ qiskit ஆவணத்தை.

[7]:
# Define feature map and ansatz
feature_map = ZZFeatureMap(num_inputs)
ansatz = RealAmplitudes(num_inputs, entanglement='linear', reps=1)

# Define quantum circuit of num_qubits = input dim
# Append feature map and ansatz
qc = QuantumCircuit(num_inputs)
qc.append(feature_map, range(num_inputs))
qc.append(ansatz, range(num_inputs))


# Define CircuitQNN and initial setup
parity = lambda x: '{:b}'.format(x).count('1') % 2 # optional interpret function
output_shape = 2  # parity = 0, 1
qnn2 = CircuitQNN(qc, input_params=feature_map.parameters, weight_params=ansatz.parameters,
                  interpret=parity, output_shape=output_shape, quantum_instance=qi)

# Set up PyTorch module
# Reminder: If we don't explicitly declare the initial weights
# they are chosen uniformly at random from [-1, 1].
np.random.seed(9)
initial_weights = 0.1*(2*np.random.rand(qnn2.num_weights) - 1)
print("Initial weights: ", initial_weights)
model2 = TorchConnector(qnn2, initial_weights)
Initial weights:  [-0.09792517  0.00037492 -0.00084534 -0.07323409]

ஆப்டிமைசெர் மற்றும் loss function தேர்வுகள் பற்றிய நினைவூட்டலுக்கு, நீங்கள் இந்தப் பிரிவுக்குச் செல்லலாம்.

[8]:
# Define model, optimizer, and loss
optimizer = LBFGS(model2.parameters())
f_loss = CrossEntropyLoss() # Our output will be in the [0,1] range

# Start training
model2.train()

# Define LBFGS closure method (explained in previous section)
def closure():
    optimizer.zero_grad(set_to_none=True)                  # Initialize gradient
    loss = f_loss(model2(X_), y01_)                        # Calculate loss
    loss.backward()                                        # Backward pass

    print(loss.item())                                     # Print loss
    return loss

# Run optimizer (LBFGS requires closure)
optimizer.step(closure);
0.6603068709373474
0.6486624479293823
0.5996587872505188
0.589975893497467
0.5881412029266357
0.5867496728897095
0.5887688398361206
0.5896384119987488
0.5888267159461975
0.5813128352165222
0.5787640810012817
0.7018635272979736
0.7185250520706177
0.7709338665008545
0.7072550058364868
0.7725899815559387
0.6697829365730286
0.7946376800537109
0.6232572793960571
0.6820956468582153
[9]:
# Evaluate model and compute accuracy
y_predict = []
for x in X:
    output = model2(Tensor(x))
    y_predict += [np.argmax(output.detach().numpy())]

print('Accuracy:', sum(y_predict == y01)/len(y01))

# plot results
# red == wrongly classified
for x, y_target, y_ in zip(X, y01, y_predict):
    if y_target == 1:
        plt.plot(x[0], x[1], 'bo')
    else:
        plt.plot(x[0], x[1], 'go')
    if y_target != y_:
        plt.scatter(x[0], x[1], s=200, facecolors='none', edgecolors='r', linewidths=2)
plt.plot([-1, 1], [1, -1], '--', color='black')
plt.show()
Accuracy: 0.75
../_images/tutorials_05_torch_connector_16_1.png

சிவப்பு வட்டங்கள் தவறாக வகைப்படுத்தப்பட்ட தரவு புள்ளிகளைக் குறிக்கின்றன.

2. பின்னடைவு

ஒரு பின்னடைவு பணியை எப்படிச் செய்வது என்பதை விளக்குவதற்கு TwoLayerQNN அடிப்படையிலான மாதிரியைப் பயன்படுத்துகிறோம். இந்த வழக்கில் தேர்ந்தெடுக்கப்பட்ட தரவுத் தொகுப்பு சைன் அலைகளைத் தொடர்ந்து தோராயமாக உருவாக்கப்பட்டது.

[10]:
# Generate random dataset

np.random.seed(0)
num_samples = 20
eps = 0.2
lb, ub = -np.pi, np.pi
f = lambda x: np.sin(x)

X = (ub - lb)*np.random.rand(num_samples, 1) + lb
y = f(X) + eps*(2*np.random.rand(num_samples, 1)-1)
plt.plot(np.linspace(lb, ub), f(np.linspace(lb, ub)), 'r--')
plt.plot(X, y, 'bo')
plt.show()
../_images/tutorials_05_torch_connector_19_0.png

A. PyTorch மற்றும் OpflowQNN உடன் பின்னடைவு

நெட்வொர்க் வரையறை மற்றும் பயிற்சி வளையம் TwoLayerQNN ஐப் பயன்படுத்தி வகைப்பாடு பணிக்கு ஒத்ததாக இருக்கும். இந்த வழக்கில், இயல்புநிலை மதிப்புகளைப் பயன்படுத்துவதற்குப் பதிலாக, எங்கள் சொந்த அம்ச வரைபடம் மற்றும் அன்சாட்ஸை நாங்கள் வரையறுக்கிறோம்.

[11]:
# Construct simple feature map
param_x = Parameter('x')
feature_map = QuantumCircuit(1, name='fm')
feature_map.ry(param_x, 0)

# Construct simple feature map
param_y = Parameter('y')
ansatz = QuantumCircuit(1, name='vf')
ansatz.ry(param_y, 0)

# Construct QNN
qnn3 = TwoLayerQNN(1, feature_map, ansatz, quantum_instance=qi)
print(qnn3.operator)

# Set up PyTorch module
# Reminder: If we don't explicitly declare the initial weights
# they are chosen uniformly at random from [-1, 1].
# Set seed for random dataset
np.random.seed(7)
initial_weights = 0.1*(2*np.random.rand(qnn3.num_weights) - 1)
model3 = TorchConnector(qnn3, initial_weights)
ComposedOp([
  OperatorMeasurement(1.0 * Z),
  CircuitStateFn(
       ┌───────┐┌───────┐
  q_0: ┤ fm(x) ├┤ vf(y) ├
       └───────┘└───────┘
  )
])

ஆப்டிமைசெர் மற்றும் loss function தேர்வுகள் பற்றிய நினைவூட்டலுக்கு, நீங்கள் இந்தப் பிரிவுக்குச் செல்லலாம்.

[12]:
# Define optimizer and loss function
optimizer = LBFGS(model3.parameters())
f_loss = MSELoss(reduction='sum')

# Start training
model3.train()   # set model to training mode

# Define objective function
def closure():
    optimizer.zero_grad(set_to_none=True)        # Initialize gradient
    loss = f_loss(model3(Tensor(X)), Tensor(y))  # Compute batch loss
    loss.backward()                              # Backward pass
    print(loss.item())                           # Print loss
    return loss

# Run optimizer
optimizer.step(closure)
21.348440170288086
3.375812292098999
21.63526153564453
2.7181315422058105
30.3101806640625
9.999582290649414
19.066198348999023
1.8251923322677612
10.245695114135742
0.30168071389198303
0.3217697739601135
0.2346433401107788
0.2989022135734558
0.24148759245872498
0.19600583612918854
0.23429127037525177
0.3245868384838104
0.23837639391422272
0.2259863168001175
0.296633780002594
[12]:
tensor(21.3484, grad_fn=<MseLossBackward>)
[13]:
# Plot target function
plt.plot(np.linspace(lb, ub), f(np.linspace(lb, ub)), 'r--')

# Plot data
plt.plot(X, y, 'bo')

# Plot fitted line
y_ = []
for x in np.linspace(lb, ub):
    output = model3(Tensor([x]))
    y_ += [output.detach().numpy()[0]]
plt.plot(np.linspace(lb, ub), y_, 'g-')
plt.show()
../_images/tutorials_05_torch_connector_25_0.png

பகுதி 2: MNIST வகைப்பாடு, கலப்பின QNN கள்

இந்த இரண்டாம் பாகத்தில், MNIST கையால் எழுதப்பட்ட இலக்கங்கள் தரவுத்தொகுப்பில் மிகவும் சிக்கலான பட வகைப்பாடு பணியைச் செய்ய, TorchConnector ஐப் பயன்படுத்தி ஒரு கலப்பின குவாண்டம்-கிளாசிக்கல் நரம்பியல் நெட்வொர்க்கை எவ்வாறு மேம்படுத்துவது என்பதைக் காண்பிப்போம்.

ஹைபிரிட் குவாண்டம்-கிளாசிக்கல் நியூரல் நெட்வொர்க்குகள் பற்றிய விரிவான (முன்-TorchConnector) விளக்கத்திற்கு, நீங்கள் Qiskit Textbook இல் தொடர்புடைய பிரிவைப் பார்க்கலாம்.

[14]:
# Additional torch-related imports
from torch import cat, no_grad, manual_seed
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
import torch.optim as optim
from torch.nn import (Module, Conv2d, Linear, Dropout2d, NLLLoss,
                     MaxPool2d, Flatten, Sequential, ReLU)
import torch.nn.functional as F

படி 1: ரயில் மற்றும் சோதனைக்கான தரவு ஏற்றிகளை வரையறுத்தல்

நாங்கள் torchvision API ஐப் பயன்படுத்தி MNIST தரவுத்தொகுப்பு மற்றும் டார்ச்சை வரையறுக்கவும் DataLoaders (இணைப்பு) ரயில் மற்றும் சோதனை.

[15]:
# Train Dataset
# -------------

# Set train shuffle seed (for reproducibility)
manual_seed(1)

batch_size = 1
n_samples = 100 # We will concentrate on the first 100 samples

# Use pre-defined torchvision function to load MNIST train data
X_train = datasets.MNIST(root='./data', train=True, download=True,
                         transform=transforms.Compose([transforms.ToTensor()]))

# Filter out labels (originally 0-9), leaving only labels 0 and 1
idx = np.append(np.where(X_train.targets == 0)[0][:n_samples],
                np.where(X_train.targets == 1)[0][:n_samples])
X_train.data = X_train.data[idx]
X_train.targets = X_train.targets[idx]

# Define torch dataloader with filtered data
train_loader = DataLoader(X_train, batch_size=batch_size, shuffle=True)

நாம் விரைவான காட்சிப்படுத்தலைச் செய்தால், ரயில் தரவுத்தொகுப்பு கையால் எழுதப்பட்ட 0 கள் மற்றும் 1 களின் படங்களைக் கொண்டிருப்பதைக் காணலாம்.

[16]:
n_samples_show = 6

data_iter = iter(train_loader)
fig, axes = plt.subplots(nrows=1, ncols=n_samples_show, figsize=(10, 3))

while n_samples_show > 0:
    images, targets = data_iter.__next__()

    axes[n_samples_show - 1].imshow(images[0, 0].numpy().squeeze(), cmap='gray')
    axes[n_samples_show - 1].set_xticks([])
    axes[n_samples_show - 1].set_yticks([])
    axes[n_samples_show - 1].set_title("Labeled: {}".format(targets[0].item()))

    n_samples_show -= 1
../_images/tutorials_05_torch_connector_32_0.png
[17]:
# Test Dataset
# -------------

# Set test shuffle seed (for reproducibility)
# manual_seed(5)

n_samples = 50

# Use pre-defined torchvision function to load MNIST test data
X_test = datasets.MNIST(root='./data', train=False, download=True,
                        transform=transforms.Compose([transforms.ToTensor()]))

# Filter out labels (originally 0-9), leaving only labels 0 and 1
idx = np.append(np.where(X_test.targets == 0)[0][:n_samples],
                np.where(X_test.targets == 1)[0][:n_samples])
X_test.data = X_test.data[idx]
X_test.targets = X_test.targets[idx]

# Define torch dataloader with filtered data
test_loader = DataLoader(X_test, batch_size=batch_size, shuffle=True)

படி 2: QNN மற்றும் கலப்பின மாதிரியை வரையறுத்தல்

இந்த இரண்டாவது படி TorchConnector இன் சக்தியைக் காட்டுகிறது. எங்கள் குவாண்டம் நரம்பியல் நெட்வொர்க் லேயரை வரையறுத்த பிறகு (இந்த விஷயத்தில், TwoLayerQNN), TorchConnector(qnn) என டார்ச் கனெக்டரை துவக்குவதன் மூலம் அதை Module இல் ஒரு லேயரில் உட்பொதிக்கலாம்.

**⚠️கவனம்: ** கலப்பின மாடல்களில் போதிய சாய்வு பின்னணி இருக்க, நாம் qnn துவக்கத்தின் போது ஆரம்ப அளவுரு input_gradients ஐ TRUE க்கு அமைக்க வேண்டும்.

[18]:
# Define QNN
feature_map = ZZFeatureMap(2)
ansatz = RealAmplitudes(2, reps=1)
# REMEMBER TO SET input_gradients=True FOR ENABLING HYBRID GRADIENT BACKPROP
qnn4 = TwoLayerQNN(2, feature_map, ansatz, input_gradients=True, exp_val=AerPauliExpectation(), quantum_instance=qi)
print(qnn4.operator)
ComposedOp([
  OperatorMeasurement(1.0 * ZZ),
  CircuitStateFn(
       ┌────────────────────┐┌──────────────────────────────┐
  q_0: ┤0                   ├┤0                             ├
       │  nlocal(x[0],x[1]) ││  nlocal(θ[0],θ[1],θ[2],θ[3]) │
  q_1: ┤1                   ├┤1                             ├
       └────────────────────┘└──────────────────────────────┘
  )
])
[19]:
# Define torch NN module

class Net(Module):

    def __init__(self):
        super().__init__()
        self.conv1 = Conv2d(1, 2, kernel_size=5)
        self.conv2 = Conv2d(2, 16, kernel_size=5)
        self.dropout = Dropout2d()
        self.fc1 = Linear(256, 64)
        self.fc2 = Linear(64, 2)         # 2-dimensional input to QNN
        self.qnn = TorchConnector(qnn4)  # Apply torch connector, weights chosen
                                         # uniformly at random from interval [-1,1].
        self.fc3 = Linear(1, 1)          # 1-dimensional output from QNN

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2)
        x = self.dropout(x)
        x = x.view(x.shape[0], -1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        x = self.qnn(x)  # apply QNN
        x = self.fc3(x)
        return cat((x, 1 - x), -1)

model4 = Net()

படி 3: பயிற்சி

[20]:
# Define model, optimizer, and loss function
optimizer = optim.Adam(model4.parameters(), lr=0.001)
loss_func = NLLLoss()

# Start training
epochs = 10     # Set number of epochs
loss_list = []  # Store loss history
model4.train()  # Set model to training mode

for epoch in range(epochs):
    total_loss = []
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad(set_to_none=True)  # Initialize gradient
        output = model4(data)                  # Forward pass
        loss = loss_func(output, target)       # Calculate loss
        loss.backward()                        # Backward pass
        optimizer.step()                       # Optimize weights
        total_loss.append(loss.item())         # Store loss
    loss_list.append(sum(total_loss)/len(total_loss))
    print('Training [{:.0f}%]\tLoss: {:.4f}'.format(
        100. * (epoch + 1) / epochs, loss_list[-1]))
Training [10%]  Loss: -0.7126
Training [20%]  Loss: -0.9233
Training [30%]  Loss: -1.1075
Training [40%]  Loss: -1.2774
Training [50%]  Loss: -1.4991
Training [60%]  Loss: -1.5984
Training [70%]  Loss: -1.8882
Training [80%]  Loss: -2.0387
Training [90%]  Loss: -2.2595
Training [100%] Loss: -2.4982
[21]:
# Plot loss convergence
plt.plot(loss_list)
plt.title('Hybrid NN Training Convergence')
plt.xlabel('Training Iterations')
plt.ylabel('Neg. Log Likelihood Loss')
plt.show()
../_images/tutorials_05_torch_connector_40_0.png

படி 4: மதிப்பீடு

[22]:
model4.eval()  # set model to evaluation mode
with no_grad():

    correct = 0
    for batch_idx, (data, target) in enumerate(test_loader):
        output = model4(data)
        if len(output.shape) == 1:
            output = output.reshape(1, *output.shape)

        pred = output.argmax(dim=1, keepdim=True)
        correct += pred.eq(target.view_as(pred)).sum().item()

        loss = loss_func(output, target)
        total_loss.append(loss.item())

    print('Performance on test data:\n\tLoss: {:.4f}\n\tAccuracy: {:.1f}%'
          .format(sum(total_loss) / len(total_loss),
                  correct / len(test_loader) / batch_size * 100)
    )
Performance on test data:
        Loss: -2.5128
        Accuracy: 98.0%
[23]:
# Plot predicted labels

n_samples_show = 6
count = 0
fig, axes = plt.subplots(nrows=1, ncols=n_samples_show, figsize=(10, 3))

model4.eval()
with no_grad():
    for batch_idx, (data, target) in enumerate(test_loader):
        if count == n_samples_show:
            break
        output = model4(data[0:1])
        if len(output.shape) == 1:
            output = output.reshape(1, *output.shape)

        pred = output.argmax(dim=1, keepdim=True)

        axes[count].imshow(data[0].numpy().squeeze(), cmap='gray')

        axes[count].set_xticks([])
        axes[count].set_yticks([])
        axes[count].set_title('Predicted {}'.format(pred.item()))

        count += 1
../_images/tutorials_05_torch_connector_43_0.png

🎉🎉🎉🎉 நீங்கள் இப்போது உங்கள் சொந்த கலப்பின தரவுத்தொகுப்புகள் மற்றும் கட்டிடக்கலைகளை Qiskit இயந்திரக் கற்றலைப் பயன்படுத்திப் பரிசோதிக்க முடியும். அதிர்ஷ்டம் உங்களுக்கு உரித்தாகட்டும்!

[24]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
QiskitNone
Terra0.17.4
Aer0.8.2
IgnisNone
AquaNone
IBM Q ProviderNone
System information
Python3.9.6 (default, Jun 29 2021, 05:25:02) [Clang 12.0.5 (clang-1205.0.22.9)]
OSDarwin
CPUs8
Memory (Gb)64.0
Wed Jul 07 09:47:11 2021 JST

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.