在傳統機器學習中數據編碼確實相對直觀:獨熱編碼處理類別變量,標準化調整數值范圍,然后直接輸入模型訓練。整個過程更像是數據清洗,而非核心算法組件。
量子機器學習的編碼完全是另一回事。
傳統算法可以直接消化特征向量[0.7, 1.2, -0.3],但量子電路運行在概率幅和量子態的數學空間里。你的每個編碼決策——是用角度旋轉、振幅映射還是基態表示——都在重新定義信息在量子系統中的存在形式。這不是簡單的格式轉換,而是從根本上塑造了量子算法能夠"看到"和處理的數據結 構。
在量子機器學習中,編碼不是預處理,而是算法設計的核心。
![]()
本文我們會詳細講解量子數據編碼的三種主要方法,分析它們與傳統方法的區別,以及為什么選對編碼方式會決定你的量子模型成敗。
量子編碼的底層邏輯
量子電路處理數據的方式和傳統算法截然不同,即使是在普通電腦上模擬運行也是如此。你沒法直接把數值列表或者歸一化向量塞給量子電路。數據必須先編碼成量子態——這些數學對象可以模擬疊加和糾纏行為。這個編碼過程就是連接經典數據集和量子計算環境的橋梁,讓我們能在本地機器上做量子機器學習實驗。
量子電路運行在一個完全不同的計算空間里。它們操作的是量子態,這些數學對象存在于疊加狀態中,可以在多個量子比特之間形成糾纏,測量時會發生坍縮。量子電路處理不了2.3這樣的普通數字,因為量子門操作的是概率幅和相位關系,不是經典的標量。
![]()
編碼方法的選擇從根本上決定了量子模型能學到什么。基礎編碼把數據直接映射成二進制量子態,實現簡單但表達能力有限。振幅編碼把整個數據集壓縮進量子態的振幅里,效率很高但需要復雜的歸一化處理。角度編碼用量子門根據數據值旋轉量子比特,在簡單性和功能性之間找到了平衡點。
這個選擇不只影響準確率,還決定了電路深度、量子比特需求,以及模型能利用哪些量子現象。選錯了編碼方式,即使是理論上有優勢的量子算法也可能跑不過經典基線。
角度編碼:最直觀的映射方式
角度編碼是把經典特征轉換為量子態最直接的方法。每個特征值變成一個旋轉角度,作用在對應的量子比特上。通常用RY門(繞Y軸旋轉),因為它能讓量子比特在Bloch球面的Y軸上旋轉。
對于特征向量x = [x?, x?, …, x?],角度編碼的操作是:第一個量子比特RY(x?)|0? → cos(x?/2)|0? + sin(x?/2)|1?,第二個量子比特RY(x?)|0? → cos(x?/2)|0? + sin(x?/2)|1?,以此類推。
旋轉角度直接控制量子比特在Bloch球面上的位置。角度0保持量子比特在|0?狀態,π/2創建等權疊加(|0? + |1?)/√2,π翻轉到|1?狀態。這種幾何解釋讓角度編碼很好理解——每個特征實際上在旋轉對應的量子比特,把信息編碼在量子態的幾何結構里。
用Qiskit實現角度編碼很簡單。每個特征通過一個RY門處理,作用在獨立的量子比特上:
from qiskit import QuantumCircuit
import numpy as np
class AngleEncoder:
def __init__(self, num_features):
self.num_features = num_features
def encode(self, features):
"""Encode a single feature vector into a quantum circuit."""
qc = QuantumCircuit(self.num_features)
for i, x in enumerate(features):
qc.ry(x, i)
return qc
處理批量樣本只需要遍歷數據集:
def batch_encode(encoder, data):
circuits = []
for features in data:
circuits.append(encoder.encode(features))
return circuits
想看編碼后的量子態,Qiskit提供了可視化工具:
from qiskit.visualization import plot_bloch_multivector
from qiskit.quantum_info import Statevector
features = [np.pi/4, np.pi/2]
qc = AngleEncoder(len(features)).encode(features)
state = Statevector.from_instruction(qc)
plot_bloch_multivector(state)
這會在Bloch球面上畫出每個量子比特的狀態,讓你直觀看到數據是怎么嵌入的。
![]()
角度編碼的優勢很明顯:特征到量子比特的映射很直接,適用于任何連續數據。但限制也不少,每個量子比特只能編碼一個特征作為單個角度,表達能力有限。每個特征只影響一個量子比特,所以多特征之間的交互沒法自然表示出來,也抓不到特征間的相關性。擴展到高維數據時需要很多量子比特這在實際應用中是個大問題。
振幅編碼:量子優勢的體現
振幅編碼真正展現了量子計算的指數優勢。它不是給每個特征分配一個量子比特,而是把整個特征向量壓縮到量子態的振幅里。
比如特征向量x = [x?, x?, x?, x?],振幅編碼會創建量子態|ψ? = α?|00? + α?|01? + α?|10? + α?|11?,每個α?對應一個歸一化的特征值。這里的關鍵是指數信息密度:n個特征只需要log?(n)個量子比特。256個特征的向量只要8個量子比特就夠了,而角度編碼需要256個。
但這種壓縮有個硬性要求:Σ|α?|2 = 1,保證量子態的有效性。你的特征向量必須先歸一化為單位長度。與角度編碼直接映射不同,振幅編碼需要復雜的數學預處理,把經典向量轉換成概率幅。
這種指數壓縮帶來了獨特的量子現象。特征不再獨立它們存在于疊加態中,測量任何量子比特都會影響整個系統狀態。這讓量子算法能處理傳統算法難以應對的特征相關性和高維模式,但也讓編碼的實現和理解變得復雜得多。
振幅編碼面臨兩個角度編碼沒有的難題:歸一化復雜性和電路深度問題。
歸一化這步看起來簡單,實際上很要命。你的特征向量必須滿足Σ|α?|2 = 1,這直接影響模型對數據關系的解釋。用L2歸一化、先做min-max縮放再歸一化,或者基于概率的歸一化,對同一份經典數據會產生完全不同的量子表示。
負特征值更麻煩。量子概率幅可以是復數,但實現復振幅編碼需要額外的量子比特或者復雜的相位編碼。很多實際應用把振幅限制為實數,如果你的特征有重要的負值信息,就可能丟失關鍵信息。
電路深度是另一個坑。創建任意振幅狀態需要復雜的量子電路,不像角度編碼每個特征用一個RY門就完事。振幅編碼需要一串受控旋轉、受控NOT門,還要輔助量子比特。電路深度隨特征數量對數增長,實現起來相當復雜。
![]()
用Qiskit的initialize方法可以直接在量子比特上設置振幅:
from qiskit import QuantumCircuit
class AmplitudeEncoder:
def __init__(self, num_qubits):
self.num_qubits = num_qubits
def encode(self, features):
"""Encode normalized feature vector into quantum circuit."""
qc = QuantumCircuit(self.num_qubits)
qc.initialize(features, qc.qubits)
return qc
處理任意長度的數據集,需要結合歸一化:
def encode_vector(vector):
vec = normalize(vector)
num_qubits = int(np.ceil(np.log2(len(vec))))
# Pad vector to length 2^num_qubits
pad_len = 2**num_qubits - len(vec)
padded = np.append(vec, [0]*pad_len)
return AmplitudeEncoder(num_qubits).encode(padded)
這樣就能處理任意長度的向量,編碼器會自動填充到最近的2的冪次。
基礎編碼:簡單高效的離散表示
基礎編碼把分類數據直接映射到計算基礎狀態∣0?和∣1?。它不依賴疊加或干涉,而是用不同的正交狀態表示不同類別,測量時能完美區分。
這創建了經典標簽和二進制量子態的一對一映射。2量子比特系統有四個基礎狀態:∣00?,∣01?,∣10?,∣11?,可以表示四個類別。編碼就是把分類標簽轉成二進制,然后初始化量子比特匹配這個二進制模式。類別"A"可能對應∣00?,類別"B"對應∣01?,測量時能100%確定地恢復原類別。
數學上很優雅:n個類別只需要 [log?(n)] 個量子比特,對離散數據非常高效。
Qiskit實現基礎編碼很直接,把量子比特準備到對應的基礎狀態:
class BasisEncoder:
def __init__(self, num_qubits):
self.num_qubits = num_qubits
def encode(self, binary_string):
"""Prepare qubits in basis state from a binary string."""
qc = QuantumCircuit(self.num_qubits)
for i, bit in enumerate(binary_string):
if bit == "1":
qc.x(i) # Apply X gate to flip |0? → |1?
return qc
多類問題可以把整數標簽映射成二進制字符串:
def int_to_basis(n, num_qubits):
return format(n, f"0{num_qubits}b")
encoder = BasisEncoder(3)
qc = encoder.encode(int_to_basis(5, 3)) # Encodes integer 5 as |101?
基礎編碼對分類變量很合適,但處理連續或高維數據就效率太低了。編碼大數據集會消耗太多量子比特,不實用。對數值特征,角度或振幅編碼是更好的選擇。
如何選擇編碼方式
選擇哪種編碼方式主要看你的具體需求。
如果你在學習量子機器學習基礎,特征之間相對獨立,需要簡單易懂的電路,或者在NISQ設備上工作,角度編碼是最好的起點。
如果你有高維連續數據,特征相關性很重要,能接受電路復雜度,想要最大化量子優勢,振幅編碼更合適。
如果數據主要是分類或離散的,需要完美的可解釋性,要求最小電路深度,處理的是分類問題,基礎編碼是理想選擇。
量子數據編碼不只是預處理步驟,它從根本上定義了量子模型能學到什么、怎么學。選對編碼方式,你的量子算法就有了成功的基礎;選錯了,再先進的量子算法也可能表現平平。
https://avoid.overfit.cn/post/460fd17cca6647cb886c14d61180e73a
作者:Aadish Parate
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.