GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - linkerlin/leaves: Pure Go implementation of Rankers for Recommendation System!

BranchesTags
Open more actions menu

Latest commit

 

History

220 Commits
220 Commits

Folders and files

NameName
Last commit message
Last commit date
.cursor/skills
.cursor/skills
 
 
.github/workflows
.github/workflows
 
 
benchmark
benchmark
 
 
booster
booster
 
 
cmd/leaves
cmd/leaves
 
 
data
data
 
 
demos/movielens
demos/movielens
 
 
docs
docs
 
 
ensemble
ensemble
 
 
examples
examples
 
 
explain
explain
 
 
internal
internal
 
 
io
io
 
 
linear
linear
 
 
mat
mat
 
 
metrics
metrics
 
 
model
model
 
 
objective
objective
 
 
predict
predict
 
 
quantize
quantize
 
 
recsys
recsys
 
 
scripts
scripts
 
 
skills
skills
 
 
testdata
testdata
 
 
testscripts
testscripts
 
 
train
train
 
 
transformation
transformation
 
 
tree
tree
 
 
treebuilder
treebuilder
 
 
util
util
 
 
.gitignore
.gitignore
 
 
.golangci.yml
.golangci.yml
 
 
AGENTS.md
AGENTS.md
 
 
CHANGELOG.md
CHANGELOG.md
 
 
CLAUDE.md
CLAUDE.md
 
 
GPU优化.md
GPU优化.md
 
 
LICENSE.md
LICENSE.md
 
 
NOTES.md
NOTES.md
 
 
README.en.md
README.en.md
 
 
README.md
README.md
 
 
TODO.md
TODO.md
 
 
backend_bench_gate_test.go
backend_bench_gate_test.go
 
 
backend_bench_test.go
backend_bench_test.go
 
 
born_parity_format_test.go
born_parity_format_test.go
 
 
born_parity_test.go
born_parity_test.go
 
 
bridge.go
bridge.go
 
 
bridge_linear_test.go
bridge_linear_test.go
 
 
bridge_test.go
bridge_test.go
 
 
compatibility.md
compatibility.md
 
 
delegation_test.go
delegation_test.go
 
 
doc.go
doc.go
 
 
ensemble_delegate.go
ensemble_delegate.go
 
 
go.mod
go.mod
 
 
go.sum
go.sum
 
 
leaves.go
leaves.go
 
 
leaves_test.go
leaves_test.go
 
 
legacy_ensemble.go
legacy_ensemble.go
 
 
lgensemble.go
lgensemble.go
 
 
lgensemble_io.go
lgensemble_io.go
 
 
lgensemble_test.go
lgensemble_test.go
 
 
lgtree.go
lgtree.go
 
 
load.go
load.go
 
 
logo.png
logo.png
 
 
register_io.go
register_io.go
 
 
reload_test.go
reload_test.go
 
 
skensemble_io.go
skensemble_io.go
 
 
train_api.go
train_api.go
 
 
train_bridge_test.go
train_bridge_test.go
 
 
wasm_size_gate_test.go
wasm_size_gate_test.go
 
 
xgblinear.go
xgblinear.go
 
 
xgblinear_io.go
xgblinear_io.go
 
 
xgensemble.go
xgensemble.go
 
 
xgensemble_io.go
xgensemble_io.go
 
 
演进方案.md
演进方案.md
 
 
演进计划.md
演进计划.md
 
 

Repository files navigation

leaves

English | 中文

版本 CI Go 文档 许可证

Logo

简介

leaves 是一个纯 Go 写的推荐系统用排序模型训练与推理库。能直接加载 XGBoost / LightGBM / scikit-learn 模型,也能自训练(hist / exact、排序、生存、tweedie 等),全程不需要任何 C 绑定。

推荐入口

  • 推理:leaves.LoadFromFile(默认开启 AutoTransform),或者沿用旧的 leaves.LGEnsembleFromFile / leaves.XGEnsembleFromFile。
  • 训练:leaves.NewLearner / train.NewLearner、leaves.LoadDataAuto / data.FromFileAuto(带内容嗅探),以及便利函数 leaves.NewLearnerFromModelAndData —— 它能从参考模型里反推出 objective。

回归矩阵见 docs/testdata-matrix.md;路线图 演进计划.md(v5.4);Agent 契约 演进方案.md(v2.2);扩展 objective/metric 见 docs/extension-points.md;backlog TODO.md。

