KPP 能量模型與採樣
負責 PyTorch 模型與 Kaiwu 採樣器的整合。模型參數、目標函數和優化器留在 PyTorch;透過相容採樣器接入 Kaiwu 求解器或任務已有的採樣流程。不要把普通機器學習任務自動改寫成能量模型任務。
選擇組件
先根據輸入、輸出和需要刻畫的關係選擇結構,說明所選組件如何滿足任務要求。使用者指定結構時按指定結構完成;自行選型時,判斷任務需要觀測變數間的直接關係、隱藏因素、分層表示、潛變數重建、上下文生成還是特徵篩選,再選擇對應組件。模型大小不是預設優先級;先驗證能力與效果是否匹配,再在滿足要求的方案間比較訓練和採樣成本。
| 問題需要的能力 | 組件 | 匹配依據 |
|---|---|---|
| 用隱藏因素解釋觀測模式,或學習可見/隱藏二部結構 | RestrictedBoltzmannMachine | 隱藏表示參與任務所需的分佈學習;僅有二元輸入不足以決定採用 RBM |
| 直接刻畫二元節點的兩兩相互作用,或固定部分節點後採樣 | BoltzmannMachine | 節點及其相互作用對應問題變數;用任務指標驗證是否足以表達所需關係 |
| 通過多層 RBM 學習分層特徵 | UnsupervisedDBN | 任務需要逐層學習的表示,或使用者明確要求 RBM 堆疊 |
| 編碼、重建及可採樣的能量模型潛變數先驗 | QVAE | 重建與潛變數先驗都服務於任務;普通自編碼器不因此改成 QVAE |
| 上下文相關的離散候選生成與能量引導 | QDiffusion | proposal 提供所需上下文,energy 對候選進行任務相關的引導 |
| 從已有 PyTorch 模型的輸入裡選擇特徵子集 | FeatureSelectionWrapper | 任務需要輸入特徵篩選,使用週期更新的 0/1 遮罩 |
二元數據、標籤數量或示例出現的先後順序不能單獨決定選型。用任務要求的關聯、重建、補全或預測等結果驗證選擇;僅導入成功或輸出形狀正確不代表匹配。任務需要高階關係或上下文時,不能僅憑兩兩統計達標就認定模型足夠。BM 與 RBM 的不同訓練結構見 模型範式,只讀當前任務相關的部分。
這是同一 KPP 包的不同組件,無需分別安裝六個插件。特徵選擇雖然內部求解 QUBO,但服務於 PyTorch 模型訓練,屬於本 Skill;純選址、調度、Max-Cut 等不依附模型、直接求最優決策的任務使用 Kaiwu SDK 技能。若同一任務同時包含組合優化與能量訓練,可分別載入兩個技能並使用各自解釋器。
應用任務的最小閉環
- 用代表性數據檢查所選結構的任務效果,並記錄真實訓練與生成的規模、耗時,據此安排正式執行,在總預算中留出模型保存、新進程載入、生成與報告核對的時間。
- 盡早打通題目要求的完整入口。每次驗證後保存當前效果最好且可複用的模型、配置和報告;後續試驗使用新的輸出目錄,交付目錄始終保留可執行版本。
- 批量生成按實際行數累計:追加一批時累加該批的行數,達到請求數量後再截取。先用小請求核對數量、寬度和取值,批數不等於樣本數。
- 分開檢查直接複製原記錄、模型採樣自然重合和人工篩選。常見組合可能在獨立生成中重合;過濾重合記錄或強制唯一會改變分佈,使用後重新核對比例與關聯等業務指標。
- 按任務公開的業務要求驗證,保存模型後在新進程中僅用交付模型和請求輸入重新生成,報告同一次執行的品質與耗時。達到本次目標後完成交付;未達到時保留當前成果並如實說明,繼續嘗試以剩餘預算允許完成上述核對為前提。
檢查、自動安裝、驗證
- 複用使用者指定/項目已有解釋器,核對 Python、
kaiwu-torch-plugin、kaiwu、torch的版本。同一環境執行一次python -m pip check,再執行技能目錄內 scripts/verify_kpp.py 的--imports-only模式。已有本次檢查結果時直接複用,隨後進入任務,不額外掃描環境或試跑通用訓練。 - 缺包時才檢查安裝計劃並安裝;依賴衝突、離線包、Python 版本或 wheel 支援有問題時,按 安裝說明 處理,依據實際元數據選擇相容環境。
- 複用任務提供的相容採樣器。選擇 SDK SA/CIM 時才檢查對應授權,不把 SDK 授權缺失當成所有本地採樣器都不能訓練。授權初始化和非互動限制見安裝說明。
- 用實際任務程式驗證所選模型;沒有任務程式且需要檢查 SDK 採樣訓練時,才執行驗證腳本預設模式。
KPP_IMPORT_OK只證明導入;KPP_TRAIN_OK只證明腳本覆蓋的小規模訓練。
檢查日誌、臨時檔案和驗證副本留在任務目錄,雲端 CIM 僅在任務明確需要且已有配額授權時使用。呼叫 Kaiwu CIM 時,task_name 必須以 kpp-skill 開頭,方便後端統計;例如 kpp-skill-rbm-train。已有任務名不含此前綴時,在其前面加上 kpp-skill-。
訓練與生成契約
BM 與 RBM 的公開導入路徑:
from kaiwu.torch_plugin import BoltzmannMachine, RestrictedBoltzmannMachine
選擇 SDK SA 時,SimulatedAnnealingOptimizer 從 kaiwu.classical 導入。BM 建構使用 BoltzmannMachine(num_nodes, quadratic_coef=None, linear_bias=None, device=None);RBM 使用 RestrictedBoltzmannMachine(num_visible, num_hidden, quadratic_coef=None, linear_bias=None, device=None)。學習率、權重衰減等設置交給 PyTorch 優化器,不向模型建構器傳入 learning_rate、k、batch_size 或其他庫的訓練參數。
- RBM:
get_hidden(batch, bernoulli=True)和sample(sampler)返回可見+隱藏聯合狀態,寬度是num_visible + num_hidden。正相批次與負相解池行數可不同,分別求均值;不硬湊相同樣本數。objective(positive, negative)返回標量。直接寫positive = model.get_hidden(batch, bernoulli=True),不解包返回值,也不再拼接可見層。get_hidden預設bernoulli=False,隱藏部分為機率;用於 RBM 正相期望合法,交付二值聯合樣本時才需bernoulli=True。不要把機率狀態當成已經採出的二值樣本。解池容量按實際採樣器配置,SDK SA 使用SimulatedAnnealingOptimizer(size_limit=...);不編造set_config或給sample增加未定義的num_solutions參數。 - SDK 採樣:
sampler.solve返回含尾部參考自旋的 ±1 二維陣列。KPP 的sample內部完成參考自旋歸一化、刪除尾列、轉成 0/1 浮點張量。對sample返回值不要再刪列或轉換。使用者提供固定測試解時,每次solve原樣返回整組解;不要把各解分配給不同條件,或重複首行湊樣本數。條件採樣須同時核對固定列和每條解轉換後的自由列,不能只檢查形狀。 - 訓練順序:每步
optimizer.zero_grad()→ 正負相 →objective→backward()→step();objective和backward()不能放在torch.no_grad()中。sample()返回的是無梯度的採樣張量,梯度來自objective重新計算能量,sample()是否在no_grad內不影響訓練。模型、數據、手動張量保持同一 device。檢查正負相寬度、負相二值性、損失/梯度有限、參數實際更新。 - BM / DBN:條件採樣用
condition_sample(sampler, s_visible),它固定的總是前s_visible.shape[1]個節點,每個條件行呼叫一次求解器。各行已知位置不同時逐行重排:按「已知在前」置換linear_bias和對稱化後的quadratic_coef,用置換後的參數建臨時BoltzmannMachine呼叫condition_sample,再把列逆置換回原順序。DBN 使用前呼叫create_rbm_layer(input_dim),訓練完成後mark_as_trained()再做forward/transform。 - QVAE:可建構注入 encoder/decoder/bm/sampler,也可子類實現四個
_create_*工廠。config 含num_latent_units / loss_type / dist_beta / kl_beta / weight_decay。伯努利均值校正是可選設置;使用時在建構後分別呼叫set_dataset_mean、set_train_bias,不認為後設置均值會自動更新偏置。均值可為標量或逐維張量,以當前介面為準。encoder+decoder 與 BM 用兩個優化器,BM 更新使用bm_loss(q.detach(), weight_decay);參考 模型範式。最終評估保留訓練時的輸入均值校正與輸出偏置。q是編碼器 logits,(q > 0).float()是硬判定,不是後驗均值。原生重建與均值的區別見參考文件的 QVAE 段落。隨機重建、解碼真實後驗均值均可;從實際最終 logits 計算並保存指標,說明所用方式,不把少量訓練的品質當作介面通過條件。 - QDiffusion:proposal 輸入 [B,L]、輸出 [B,L,V] logits。需要上下文補全時,用自注意力等結構讓缺失位置讀取其他位置;逐位置 embedding + MLP 只能學習位置偏好,即使符合率很高,也不滿足上下文補全。
EnergyModel子類實現score_conditioned(noisy, candidate, attention_mask)輸出 [B,1]。SequenceTokenSpec從kaiwu.torch_plugin.qdiffusion導入,頂層未導出。僅給出「詞表大小 V」時,保持輸出寬度 V;特殊 id 必須落在該詞表內並與內容 token 分開。不自行把 V 解釋為內容詞表並擴成 V+4。內容 id 佔滿 V 或特殊 id 映射不明時,在方案中列出待確認的映射;確認前不採用擴大的輸出寬度,也不縮減使用者已有的內容類別。proposal 從零訓練時先完成獨立補全訓練,再凍結並訓練 energy;原生objective內部截斷 proposal 梯度,不能用它預訓練 proposal。訓練用generator.objective({"targets": batch}),生成用generator.generate(init, max_steps=...)。freeze_proposal=True時只優化 energy 側。完整整合條件見 模型範式。 - 特徵選擇(MAIFS):
from kaiwu.torch_plugin import FeatureSelectionWrapper, QuadraticLinearSolver。建構簽名FeatureSelectionWrapper(model, feature_dim, lambda_reg=0.0, cardinality_k=None, min_selected_features=None, max_selected_features=None, solver="local_search", mask_update_epochs=None, input_feature_axis=-1, solver_kwargs=None)。訓練用sel.fit_weights(loader, loss_fn, optimizer, train_epochs):loader 產出(x, y),loss_fn返回標量,optimizer 作用於sel.model.parameters()。遮罩每mask_update_epochs個 epoch 重新整理一次;為None時只在手動呼叫update_mask(loader, loss_fn, hessian_mode="full"|"diagonal", max_samples=1000)時重新整理。結果用selected_indices()、num_selected()、get_support()讀取。solver="local_search"不需要 license;"sa"、"kaiwu_cim"走 Kaiwu SDK,需要 license。update_mask的耗時主要在 QUBO 求解與數量投影,隨特徵數快速增長(本機 400 個特徵約 13–15 秒,導數計算不到 1 秒);hessian_mode和max_samples只影響導數部分,按實際特徵數預留時間。QuadraticLinearSolver().solve(Q, b)只把 QUBO 項轉成帶一個輔助自旋的 Ising 矩陣,不負責求解。
交付與驗收
新建任務交付完整腳本,補齊數據、import、配置、訓練循環與結果輸出;改已有程式碼時只改任務所需部分。只要求方案或環境記錄時,實際保存指定文件;多輪需求補齊後更新交付,並核對檔案已寫入。參考文件中的 QVAE/QDiffusion 片段是結構示意,含上下文變數,不能冒充可直接執行的腳本。API 不確定時定位當前 kaiwu.torch_plugin.__file__,查實際簽名和源碼。報告真實解釋器、依賴版本和執行結果;RBM 通過不能代表其他模型、GPU 或雲端 CIM 也通過。