动态

详情 返回 返回

量子機器學習入門:三種數據編碼方法對比與應用 - 动态 详情

在傳統機器學習中數據編碼確實相對直觀:獨熱編碼處理類別變量,標準化調整數值範圍,然後直接輸入模型訓練。整個過程更像是數據清洗,而非核心算法組件。

量子機器學習的編碼完全是另一回事。

傳統算法可以直接消化特徵向量 [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個。

但這種壓縮有個硬性要求:Σ|αᵢ|² = 1,保證量子態的有效性。你的特徵向量必須先歸一化為單位長度。與角度編碼直接映射不同,振幅編碼需要複雜的數學預處理,把經典向量轉換成概率幅。

這種指數壓縮帶來了獨特的量子現象。特徵不再獨立它們存在於疊加態中,測量任何量子比特都會影響整個系統狀態。這讓量子算法能處理傳統算法難以應對的特徵相關性和高維模式,但也讓編碼的實現和理解變得複雜得多。

振幅編碼面臨兩個角度編碼沒有的難題:歸一化複雜性和電路深度問題。

歸一化這步看起來簡單,實際上很要命。你的特徵向量必須滿足 Σ|αᵢ|² = 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

user avatar fengdudeyema 头像 cryptorzz 头像 ponponon 头像 wenzhibinbinderiguangdeng 头像 user_p8ybhj2y 头像 jueqiangderijiben_xuc2 头像
点赞 6 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.