特性

通用

  • 并行批预测(dense / CSR)
  • 支持 sigmoid、softmax 变换;DefaultLoadOptions() 默认开启 AutoTransform
  • 可输出决策树的叶节点索引
  • 训练数据内容嗅探(LIBSVM、排序 TSV、CSV·TSV —— 扩展名只是回退依据)

LightGBM

  • 兼容 text 与 JSON 两种模型格式
  • 支持 gbdt、rf(随机森林)、dart 三类模型
  • 支持多分类预测
  • 对类别特征(独热分割等)有专门的决策规则优化
  • 纯预测场景下的快速路径

XGBoost

  • 支持二进制、JSON、UBJSON 三种模型格式
  • gbtree / gblinear / dart 三种 booster;3.x 嵌套 DART gbtree.model
  • 多分类预测、多输出向量叶、XGBoost 原生 categorical(model.cats)并支持 round-trip 导出
  • 缺失值(nan)支持
  • reg:gamma / count:poisson / reg:tweedie 自动加载变换(Exp + base_score 对数转换)

scikit-learn(实验性)

  • 支持 pickle 协议 0
  • 兼容 sklearn.ensemble.GradientBoostingClassifier

训练(v2.x,里程碑 T1–T5)

  • gbtree / dart / gblinear;hist / exact / gpu_hist(auto 模式按行数自动选)
  • 目标函数:回归、二分类 / 多分类、gamma、poisson、tweedie、survival:cox / survival:aft,以及排序(rank:ndcg / rank:pairwise / rank:listwise)
  • 交叉验证、早停、checkpoint、续训、单调约束、max_leaves(lossguide)、BatchedMatrix(外存 DMatrix)
  • 模型导出:原生 leaves.json、XGBoost 3.x JSON

部署与观测

  • int8 阈值量化(带 parity 门禁)
  • Ensemble.Reload 线上热更新;按 batch 维度的推理 profiling
  • WASM demo、HTTP embed、serving 模板、train-from-model、扩展 objective/metric、多目标回归
  • MovieLens Ranker 教程(精排全流程;demo 另有可选 MCP 入口,主闭环仍是 SKILL + CLI)

安装

go install github.com/linkerlin/leaves/v2/cmd/leaves@latest

模块路径:github.com/linkerlin/leaves/v2(Go 1.26+)。张量与 GPU 加速由 github.com/born-ml/born 提供。

快速上手

最简单的方式:用 leaves.LoadFromFile 加载模型,然后调 PredictSingle。

package main

import (
	"fmt"

	"github.com/linkerlin/leaves/v2"
)

func main() {
	m, err := leaves.LoadFromFile("lightgbm_model.txt", leaves.DefaultLoadOptions())
	if err != nil {
		panic(err)
	}

	fvals := []float64{1.0, 2.0, 3.0}
	p := m.PredictSingle(fvals, 0)
	fmt.Printf("对 %v 的预测: %f\n", fvals, p)
}

旧 API 仍兼容:leaves.LGEnsembleFromFile(path, loadTransformation) 和 leaves.XGEnsembleFromFile(...),行为不变。

格式自动识别与支持等级

io.LoadFromFile / DetectFormat 看扩展名与文件头。完整等级表见 docs/interop-matrix.md(稳定 / 实验 / 占位)。

格式 等级 扩展名 / 探测 说明
leaves.json 稳定 leaves_version 训练主产物;推荐部署
XGBoost JSON 稳定 .json + learner 3.x 默认;base_score→margin
XGBoost UBJSON 稳定 .ubj 与 JSON 预测一致
XGBoost binary 稳定 binf / header 经典 Booster;优先改用 JSON
LightGBM text/JSON 稳定 tree= / tree_info text 与 JSON
scikit-learn 实验 .pkl / .joblib 窄协议;生产请转 XGB/leaves JSON
ONNX 实验 .onnx TreeEnsemble Regressor/Classifier 子集;复杂图走 LoadOnnxGraph 或先转 JSON/leaves

加载失败返回 *io.LoadError(含 hint: 下一步)。数值表误用 .txt 会提示改用 data.FromFile。

import "github.com/linkerlin/leaves/v2/io"

m, err := io.LoadFromFile("model.ubj", io.DefaultLoadOptions()) // AutoTransform = true

