Introduzione all' Machine Learning quantistico
Panoramica e motivazione
Benvenuti nell'apprendimento automatico quantistico!
Il video che segue fornisce una breve introduzione, integrata dal testo che segue.
Per ricapitolare brevemente e integrare il video:
- Abbiamo visto risolvere un problema per la prima volta su un computer quantistico e poi trovare un modo per farlo su un supercomputer classico. Questo ciclo di calcolo classico e quantistico che si spingono l'un l'altro verso i propri limiti continuerà probabilmente per alcuni anni.
- Esistono problemi specifici in cui l'informatica quantistica può avere un vantaggio dimostrabile rispetto all'informatica classica, dati i progressi compiuti in aree quali la riduzione degli errori e il numero di qubit disponibili. Ma questo è ancora un momento di esplorazione, alla ricerca di insiemi di dati quantistici e di mappe di caratteristiche quantistiche utili.
- L'apprendimento automatico quantistico (QML) è una delle tante aree interessanti in cui l'informatica quantistica può aumentare o integrare i flussi di lavoro classici esistenti.
L'apprendimento automatico (ML) applica algoritmi a insiemi di dati, e quindi il QML potrebbe plausibilmente includere la meccanica quantistica sia nei dati che negli algoritmi, o in entrambi. Tutte queste possibilità sono potenzialmente interessanti. Ma ci limiteremo soprattutto a discutere di algoritmi quantistici applicati a dati classici. Uno dei motivi è che i problemi di ML con i dati classici sono già così ben studiati e ampiamente disponibili. Esiste un ampio interesse per la soluzione di problemi che partono da dati classici. Un altro motivo è la mancanza di QRAM. Senza la capacità di immagazzinare grandi quantità di dati quantistici su una scala temporale relativamente lunga, i metodi che iniziano con i dati quantistici sono ancora piuttosto lontani dall'applicabilità all'industria. Inoltre, non è chiaro come "accedere quantisticamente" ai dati classici in modo efficiente. Due tipi di ML di particolare interesse sono l'apprendimento supervisionato, in cui si addestra un algoritmo utilizzando un insieme di dati etichettati, e l'apprendimento non supervisionato, in cui l'algoritmo tenta di apprendere una distribuzione da campioni non etichettati. Un algoritmo non supervisionato potrebbe, ad esempio, imparare a generare nuovi campioni dalla stessa distribuzione o a raggruppare i campioni in gruppi con caratteristiche simili.
L'immagine a sinistra mostra due categorie di dati etichettati come nell'apprendimento supervisionato. In questo caso, le categorie sono linearmente separabili. L'immagine a destra mostra dei cluster di dati. In un'attività di apprendimento non supervisionato, questi dati non sarebbero inizialmente etichettati e l'algoritmo studierebbe la distribuzione, magari cercando dei cluster. Al fine di visualizzare i cluster di esempio che l'algoritmo potrebbe identificare, i punti dati sono stati ora etichettati. Una differenza fondamentale tra i due è che il processo di apprendimento supervisionato inizia con dati già etichettati, mentre quello non supervisionato inizia con dati non etichettati, anche se alla fine i dati vengono etichettati.
Chi ha un background nell'apprendimento automatico saprà già che molti metodi risolutivi comportano la mappatura dei dati in spazi più dimensionali. Questo aspetto è particolarmente ben esplorato nel contesto dei kernel. Come breve promemoria, a volte i dati possono essere separati in categorie da una linea, un piano o un iperpiano (spesso diremo semplicemente "iperpiano" per compattezza), nello stesso numero di dimensioni in cui sono dati i dati. Questo è mostrato nella prima immagine qui sopra. Altre volte, i dati possono non essere separabili da un iperpiano in quelle dimensioni, come mostrato nella seconda immagine. Ma i dati possono ancora presentare una struttura che può essere sfruttata in una mappatura a dimensioni superiori, che lascia i dati separabili in quello spazio a più alte dimensioni. Ciò è illustrato nella mappatura dei dati 2D con simmetria circolare nello spazio 3D in cui i punti dei dati sono disposti lungo una superficie paraboloide.
Un obiettivo comune in QML è quello di trovare una mappatura dall'insieme di caratteristiche a bassa dimensione in uno spazio a più alta dimensione, che separi efficacemente i nostri punti di dati in modo da poter utilizzare la mappatura per classificare nuovi punti di dati. Ma non si tratta di un compito facile e qualsiasi discussione sulla potenziale utilità dell'informatica quantistica nell'apprendimento automatico deve essere accompagnata dagli opportuni avvertimenti. In particolare, dobbiamo affrontare le sfumature nella selezione dei set di dati e le sfide per raggiungere la scala di utilità. Dobbiamo anche abbandonare il tentativo di superare le prestazioni degli algoritmi di ML classici su dati che sono già gestiti in modo efficiente e corretto dagli algoritmi classici e concentrare la discussione sullo studio di nuove mappe di caratteristiche che potrebbero essere utili.
Gestire le aspettative
Molti set di dati utilizzati nelle applicazioni QML descritte in letteratura sono "feature engineered", ovvero un set di dati viene selezionato o generato appositamente per mostrare un caso d'uso ristretto in cui il calcolo quantistico è utile. Se questo sembra un imbroglio, allora stiamo fraintendendo il compito da svolgere. Non è detto che alcune mappe di caratteristiche quantistiche ci permettano di risolvere tutti o molti compiti di classificazione in modo più efficiente o scalabile rispetto agli algoritmi di apprendimento automatico classici. Piuttosto, alcune mappe di caratteristiche quantistiche (non tutte) si comportano in modo diverso dalle mappe di caratteristiche classiche. Si tratta quindi di esplorare i circuiti quantistici nel contesto di strutture dati complesse. Alcune domande specifiche da affrontare sono:
- Quali circuiti quantistici hanno maggiori probabilità di comportarsi in modo nuovo rispetto alle alternative classiche?
- Esistono problemi del mondo reale che coinvolgono dati con proprietà che possono essere esplorate al meglio utilizzando questi nuovi circuiti quantistici?
- Questi circuiti quantistici sono scalabili sui computer quantistici di prossima generazione?
Spiegazione insufficiente
Spesso ci si imbatte in una spiegazione semplificata di come l'informatica quantistica possa essere potente. La frase è più o meno la stessa:
Così come i computer classici utilizzano bit di informazione, i computer quantistici utilizzano qubit. Dato un numero di bit, ad esempio 4, un computer classico può assumere uno qualsiasi dei stati possibili, mentre un computer quantistico può esistere in una sovrapposizione di tutti i 16 stati simultaneamente, e le operazioni possono essere eseguite su questa intera sovrapposizione. In alcuni casi, questo ci permette naturalmente di progettare algoritmi di apprendimento potenzialmente interessanti, basati su mappature in spazi di dimensioni superiori.
È un'affermazione vera, ma inadeguata e un po' fuorviante, come spiegheremo. Si possono anche sottolineare le differenze tra coefficienti complessi e reali, come nel caso di:
Un sistema classico probabilistico, in cui un sistema può essere descritto come avente determinate probabilità di trovarsi in stati diversi, può essere descritto come segue.
In un sistema di questo tipo, i coefficienti , , , e così via, possono essere significativi solo se sono numeri reali positivi. Gli stati nei computer quantistici sono descritti da ampiezze di probabilità che possono essere numeri complessi.
Le affermazioni di cui sopra sono state fatte con molta attenzione in modo che siano vere (molte affermazioni superficialmente simili sono errate). Ma queste affermazioni corrette non spiegano la potenza del calcolo quantistico nell'apprendimento automatico. Innanzitutto, qualsiasi applicazione dell'informatica quantistica all'apprendimento automatico comporterà delle misurazioni e non possiamo misurare un qubit che si trovi in più stati contemporaneamente. Possiamo preparare un qubit in una superposizione come ma una misurazione produrrà o o . Quindi, come minimo, questa storia dell'aumento della dimensionalità è incompleta. Inoltre, nel contesto dei kernel, l'aumento delle dimensioni nell'informatica quantistica non può essere una condizione sufficiente per la potenza di calcolo rispetto alle alternative classiche, poiché i kernel gaussiani sono infinitamente dimensionali. Ci sono delle sottigliezze, in quanto le mappe di caratteristiche gaussiane sono utilizzate solo in combinazione con il "trucco del kernel" che evita la necessità di calcolare un vettore mappato infinito. Ma il punto rimane:
L'alta dimensionalità degli stati quantistici entangled non è un parallelismo esponenziale e non è una condizione sufficiente per aumentare la potenza dell'apprendimento automatico.
Nelle lezioni che seguono, presentiamo i flussi di lavoro per incorporare i circuiti quantistici nelle attività di apprendimento automatico, con l'obiettivo esplicito di facilitare l'esplorazione della potenza del calcolo quantistico. In questo corso, nessuna mappa di caratteristiche o algoritmo viene presentata come un percorso rapido per ottenere risultati migliori nell'apprendimento automatico per problemi generali, perché non esistono mappe di caratteristiche o algoritmi di questo tipo. Piuttosto, presentiamo un'ampia gamma di strumenti quantistici da utilizzare nell'esplorazione dell'informatica quantistica utile.
Dequantizzazione
La dequantizzazione si riferisce alla sostituzione di un determinato algoritmo quantistico con uno classico che ha prestazioni simili a quelle dell'algoritmo quantistico per un determinato insieme di compiti, in genere compreso lo scaling. Secondo alcune definizioni, l'algoritmo classico dovrebbe funzionare solo polinomialmente più lentamente dell'algoritmo quantistico.
Negli ultimi anni sono stati dequantizzati diversi algoritmi di apprendimento automatico quantistico (QML) che inizialmente si pensava potessero fornire significativi incrementi di velocità rispetto agli algoritmi classici. Questo processo di dequantizzazione ha portato a importanti intuizioni sui potenziali vantaggi e limiti degli approcci quantistici all'apprendimento automatico.
Uno dei risultati più notevoli in materia di dequantizzazione è stato il lavoro di Ewin Tang sui sistemi di raccomandazione. Tang ha scoperto un algoritmo classico in grado di eseguire attività di raccomandazione a velocità che in precedenza si pensava fossero raggiungibili solo dai computer quantistici. Questa scoperta ha messo in discussione l'ipotesi che gli algoritmi quantistici avessero un vantaggio esponenziale per questo problema. Un lavoro più recente di Shin et al. si è concentrato sull'identificazione delle condizioni di dequantizzabilità della classe di funzioni di un modello di apprendimento quantistico variazionale.
Un approccio comune alla dequantizzazione (anche se non è l'unico) consiste nel considerare l'overhead del caricamento dei dati. In altre parole, qualsiasi algoritmo quantistico applicato ai dati classici prevede una fase in cui i dati classici vengono codificati nel computer quantistico. Se un algoritmo quantistico presuppone un punto di partenza in cui i dati quantistici sono già disponibili, allora si nasconde efficacemente il tempo necessario per la codifica. Ci sono contesti in cui assumere dati quantistici può essere ragionevole, ma molte applicazioni di interesse inizieranno con dati classici. Alcuni casi di dequantizzazione hanno dimostrato che quando questo tempo di codifica è incluso, e quando il caricamento dei dati classici può essere realizzato in modo efficiente, l'algoritmo quantistico non supera più la sua controparte classica.
Anche se un algoritmo non può essere dequantizzato, ciò non significa che sia più efficiente o scalabile di tutti gli algoritmi classici. Un esempio estremo e artificioso: immaginiamo un algoritmo per selezionare gli elementi più grandi di j da un insieme di dimensioni k. Si potrebbe scrivere un algoritmo quantistico che utilizzi l'algoritmo di Shor per fattorizzare ciascuno dei k elementi in fattori primi, e quindi determinare gli elementi più grandi utilizzando i fattori primi. Un algoritmo di questo tipo probabilmente non può essere dequantizzato, ma è drasticamente meno efficiente degli algoritmi classici per ottenere la stessa selezione degli elementi più grandi (ma non la parte di fattorizzazione non necessaria).
Prova di esistenza
Nel 2021, i ricercatori di IBM Quantum® Yunchao Liu, Srinivasan Arunachalam e Kristan Temme hanno pubblicato un articolo su Nature, A rigorous and robust quantum speed-up in supervised machine learning Coerentemente con le avvertenze di cui sopra, per questo lavoro è stato scelto con cura un problema di classificazione che (1) è noto per essere classicamente difficile e (2) è adatto agli algoritmi quantistici per mostrare un aumento di velocità.
Il documento affronta la classificazione dei dati basata sui logaritmi discreti. Citando il documento, "Per un grande numero primo e un generatore di , è una congettura ampiamente accreditata che nessun algoritmo classico può calcolare su input , in tempo polinomiale in , il numero di bit necessari per rappresentare " È invece noto che l' algoritmo di Shor risolve il problema del log discreto in tempo polinomiale. Questa scelta di problemi soddisfa quindi contemporaneamente i criteri di cui sopra: durezza classica (improbabile dequantizzazione) e notoriamente adatta agli algoritmi quantistici.
Grazie a questa scelta oculata del problema di classificazione, gli autori sono stati in grado di dimostrare una velocità esponenziale utilizzando i metodi dei kernel quantistici (abbozzati di seguito e discussi nelle lezioni successive) che sono sia end-to-end che robusti. In questo caso, "end-to end" si riferisce alle ipotesi di partenza con dati classici; gli autori in questo caso includono il tempo per la codifica dei dati. In questo caso, "robusto" si riferisce al fatto che i dati da classificare sono separati da un ampio margine utilizzando l'algoritmo quantistico, in modo che il successo della classificazione sia robusto a considerazioni del mondo reale come l'errore di campionamento finito.
Tutto questo per dire che esistono problemi in cui i kernel quantistici possono produrre un aumento esponenziale della velocità. Tuttavia, allo stato attuale della scienza, tali problemi vengono selezionati sulla base di osservazioni o di una giustificazione teorica che li renda adatti agli algoritmi quantistici. Non è realistico aspettarsi una velocità quantistica per compiti di apprendimento automatico che i computer classici svolgono già abbastanza bene.
Identificare questi casi ideali per l'esplorazione dell'utilità quantistica è un'enorme responsabilità per gli studenti di questo corso. E non è un compito che si può svolgere in un corso come questo. Questa esplorazione è un compito che spetta alla Rete Quantistica IBM nel suo complesso, composta da ricercatori come lei. Il corso illustra i flussi di lavoro e le strategie di codifica QML in modo che possiate iniziare a esplorare l'utilità quantistica nella vostra area di competenza.
Speriamo che questa introduzione abbia chiarito alcune cose sull'apprendimento automatico quantistico:
- Gli algoritmi quantistici possono offrire una velocità esponenziale rispetto agli algoritmi classici per problemi molto specifici che sono classicamente difficili e ben adatti agli algoritmi quantistici.
- L'alta dimensionalità degli stati entangled nell'informatica quantistica è importante, ma non è sufficiente per ottenere un vantaggio sugli algoritmi classici.
- Trovare problemi adatti agli algoritmi quantistici è un compito estremamente difficile, che spetterà in gran parte agli studenti di questo corso.
Domande al check-in
Cosa rende gli stati quantistici diversi da quelli classici?
Molto. In particolare: coefficienti complessi e sovrapposizione con una singola copia. Ci sono molte altre differenze che saranno discusse nelle lezioni future, tra cui l'entanglement e l'interferenza.
Vero o falso? Gli stati quantistici altamente entangled ci permettono di risolvere la maggior parte dei problemi di apprendimento automatico in modo più efficiente su un computer quantistico.
Falso. La maggior parte dei problemi di apprendimento automatico sono risolti in modo molto efficiente da algoritmi classici e gli algoritmi quantistici non sono in grado di offrire una sostanziale accelerazione. L'obiettivo di QML è trovare insiemi di dati con caratteristiche ben descritte dagli stati quantistici e/o trovare mappature delle caratteristiche dei dati che ottimizzino l'accuratezza dei modelli.
Obiettivi formativi del corso
Completando questo corso, ci si può aspettare di acquisire le seguenti abilità e competenze fondamentali. Gli studenti saranno in grado di:
-
Spiegare cos'è il QML e quali sono i collegamenti tra il quantum e l'apprendimento automatico classico.
-
Applicare il vocabolario quantistico e i termini chiave ai flussi di lavoro ML.
-
Identificare i componenti chiave di un flusso di lavoro QML (vari tipi).
-
Identificare i diversi tipi di QML e distinguerli.
-
Implementare i metodi del kernel quantistico e i classificatori quantistici variazionali utilizzando le primitive di IBM Quantum e seguendo i modelli di Qiskit.
-
Identificare dove il QML è più promettente e dove non lo è.
-
Adattare un problema di esempio al proprio set di dati.
-
Tenere presente i problemi di QML, come il tempo di addestramento, il rumore e l'errore di composizione nelle letture a stati multipli.
-
Formulare raccomandazioni per i casi in cui il QML potrebbe essere utile alla loro organizzazione.
Struttura del corso
Questo corso è composto da diverse lezioni. Ogni lezione è corredata da diverse domande di verifica lungo il testo, in modo da poter mettere in pratica le nuove abilità o verificare la propria comprensione durante il corso della lezione. Non sono necessari.
Alla fine del corso è previsto un quiz di 20 domande. Per ottenere il badge Quantum Machine Learning, tramite Credly, è necessario ottenere un punteggio di almeno il 70% in questo quiz. Se si ottiene un punteggio di almeno il 70%, il badge verrà automaticamente inviato via e-mail poco dopo. È possibile inviare il quiz solo due volte. Dopo il primo invio, si avrà la possibilità di fare un secondo tentativo con le domande mancate. Dopo il secondo invio, il punteggio è definitivo. Per ulteriori dettagli, consultare il quiz.
La struttura del corso è la seguente:
- Lezione 1: Introduzione e panoramica
- Lezione 2: Introduzione all'apprendimento automatico
- Lezione 3: Codifica dei dati
- Lezione 4: Metodi kernel quantistici e macchine vettoriali di supporto
- Lezione 5: Classificatori quantistici variazionali / reti neurali
- Esame per il badge
Esegui il tuo primo codice QML
Spesso è utile vedere dove si va a parare, prima di scomporre il tutto in pezzi e approfondire il background. Le celle di codice riportate di seguito eseguono una semplice istanza di un metodo kernel quantistico. In particolare, viene calcolato un singolo elemento della matrice kernel. Gli utenti che non conoscono i metodi kernel o i kernel quantistici non devono lasciarsi intimidire; diverse lezioni di questo corso saranno dedicate alla disamina di ciò che viene fatto esattamente in queste celle.
Con questo codice introduciamo contemporaneamente i modelli Qiskit: un quadro di riferimento per l'approccio al calcolo quantistico su scala di utilità. Questo schema consiste in quattro fasi che sono molto generali e possono essere applicate alla maggior parte dei problemi (anche se in alcuni flussi di lavoro alcune fasi possono essere iterate più volte).
Modelli Qiskit:
- Fase 1: mappare gli input classici in un problema quantistico
- Fase 2: Ottimizzazione del problema per l'esecuzione quantistica
- Fase 3: Esecuzione tramite le primitive " IBM Quantum "
- Fase 4: analisi / post-elaborazione
Nelle celle che seguono, offriamo solo spiegazioni sommarie dei vari passaggi, quanto basta perché possiate trovare la lezione appropriata per saperne di più.
# Import some qiskit packages required for setting up our quantum circuits.
from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit
from qiskit.circuit.library import unitary_overlap
# Import StatevectorSampler as our sampler.
from qiskit.primitives import StatevectorSampler
# Step 1: Map classical inputs to a quantum problem:
# Start by getting some appropriate data.
# The data imported below consist of 128 rows or data points.
# Each row has 14 columns that correspond to data features, and a 15th column with a label (+/-1).
!wget https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv
# Import some required packages, and write a function to pull some
# training data out of the csv file you got above.
import pandas as pd
import numpy as np
def get_training_data():
"""Read the training data."""
df = pd.read_csv("dataset_graph7.csv", sep=",", header=None)
training_data = df.values[:20, :]
ind = np.argsort(training_data[:, -1])
X_train = training_data[ind][:, :-1]
return X_train
# Prepare training data
X_train = get_training_data()
# Empty kernel matrix
num_samples = np.shape(X_train)[0]
# Prepare feature map for computing overlap between two data points.
# This could be pre-built feature maps like ZZFeatureMap, or a custom quantum circuit,
# as shown here.
num_features = np.shape(X_train)[1]
num_qubits = int(num_features / 2)
entangler_map = [[0, 2], [3, 4], [2, 5], [1, 4], [2, 3], [4, 6]]
fm = QuantumCircuit(num_qubits)
training_param = Parameter("θ")
feature_params = ParameterVector("x", num_qubits * 2)
fm.ry(training_param, fm.qubits)
for cz in entangler_map:
fm.cz(cz[0], cz[1])
for i in range(num_qubits):
fm.rz(-2 * feature_params[2 * i + 1], i)
fm.rx(-2 * feature_params[2 * i], i)
# Pick two data points, here 14 and 19, and assign the features to the circuits as parameters.
x1 = 14
x2 = 19
unitary1 = fm.assign_parameters(list(X_train[x1]) + [np.pi / 2])
unitary2 = fm.assign_parameters(list(X_train[x2]) + [np.pi / 2])
# Create the overlap circuit
overlap_circ = unitary_overlap(unitary1, unitary2)
overlap_circ.measure_all()
overlap_circ.draw("mpl", scale=0.6, style="iqp")
# Step 2: Optimize problem for quantum execution
# Use IBM Quantum Compute Service to get the least busy backend for running on real quantum computers.
# from qiskit_ibm_runtime import QiskitRuntimeService
# service = QiskitRuntimeService(channel="ibm_quantum")
# backend = service.least_busy(
# operational=True, simulator=False, min_num_qubits=overlap_circ.num_qubits
# )
# Transpile the circuits optimally for the chosen backend using a pass manager.
# from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
# pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
# overlap_ibm = pm.run(overlap_circ)
# Step 3: Execute using IBM Quantum primitives
# Specify the number of shots to use.
num_shots = 10_000
## Evaluate the problem using statevector-based primitives from Qiskit
sampler = StatevectorSampler()
counts = (
sampler.run([overlap_circ], shots=num_shots).result()[0].data.meas.get_int_counts()
)
# Step 4: Analyze and post-processing
# Find the probability of 0.
counts.get(0, 0.0) / num_shotsOutput:
--2025-05-09 10:04:28-- https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.109.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 49405 (48K) [text/plain]
Saving to: ‘dataset_graph7.csv.2’
dataset_graph7.csv. 100%[===================>] 48.25K --.-KB/s in 0.03s
2025-05-09 10:04:29 (1.37 MB/s) - ‘dataset_graph7.csv.2’ saved [49405/49405]
0.8199
Anche se non è necessario comprendere tutti i passaggi sopra descritti, dovremmo cercare di capire l'output, in modo da sapere perché lo stiamo facendo. Molti processi di apprendimento automatico utilizzano i prodotti interni come parte della classificazione binaria (tra le altre cose). La meccanica quantistica ha un'ovvia connessione con questo, poiché le probabilità di misurare vari stati sono date dal prodotto interno con uno stato iniziale attraverso il prodotto interno: . Quindi, quello che abbiamo fatto sopra è stato creare un circuito quantistico che contiene le caratteristiche dei nostri due punti dati e le mappa nello spazio di un vettore quantistico, per poi stimare il prodotto interno in quello spazio effettuando delle misurazioni. Questo è un esempio di stima quantistica del kernel. Si noti che abbiamo implementato questo processo solo per due dei punti dati (il 14 e il 19). Se si facesse questo per tutte le coppie possibili, si potrebbe prendere l'output (in questo caso il numero 0.821...) e popolano una matrice di risultati che descrive la sovrapposizione tra tutti i punti del set di dati di addestramento. Questa è la "matrice del kernel".
Verifica la tua comprensione
Nel processo sopra descritto, abbiamo calcolato una voce della matrice kernel per il 14° e il 19° punto di dati. Quale valore dovremmo ottenere se utilizziamo lo stesso punto di dati due volte (come 14° e 14° di nuovo)? In altre parole, quali dovrebbero essere le voci diagonali della matrice kernel? Rispondete a questa domanda in assenza di rumore, ma tenete presente che sono possibili deviazioni dalla vostra risposta in presenza di rumore.
Le diagonali devono essere 1.0. Questo processo dovrebbe calcolare il prodotto interno normalizzato di un vettore con se stesso, che deve essere sempre uno.