主管週五要她交出「下個月哪些客戶可能退租」的名單,手上只有 400 筆標好「有退租/沒退租」的客戶表格
NVIDIA 在 Hugging Face 上公開了 Kumo Tabular,這是一個專門處理「表格資料」的 預訓練模型已經先用大量資料學過一輪基本功的模型,拿來就能用,不必你從零教起。表格資料就是客戶名單、交易紀錄、感測器紀錄、保險理賠、訂單這類一列一列的資料。預測客戶會不會流失、會不會違約、明年需求多少、房價多少,都是企業最常做的表格預測。
它的用法跟以往很不一樣:你給它一張「有答案的表格」(稱為 上下文這裡指你一次丟給模型看的那批有答案的範例資料),再給它「想預測的新列」,它會在 一次前向傳遞資料從模型輸入端一路算到輸出端,只走一趟、不回頭修改模型 內直接吐出答案:分類問題給各類別的機率,數值問題給預測數字。全程沒有訓練、沒有調參數、也不用做特徵工程(也就是人工挑選與加工欄位)。
這種「看例子就答題」的能力叫 in-context learning在提示裡看幾個範例就學會做新任務,模型本身的權重一個都不更新,原本是大型語言模型的招牌。素材指出它同樣適用於表格:模型先在數百萬張表格上預習,之後把有答案的表格讀進來當作參考。Kumo Tabular 有三種大小(2,800 萬到 2.15 億個 參數模型內部可以調整的數字旋鈕,數量越多通常越強也越吃資源),以 OpenMDW-1.1 授權釋出、可商用,而且只用「人造資料」預訓練。
它在 TabArena、BeyondArena、TALENT、ScoringBench 四個 基準測試大家用同一批題目給不同模型考試,比較誰分數高的公開榜單 都排第一。過去二十年這類工作主要靠 梯度提升樹一種把很多棵小決策樹接力組合起來的傳統機器學習方法,表格預測的老牌主力,效果很好,但每個新問題都要重新蒐集標籤、調參、驗證、部署,Kumo Tabular 想把這段流程大幅縮短。
| 工作項目 | 傳統梯度提升樹流程 | Kumo Tabular |
|---|---|---|
| 蒐集有答案的資料 | 要 | 要(當作上下文) |
| 特徵工程 | 要,人工加工欄位 | 不用 |
| 超參數搜尋 | 要 | 不用 |
| 針對新任務重新訓練 | 要,每個任務從零學 | 不用,一次前向傳遞 |
| 預訓練資料 | 無(不適用) | 只用人造資料預訓練 |
這是一個「教學用玩具」,只用標準函式庫模擬 in-context 預測的核心想法:新客戶去跟「有答案的範例列」比相似度,越像的範例,投的票越重。它不是 Kumo Tabular 的真實程式,真實模型是用 Transformer 學出相似度,這裡用簡單距離代替,方便你看清楚流程。
maxes = [max(abs(r[0][i]) for r in context) for i in range(cols)]d = math.dist(norm(feats), norm(query))scores.append(-d / temp)w = [math.exp(s - m) for s in scores]return sum(wi * lab for wi, (f, lab) in zip(w, context)) / total這是一個真實小專案:下載(或複製)檔案,照步驟在你電腦上跑起來。
import math
# 有答案的表格(上下文):[月費, 使用月數] -> 是否退租 (1=退租, 0=續約)
CONTEXT = [
([300, 2], 1), ([350, 3], 1), ([280, 1], 1),
([200, 24], 0), ([250, 30], 0), ([180, 18], 0),
]
# 想預測的新客戶(沒有答案)
QUERY = [[320, 2], [210, 20], [260, 6]]
def predict(context, query, temp=0.3):
cols = len(query)
maxes = [max(abs(r[0][i]) for r in context) for i in range(cols)]
def norm(x):
return [x[i] / maxes[i] for i in range(cols)]
scores = []
for feats, _label in context:
d = math.dist(norm(feats), norm(query))
scores.append(-d / temp)
m = max(scores)
w = [math.exp(s - m) for s in scores]
total = sum(w)
return sum(wi * lab for wi, (_f, lab) in zip(w, context)) / total
if __name__ == "__main__":
for q in QUERY:
p = predict(CONTEXT, q)
print(f"月費={q[0]} 使用月數={q[1]} -> 退租機率 {p:.2f}")
# 試試看:把 CONTEXT 換成你自己的資料,模型權重完全沒有被更新