m, err = io.LoadFromFile("model.ubj", &io.LoadOptions{
	AutoTransform:      false, // 输出原始 margin
	LoadTransformation: true,  // 或者对所有目标强制启用变换
	Backend:            io.BackendAuto,
})

当 AutoTransform 与 LoadTransformation 都为 false 时,OutputValue 和 OutputMargin 都是原始 margin。contrib / SHAP 始终在 margin 空间,与 AutoTransform 无关。

训练 API

dm, _ := leaves.LoadDataAuto("train.tsv") // 内容嗅探

learner, _ := leaves.NewLearner(leaves.TrainConfig{
	Objective: leaves.TrainObjectiveBinaryLogistic,
	NumRound:  50,
})
_ = learner.Fit(dm)
_ = learner.Save("out.leaves.json")

外存 DMatrix

bm, _ := data.SplitDense(dense, batchRows) // 也可以 data.NewBatchedMatrix(...)
learner, _ := train.FitExternal(train.Config{
	Objective:     train.ObjectiveBinaryLogistic,
	TreeMethod:    train.TreeMethodHist,
	HistBinPolicy: "global",
	NumRound:      10,
}, bm)

Checkpoint 续训

learner, _ := train.ResumeFit("ckpt.json", train.Config{
	Objective:  train.ObjectiveSquaredError,
	NumRound:   20, // 在 checkpoint 完成的轮次之上继续
	TreeMethod: train.TreeMethodExact,
}, dm)
score, _ := learner.Eval(dm)

训练数据 —— 自动嗅探

data.FromFileAuto / leaves.LoadDataAuto 会先读一段样本来选 loader,扩展名只是兜底。

嗅探结果 典型内容 Loader
LIBSVM label 1:0.5 3:1.2 FromLIBSVM
排序 TSV qid label feat... LoadRankingTSV
末列为 label 的 TSV 无表头,末列是 label LoadDenseTSV
CSV 有表头或启发式 label 列 FromCSV

从参考模型反推 objective

learner, _ := leaves.NewLearnerFromModelAndData(
	"reference_model.json", // 只读 objective(XGB JSON / UBJ / leaves.json)
	"train.tsv",            // LoadDataAuto 嗅探
	leaves.TrainConfig{NumRound: 10, TreeMethod: leaves.TrainTreeMethodExact},
	data.DefaultFileLoadOptions(),
)
_ = learner.Save("out.leaves.json")
go run ./examples/train_from_model/ -model testdata/xgboost_smoke.json -data testdata/breast_cancer_train.tsv

survival:aft 区间删失

d, _ := data.NewDense(vals, n, nfeat, placeholderLabels, nil)
dm, _ := data.NewAFTDense(d, []data.AFTInterval{
	{1.5, 1.5},              // 事件
	{2, math.Inf(1)},        // 右删失
	{0, 4},                  // 左删失
	{1, 6},                  // 区间删失
})
learner, _ := train.NewLearner(train.Config{Objective: train.ObjectiveSurvivalAFT, ...})
_ = learner.Fit(dm)

单调约束

learner, _ := train.NewLearner(train.Config{
	Objective:           "reg:squarederror",
	MonotoneConstraints: []int{1, 0, -1}, // 特征 0 递增,特征 2 递减
	TreeMethod:          train.TreeMethodHist,
})

训练加速栈(T4+)

hist / gpu_hist 路径上的加速分层(日志前缀 [leaves/train] accel:):

阶段 实现 默认 auto(≥3 万行 + WebGPU) LEAVES_TRAIN_ACCEL=webgpu
全局分箱 训练期每特征一次切点 + 行级 bin 缓存 ✅ ✅
直方图累加 CPU rowBin / WebGPU SelectAdd 批量 gpu_hist GPU batch
增益扫描 纯 CPU / 批量 WebGPU gain 批量 GPU(GPU 路径) 批量 GPU
margin 预测 逐行 CPU / Born GPU PredictDense PredictMargins ≥256 行 ≥64 行
learner, _ := train.NewLearner(train.Config{
	Objective:     train.ObjectiveRankNDCG,
	TreeMethod:    train.TreeMethodGPUHist,
	AccelMode:     train.AccelModeWebGPU, // 也可走环境变量 LEAVES_TRAIN_ACCEL
	NumThreads:    4,
	HistBinPolicy: "global", // 默认;"per_node" 恢复旧的 per-node 切点
	NumRound:      50,
})
_ = learner.Fit(dm)

