Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quantum-kittens
GitHub Repository: quantum-kittens/platypus
Path: blob/main/translations/pt/quantum-machine-learning/encoding.ipynb
3860 views
Kernel: Python 3

Codificação de dados

Nesta página, apresentaremos o problema de codificação de dados para aprendizado de máquina quântico e, em seguida, descreveremos e implementaremos vários métodos de codificação de dados.

Introdução

A representação de dados é crucial para o sucesso dos modelos de aprendizado de máquina. Para o aprendizado de máquina clássico, o problema é como representar os dados numericamente, para que possam ser melhor processados por um algoritmo de aprendizado de máquina clássico.

Para o aprendizado de máquina quântico, essa questão é semelhante, mas mais fundamental: como representar e inserir eficientemente os dados em um sistema quântico, para que possam ser processados por um algoritmo de aprendizado de máquina quântico. Isso geralmente é chamado de codificação de dados, mas também é chamado de incorporação ou carregamento de dados.

Esse processo é uma parte crucial dos algoritmos de aprendizado de máquina quânticos e afeta diretamente seu poder computacional.

Métodos

Vamos considerar um conjunto de dados clássico X\mathscr{X} consistindo de MM amostras, cada uma com NN características : ParseError: KaTeX parse error: Undefined control sequence: \class at position 1: \̲c̲l̲a̲s̲s̲{script-x}{\mat… onde x(m)x^{(m)} é um vetor NN dimensional para m=1,...,Mm = 1, ..., M. Para representar este conjunto de dados em um sistema de qubits, podemos usar várias técnicas de incorporação, algumas das quais são brevemente explicadas e implementadas a seguir, conforme as Referências 1 e 2 .

Codificação de base

A codificação de base associa uma string clássica de NN bits com um estado de base computacional de um sistema de NN qubits. Por exemplo, se x=5x = 5, isso pode ser representado como uma string de 44 bist como 01010101, e por um sistema 44 qubits como o estado quântico 0101|0101\rangle. De forma geral, para uma string de NN bits: x=(b1,b2,...,bN)x = (b_1, b_2, ... , b_N), o estado de NN qubits correspondente é ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{ket-x}{| x \ra… com ParseError: KaTeX parse error: Undefined control sequence: \class at position 5: b_n \̲c̲l̲a̲s̲s̲{in}{\in} {0,1} para n=1,,Nn = 1 , \dots , N.

Para o conjunto de dados clássico X\mathscr{X} descrito acima, para usar a codificação de base, cada ponto de dados deve ser uma string de NN bits: x(m)=(b1,b2,...,bN)x^{(m)} = (b_1, b_2, ... , b_N ), que pode ser mapeado diretamente para o estado quântico xm=b1,b2,...,bN|x^{m}\rangle = |b_1, b_2, ... , b_N \rangle com bn0,1b_n \in {0, 1 } para n=1,...,Nn = 1, ..., N e m=1,...,Mm = 1, ..., M. Podemos representar todo o conjunto de dados como superposições de estados de base computacional:

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{_ket-dataset}{…

Codificação de base

q-statevector-binary-encoding p Add/remove bit strings to/from our input dataset on the left to see how basis encoding encodes this in the state vector on the right.

No Qiskit, uma vez que calculamos qual estado irá codificar nosso conjunto de dados, podemos usar a função initialize para prepará-lo. Por exemplo, o conjunto de dados X=x(1)=101,x(2)=111\mathscr{X} = {x^{(1)}=101, x^{(2)}=111} é codificado como o estado X= frac12(101+111)|\mathscr{X}\rangle= \ frac{1}{\sqrt{2}}(|101\rangle+|111\rangle):

import math from qiskit import QuantumCircuit desired_state = [ 0, 0, 0, 0, 0, 1 / math.sqrt(2), 0, 1 / math.sqrt(2)] qc = QuantumCircuit(3) qc.initialize(desired_state, [0,1,2]) qc.decompose().decompose().decompose().decompose().decompose().draw()
Image in a Jupyter notebook

Este exemplo ilustra algumas desvantagens da codificação de base. Embora seja simples de entender, os vetores de estado podem se tornar bastante esparsos e os esquemas para implementá-lo geralmente não são eficientes.

Codificação de amplitude

A codificação de amplitude codifica dados nas amplitudes de um estado quântico. Ela representa um ponto de dados NN-dimensional clássico normalizado, xx, como as amplitudes de um estado quântico de nn qubits, ψx|\psi_x\rangle: ψx=i=1Nxii|\psi_x\rangle = \sum_{i= 1}^N x_i |i\rangle onde N=2nN = 2^n, xix_i é o elemento ithi^{th} de xx e i|i\rangle é o ithi^{ th} estado da base computacional.

Para codificar o conjunto de dados clássico X\mathscr{X} descrito acima, concatenamos todos os pontos de dados MM NN-dimensionais em um vetor de amplitude, de comprimento N×MN \times M: ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 8: \alpha=\̲c̲s̲s̲I̲d̲{ *a -norm}{A* … onde AnormA_{\text{norm}} é uma constante de normalização, tal que α2=1|\alpha|^2 = 1. O conjunto de dados X\mathscr{X} agora pode ser representado na base computacional como: X=i=1Nαii|\mathscr{X}\rangle = \sum_{i=1}^N \alpha_i |i\rangle onde  alphai\ alpha_i são elementos do vetor de amplitudes e i|i\rangle são os estados da base computacional. O número de amplitudes a serem codificadas é N×MN \times M. Como um sistema de nn qubits fornece 2n2^n amplitudes, a incorporação de amplitude requer nlog2(NM)n \ge \mathrm{log}_2(NM) qubits.

Codificação de amplitude

q-statevector-amplitude-encoding p Change the values of the datapoints on the left, and see how amplitude encoding encodes these as a state vector on the right.

Como exemplo, vamos codificar o conjunto de dados X=x(1)=(1.5,0),x(2)=(2,3)\mathscr{X}= {x^{(1)}=(1.5,0), x^{(2)}=(-2,3)} usando codificação de amplitude. Concatenando os dois pontos de dados e normalizando o vetor resultante, obtemos: α=115.25(1.5,0,2,3)\alpha = \frac{1}{\sqrt{15.25}}(1.5,0,-2,3) e o estado quântico de 2 qubits resultante seria: X=115.25(1.500210+311)|\mathscr{X}\rangle = \frac{1}{\sqrt{15.25}}(1.5|00\rangle-2|10\rangle+3|11\rangle)

No exemplo acima, o número total de elementos do vetor amplitude, N×MN \times M, é uma potência de 2. Quando N×MN \times M não é uma potência de 2, podemos simplesmente escolher um valor para n n tal que 2nMN2^n\geq MN e preencher o vetor amplitude com constantes pouco informativas.

Tal como na codificação de base, uma vez calculado qual o estado que codifica nosso conjunto de dados, podemos usar a função initialize no Qiskit para prepará-lo:

desired_state = [ 1 / math.sqrt(15.25) * 1.5, 0, 1 / math.sqrt(15.25) * -2, 1 / math.sqrt(15.25) * 3] qc = QuantumCircuit(2) qc.initialize(desired_state, [0,1]) qc.decompose().decompose().decompose().decompose().decompose().draw()
Image in a Jupyter notebook

A vantagem da codificação de amplitude é que ela requer apenas log2(NM)\mathrm{log}_2(NM) qubits para codificar. No entanto, algoritmos subsequentes devem operar nas amplitudes de um estado quântico, e os métodos para preparar e medir os estados quânticos tendem a não ser eficientes.

Codificação de ângulo

A codificação de ângulo codifica NN recursos nos ângulos de rotação de nn qubits, onde NnN \le n. Por exemplo, o ponto de dados x=(x1,...,xN)x = (x_1,...,x_N) pode ser codificado como: ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{_}{|x\rangle} …

Isso é diferente dos dois métodos de codificação anteriores, pois codifica apenas um ponto de dados por vez, em vez de um conjunto de dados inteiro. No entanto, ele usa apenas N N qubits e um circuito quântico de profundidade constante, tornando-o receptivo ao hardware quântico atual.

Podemos especificar a codificação de ângulo como uma unitária : ParseError: KaTeX parse error: Undefined control sequence: \class at position 12: S_{x_j} = \̲c̲l̲a̲s̲s̲{ *big-o-times-…

onde:

U(xj(i))=[cos(xj(i))amp;sin(xj(i)) sin(xj(i))amp;cos(xj(i)) ]U(x_j^{(i)}) = \begin{bmatrix} \cos(x_j^{(i)}) & -\sin(x_j^{(i)}) \ \sin(x_j^{(i)}) & \cos(x_j^{(i)}) \ \end{bmatrix}

Lembrando que uma rotação de um único qubit em torno do eixo YY é: RY(θ)=exp(iθ2Y)=(cos fracθ2amp;sinθ2 sinθ2amp;cosθ2)RY(\theta) = \exp(-i \frac{\theta}{2} Y) = \begin{pmatrix} \cos{\ frac{\theta}{2}} & -\sin{\frac{\theta}{2}} \ \sin{\frac{\theta}{2}} & \cos{\frac{\theta}{2 }} \end{pmatrix}

Notamos que U(xj(i))=RY(2xj(i))U(x_j^{(i)}) = RY(2x_j^{(i)}), e como exemplo, codificamos o ponto de dados x=(0,π/4,π/2)x = (0, \pi/4, \pi/2 ) usando o qiskit:

qc = QuantumCircuit(3) qc.ry(0, 0) qc.ry(math.pi/4, 1) qc.ry(math.pi/2, 2) qc.draw()
Image in a Jupyter notebook

A codificação de ângulo denso é uma ligeira generalização da codificação de ângulo, que codifica dois recursos por qubit usando a fase relativa, onde o ponto de dados x=(x1,...,xN)x = (x_1,...,x_N) pode ser codificado como: ParseError: KaTeX parse error: Undefined control sequence: \class at position 13: |x\rangle = \̲c̲l̲a̲s̲s̲{ *big-o-times-…

Embora a codificação de ângulo e ângulo denso usem sinusóides e exponenciais, não há nada de especial sobre essas funções, e podemos facilmente abstraí-las para uma classe geral de codificações de qubit que usam funções arbitrárias ou definem as codificações como unidades arbitrárias, implementadas como circuitos quânticos parametrizados

Codificação arbitrária

A codificação arbitrária codifica NN recursos como rotações em NN portas lógicas parametrizadas em nn qubits, onde nNn \leq N. Tal como a codificação de ângulo, esta codifica apenas um ponto de dados de cada vez, em vez de um conjunto de dados inteiro. Esta codificação também usa um circuito quântico de profundidade constante e nNn \leq N qubits, o que significa que pode ser executada no hardware quântico atual.

Por exemplo, usar o circuito do Qiskit EfficientSU2 para codificar 12 recursos, necessita apenas de 3 qubits:

from qiskit.circuit.library import EfficientSU2 circuit = EfficientSU2(num_qubits=3, reps=1, insert_barriers=True) circuit.decompose().draw()
Image in a Jupyter notebook

Aqui codificamos o ponto de dados x=[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2]x = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2] com 12 recursos, usando cada uma das portas parametrizadas para codificar uma recurso diferente.

x = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2] encode = circuit.bind_parameters(x) encode.decompose().draw()
Image in a Jupyter notebook

O circuito Qiskit ZZFeatureMap com 3 qubits, codifica apenas um ponto de dados de 3 recursos, apesar de possuir 6 portas parametrizadas:

from qiskit.circuit.library import ZZFeatureMap circuit = ZZFeatureMap(3, reps=1, insert_barriers=True) circuit.decompose().draw()
Image in a Jupyter notebook
x = [0.1, 0.2, 0.3] encode = circuit.bind_parameters(x) encode.decompose().draw()
Image in a Jupyter notebook

Questionário rápido

Um circuito quântico parametrizado possui 16 parâmetros. Qual é o maior número de recursos que ele pode codificar?

  1. 4

  1. 8

  1. 16

  1. 32

O desempenho de diferentes circuitos quânticos parametrizados em diferentes tipos de dados é uma área ativa de investigação.

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{big-o-times}{\…

Referências

  1. Maria Schuld and Francesco Petruccione, Supervised Learning with Quantum Computers, Springer 2018, doi:10.1007/978-3-319-96424-9.

  2. Ryan LaRose and Brian Coyle, Robust data encodings for quantum classifiers, Physical Review A 102, 032420 (2020), doi:10.1103/PhysRevA.102.032420, arXiv:2003.01695.

import qiskit.tools.jupyter %qiskit_version_table
/usr/local/anaconda3/lib/python3.7/site-packages/qiskit/aqua/__init__.py:86: DeprecationWarning: The package qiskit.aqua is deprecated. It was moved/refactored to qiskit-terra For more information see <https://github.com/Qiskit/qiskit-aqua/blob/main/README.md#migration-guide> warn_package('aqua', 'qiskit-terra')