环境变量覆盖:LEAVES_TRAIN_ACCEL=auto|webgpu|born_cpu|cpu。无真实 GPU 的环境(CI WARP 软件设备运行时 DXGI_ERROR_DEVICE_REMOVED)设 LEAVES_BORN_GPU=0 可同时关闭训练与推理的 WebGPU 路径。

计算底座 —— Born

Born = 训练加速器 + ONNX 运行时;推理 golden 永远 Native(桌面与 WASM)。训练侧 WebGPU hist / CPU 增益扫描构建在 Born 之上;推理侧 Born 引擎是 parity/兼容路径(桌面实测慢 6–30×)。GOOS=js 上 BornEngine 委托 Native。BackendAuto(2.1)一律 Native——历史 batch 阈值「加速区」未复现(docs/benchmark-baseline.md §再测量);需要 Born 时显式指定,或设 LEAVES_BACKEND_PROFILE=1 实测选型(带预算/超时守卫)。完整决策表:docs/backend-auto.md。

m, _ := leaves.LoadFromFile("model.json", &io.LoadOptions{
	Backend:  io.BackendBornCPU, // 或 BackendAuto + LEAVES_BACKEND_PROFILE=1 实测选型
	Workload: tree.WorkloadHint{BatchSize: 256, HasGPU: true},
})
// 可解释选型:tree.SelectBackendExplained(caps, hint) → Rule / Reason

parity 门禁 TestBornParityFormatMatrix 覆盖 LGB text/JSON、XGB bin/json/ubj、scikit-learn pickle × batch {1, 16, 256} × BornCPU / BornGPU,容差 1e-5(相对 Native)。

后端选型速查(BackendAuto 2.1)

场景 Auto 结果 说明
桌面任意 batch(CPU / GPU) Native 默认;实测 Born 更快再显式指定或开 profiling
实测确认 Born 更快 BackendBornCPU / BackendBornGPU 显式;或 LEAVES_BACKEND_PROFILE=1 形状类缓存,测得更快才选
WASM Native js 上 BornEngine 委托 Native;显式 BornCPU 也是同一 walk
稀疏 SparseDensity∈(0,0.15) / cat-small Native Born 未优化 / 不支持

Tree SHAP 与可解释性

m.Explain() 暴露的是 Lundberg 快速 Tree SHAP(带 SumHess 权重覆盖,tree_path_dependent);SHAP 值在 margin 空间,与 OutputMargin / predict.OutputContribution 保持一致。DefaultLoadOptions() 对 logistic 模型返回概率;contrib / SHAP 仍在 margin 空间。

import (
	"github.com/linkerlin/leaves/v2"
	"github.com/linkerlin/leaves/v2/explain"
)

m, _ := leaves.LoadFromFile("model.json", leaves.DefaultLoadOptions())

x := [][]float64{{1.0, 2.0, 3.0}}
contrib, _ := m.Explain().TreeSHAP(x)        // margin 空间 SHAP
inter, _ := m.Explain().InteractionSHAP(x)   // 交互值矩阵
mc, _ := m.Explain().TreeSHAPMulticlass(x)   // 多类:[sample][feature][class]
base := m.Explain().ExpectedValue()          // 背景基线(全零特征)

imp := m.Explain().Importance(explain.ImportanceGain, nil)
text := m.Explain().DumpText(nil)
dot := m.Explain().DumpDOT(nil)

统一出口是 predict.Request:

import "github.com/linkerlin/leaves/v2/predict"

nf := m.NFeatures()
nRows := 1

// 输出值(logistic 已变换,squarederror 仍为原始)
vals := make([]float64, nRows*m.NOutputGroups())
_ = m.PredictWithRequest(predict.Request{
	Matrix: predict.DenseMatrix{Values: flat, Rows: nRows, Cols: nf},
	Output: predict.OutputValue,
}, vals)

// 原始 margin(sigmoid / softmax 之前)
margins := make([]float64, nRows*m.NRawOutputGroups())
_ = m.PredictWithRequest(predict.Request{
	Matrix: predict.DenseMatrix{Values: flat, Rows: nRows, Cols: nf},
	Output: predict.OutputMargin,
}, margins)

// 叶节点索引(每棵树一个 int32)
nTrees := m.NTrees()
leaves := make([]int32, nRows*nTrees)
_ = m.PredictWithRequest(predict.Request{
	Matrix: predict.DenseMatrix{Values: flat, Rows: nRows, Cols: nf},
	Output: predict.OutputLeaf,
}, leaves)

// SHAP 贡献(margin 空间;二分类 [sample][feature+bias])
out := make([]float64, (nf+1)*nRows)
_ = m.PredictWithRequest(predict.Request{
	Matrix: predict.DenseMatrix{Values: flat, Rows: nRows, Cols: nf},
	Output: predict.OutputContribution, // 也可 OutputApproxContribution / OutputInteraction
}, out)

bias 语义:末列是全零特征处的背景 margin,与 XGBoost pred_contribs 的可加性约定一致(逐元素分解可能不同)。

评估指标 —— metrics/

内置 RMSE / MAE / AUC / LogLoss / MAPE / RMSLE / NDCG@k / MAP,命名与 XGBoost eval_metric 对齐:

import "github.com/linkerlin/leaves/v2/metrics"

rmse, _ := metrics.RMSE{}.Evaluate(yTrue, yPred)
m, _ := metrics.Resolve("ndcg@5", metrics.Options{Groups: []int{10, 10}})
ndcg, _ := m.Evaluate(yTrue, yPred)

排序指标需要 data.GroupedMatrix 提供 Groups()。

排序学习

XGBoost 兼容的 LambdaMART,再加上原生的 listwise 头:

目标 家族 说明
rank:ndcg LambdaMART(XGBoost 兼容) pairwise + |ΔNDCG| 缩放,直接对齐排序指标
rank:pairwise RankNet pairwise 默认 top-k(k=32)+ lambdarank_normalization(对标 XGBoost)
rank:listwise ListNet softmax CE(leaves 原生) q ∝ exp(label)、p = softmax(pred),纯 listwise 交叉熵
import (
	"github.com/linkerlin/leaves/v2/data"
	"github.com/linkerlin/leaves/v2/train"
)

dm, _ := data.LoadRankingTSV("rank_train.tsv", "\t") // qid label feat1 feat2 ...

learner, _ := train.NewLearner(train.Config{
	Objective:    train.ObjectiveRankNDCG, // 或 ObjectiveRankPairwise / ObjectiveRankListwise
	NumRound:     40,
	MaxDepth:     4,
	LearningRate: 0.1,
	NDCGK:        10,
	EvalMetric:   "ndcg@10",
})
_ = learner.Fit(dm)

端到端 MovieLens 100K demo(训练 → 保存 → Top-K 推荐):demos/movielens/README.md。

cd testdata && python gen_rank_movielens.py
go run ./demos/movielens/cmd/train
go run ./demos/movielens/cmd/recommend -group 0 -topk 10
go test ./train/... -run TestRankMovieLens -v

训练回调与学习率调度

learner, _ := train.NewLearner(train.Config{
	Objective:    train.ObjectiveSquaredError,
	NumRound:     20,
	LearningRate: 0.3,
	LRScheduler:  train.ExponentialLRScheduler(0.95), // 每轮 ×0.95
	Callbacks: []train.TrainingCallback{
		train.FuncCallback(func(ctx *train.CallbackContext) error {
			// ctx.Round, ctx.LearningRate, ctx.TrainMetric, ctx.EvalMetric
			return nil
		}),
	},
})

内置调度器:ExponentialLRScheduler(gamma) 和 StepLRScheduler(every, factor)。配置 EvalSet + EvalMetric 时,CallbackContext 也会自动填充 EvalMetric / EvalMetricOK(不依赖 EarlyStop)。

推理 profiling 与热更新

if ne, ok := m.Engine().(*tree.NativeEngine); ok {
	prof, err := tree.ProfileNativeDense(ne, vals, nrows, ncols, preds, 0)
	_ = prof.Elapsed
}

// 线上原子切换模型
_ = m.Reload("/path/to/new.model", io.DefaultLoadOptions())

tree.ProfileWalkStats 可以单独统计单样本的树遍历深度,不跑完整预测。

int8 阈值量化

数值分裂阈值按特征做 int8 仿射量化(127 级),叶子值保持 float64,分类节点不量化。quantize.Engine 不支持 PredictLeafIndices*(只支持 margin 预测)。

qf, _ := quantize.QuantizeForest(m.Forest(), quantize.Config{})
res, err := quantize.CheckParityWithGate(m.Forest(), qf, samples, 0, quantize.DefaultGate())

eng, _ := quantize.NewEngine(qf, nil, tree.TransformRaw, m.NOutputGroups())
model.NewEnsemble(eng) // 替换线上 Ensemble 引擎

Agent 自动化(SKILL 驱动,无 MCP)

通用 Agentic 训练契约已达成(见 演进方案.md v2.2 DoD);推荐生产闭环控制面(§十七 RC)亦已落地,见 docs/recsys-loop.md。 库整体 12 个月路线图见 演进计划.md v5.4 — 二者互补,不互相替代。

Agent 通过 SKILL + leaves CLI + metrics.json 完成「训练→调参→发布」;Agent 即优化器(搜索逻辑在 SKILL,库不内置 HPO)。

三步让 Agent 帮你训练(用户视角)

  1. 装 CLI:go install github.com/linkerlin/leaves/v2/cmd/leaves@latest(或在仓库内用 go run ./cmd/leaves ...)。
  2. 把技能给 Agent:Cursor 用户开箱即得(.cursor/skills);Claude Code 读 CLAUDE.md → AGENTS.md;其他 Agent 让它读 skills/leaves-autotrain/SKILL.md。
  3. 对 Agent 说一句话(无需懂 flag):
用 leaves-autotrain 技能,训练数据在 data/train.csv,
目标把 RMSE 降下来,收敛后发布到 release/v1。

Agent 会自动:嗅探数据定任务类型 → CV 基线 → 按 SKILL §4.5 演化搜索协议调参(runs.jsonl 记账、早停保最优轮)→ 收敛后 publish 出工件包(模型 + manifest + 复现命令)。全程只读 JSON,不写 Go 代码。

文档 用途
演进方案.md Agentic 契约 / WP / 验收 DoD
skills/leaves-autotrain/SKILL.md 决策表与闭环策略
skills/leaves-autotrain/cli.md flag + metrics schema
examples/autotrain/ 零准备 demo
sniff → [split] → train(--cv --runs --tag [--early-stop 默认 save-best] [--from-run])
  → runs/diagnose 读账本与 ASI 诊断 → 决策表调参 → 收敛 → compare/inspect → publish(--emit-repro-script)

边界:本地工件包(非 registry);不内置 HPO;CSV 默认无缺失(--na-policy skip-row 可丢行,--na-policy nan 保留 NaN 走树默认方向;--auto-encode 可自动字典序编码类别列并持久化至模型)。

go run ./cmd/leaves --error-format json sniff --data train.csv
go run ./cmd/leaves train --data train.csv --objective reg:squarederror --cv 5 --runs runs.jsonl --tag baseline
go run ./cmd/leaves train --data train.csv --from-run runs.jsonl --tag baseline --out-model m.leaves.json --metrics metrics.json
go run ./cmd/leaves publish --model m.leaves.json --out-dir release/ --quantize --export-xgb --metrics metrics.json --emit-repro-script both

publish --quantize 会持久化 int8 量化侧车(model.quant.json);manifest.json 含 reproduce 复现命令与文件 sha256。

CLI 入口(用哪条命令)

要做什么 命令 说明
训练 / 评估 / 对比 / 发布 / lessons go run ./cmd/leaves <sniff|split|train|runs|diagnose|eval|compare|predict|inspect|explain|publish|lessons|schema|version> Agent 主闭环;SKILL leaves-autotrain
推荐生产闭环八段 go run ./recsys/cmd/control <pipeline|snapshot|split|eval|…> 控制面;支持 pipeline 一键闭环与纯 JSON stdout
离线四段 smoke go run ./recsys/cmd/smoke 合成数据 prep→召回→LTR→发牌
MovieLens 四段 go run ./recsys/cmd/movielens 真实 u.data
MovieLens 精排 demo go run ./demos/movielens/cmd/{train,recommend,agent} 案例;cmd/mcp 为可选 demo,不是主闭环

不把 recsys 并进 cmd/leaves(见 TODO 明确不做)。

推荐生产闭环控制面(§十七 RC)

recsys/ 在离线四段(prep→召回→LTR→发牌)之上提供可离线测试的控制面契约(纯 Go,无运行时依赖):数据快照/指纹(recsys/contract)、时间切分防泄漏(recsys/split)、三层离线门禁(recsys/eval)、决策/曝光/反馈账本(recsys/ledger)、归因回放(recsys/replay)、窗口监控(recsys/monitor)、发布状态机 + adapter 请求(recsys/release)。端到端演练见 recsys/loop。

  • 指南:docs/recsys-loop.md · 剧本:skills/recsys-orchestrator/SKILL.md §十
  • 边界:离线 deal ≠ 线上 decision;leaves 只产出推广/回滚请求(fake adapter 可测),不托管 registry/serving/在线学习

文档

文档 说明
godoc API 参考
docs/api-surface.md 推荐 / 兼容 / 实验 API 分层与迁移
docs/versioning.md v2.x 允许改什么
docs/release-checklist.md v2.x 发版检查表
CHANGELOG.md 面向用户的变更记录(Unreleased → tag)
docs/interop-matrix.md 格式支持等级
docs/backend-auto.md BackendAuto 2.1 决策表
docs/extension-points.md 自定义 objective/metric
演进计划.md 库 12 个月路线(v5.4)
演进方案.md Agent 闭环契约(已达成)+ §十七 RC
docs/recsys-loop.md 推荐生产闭环控制面(RC)
TODO.md 可执行 backlog
NOTES.md 仍有效的兼容注记(AutoTransform 等)
compatibility.md 外部 GBRT 库正确性矩阵
AGENTS.md 项目规约
docs/testdata-matrix.md 回归矩阵
docs/benchmark-baseline.md Bench 门禁
examples/ autotrain / wasm / http / serving-template / train_from_model / extension / multitarget

兼容性

  • API 分层与迁移:docs/api-surface.md
  • 版本策略:docs/versioning.md
  • 行为注记(AutoTransform 默认等):NOTES.md
  • 外部库版本矩阵:compatibility.md

性能

单线程 / batch=1000,硬件:2017 款 15 寸 MacBook Pro(2.9 GHz Core i7,16 GB 2133 MHz LPDDR3)。C API 走 Python 绑定,批调用下绑定开销可忽略。go test -bench 驱动 leaves 一侧;数据准备流程见 benchmark/ 和 testdata/README.md。

单线程:

测试用例 特征数 树数 批量 C API leaves
LightGBM MS LTR 137 500 1000 49 ms 51 ms
LightGBM Higgs 28 500 1000 50 ms 50 ms
LightGBM KDD Cup 99* 41 1200 1000 70 ms 85 ms
XGBoost Higgs 28 500 1000 44 ms 50 ms

四线程:

测试用例 特征数 树数 批量 C API leaves
LightGBM MS LTR 137 500 1000 14 ms 14 ms
LightGBM Higgs 28 500 1000 14 ms 14 ms
LightGBM KDD Cup 99* 41 1200 1000 19 ms 24 ms
XGBoost Higgs 28 500 1000 ? 14 ms

(?)XGBoost 的多线程预测目前无法通过 Python 绑定启用。(*)KDD Cup 99 同时含连续与类别特征。

Born 后端的微基准(Windows / WebGPU)见 docs/benchmark-baseline.md。

局限

  • LightGBM —— 支持的变换函数有限(仅 sigmoid 与 softmax)
  • XGBoost —— 支持的变换函数有限(仅 sigmoid 与 softmax);浮点转换的精度差异会导致 C API 与 _leaves_ 的预测有零星 ULP 级偏差
  • scikit-learn —— 不支持变换函数(输出为 GradientBoostingClassifier.decision_function 的原始分数);仅支持 pickle 协议 0;同样有浮点精度差异

项目演进

路线图现已转为“当前代码库审计 + 下一年演进计划”的写法。见 演进计划.md 的 v5.4,以及作为历史已完成清单的 TODO.md。

联系方式

有任何问题或想交流,可发邮件:[email protected]。

许可证

MIT —— Copyright (c) 2018 Steper Lin。

About

Pure Go implementation of Rankers for Recommendation System!

zhichai.net/

Topics

algorithmsgbdtgogpumlxgboost

Resources

Readme
MIT license
Activity

Stars

3 stars

Watchers

0 watching

Forks

0 forks
Report repository

Releases

Packages

Used by

Contributors

Languages

You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.