Multi-Model Hierarchical Ensemble for Book Borrowing Recommendation
面向图书借阅预测的多模型分层融合推荐系统
Project Background · Architecture · Quick Start · Model Zoo · License
我们是 Algorithm Challenge 图书借阅推荐赛 初赛第一名 的「噜啦啦」队,最终获 国家一等奖。比赛结束后,我们将最终提交方案与实现整理开源。
整理仓库时,我们没有把比赛过程中的痕迹都抹掉,部分目录结构、脚本命名和中间结果仍保留了当时迭代的状态。我们更想保留真实数据下有效的建模思路、融合方式和取舍过程,而不只是留下一个最终结果。希望这些内容能给后续参赛者和推荐系统学习者带来一点思路参考。
| Part | What it carries | Output |
|---|---|---|
| 🧠 Candidate Models | LightGBM / Graph / GNN-BERT 多路候选 | per-model CSV |
| 🔥 V5 Stable Vote | 跨参数仍然稳定的 user-book 对 | stable_v5.csv |
| 🎯 Top-k Fusion | 前排候选的覆盖信号 | topk_ensemble.csv |
| ⚖️ Final Ensemble | 权重投票与固定优先级仲裁 | submission.csv |
git clone https://github.com/Sihang-Geng/AIC_Solution.git
cd AIC_Solutionconda create -n aic-solution python=3.10 -y
conda activate aic-solutionIf conda has not been initialized:
conda init
conda activate aic-solutionpip install -r requirements.txtOptional graph-model environment
For dspos2 and gnn_bert, install PyTorch according to your CUDA version.
CUDA example:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
pip install torch-geometricCPU fallback:
pip install torch torchvision torchaudio
pip install torch-geometricThe ensemble scripts consume candidate CSV files generated by each model module.
Normal candidate files use:
user_id,book_id
1,10001
2,10008Top-k files additionally use:
user_id,book_id,score
1,10001,0.873
2,10008,0.742具体文件路径在各脚本顶部集中配置,保持目录结构不变即可。
python ensemble_v5.py
python ensemble_topk.py
python final_ensemble.pyExpected outputs:
stable_v5.csv
topk_ensemble.csv
submission.csv
AIC_Solution/
|-- final_ensemble.py # final weighted arbitration
|-- ensemble_v5.py # V5 stable voting
|-- ensemble_topk.py # Top-k auxiliary fusion
|-- requirements.txt
|-- assets/
| `-- architecture.png
`-- models/
|-- mix_lgbm/ # mixed LightGBM baseline
|-- v5_ranker/ # V5 model family
|-- f3_lgbm/ # feature auxiliary model
|-- v2_lgbm/ # compact auxiliary model
|-- f1_lgbm/ # coverage auxiliary model
|-- dspos2/ # graph-based model
|-- gnn_bert/ # graph + text representation
`-- legacy_reuse/ # stable historical signals
| Module | Style | Signal |
|---|---|---|
🟢 models/mix_lgbm |
LightGBM baseline | fast backbone |
🟣 models/v5_ranker |
ranking family | stable variants |
🟢 models/v2_lgbm |
lightweight GBDT | auxiliary candidate |
🟢 models/f3_lgbm |
feature ranker | tabular supplement |
🟢 models/f1_lgbm |
auxiliary ranker | coverage boost |
🔵 models/dspos2 |
graph model | structural signal |
🟣 models/gnn_bert |
GNN + BERT | text and graph representation |
🟠 models/legacy_reuse |
historical reuse | stable semi-final signal |
- 👤 user-book interaction frequency
- ⏱️ borrowing interval and temporal behavior
- 📖 borrow duration and renewal pattern
- 🧾 book metadata and text representation
- 🔗 user-book graph neighborhood
- 🧠 BERT-style semantic embedding
- 🎚️ Min-Max calibration for Top-k scores
- 🔥 vote thresholding for V5 variants
- ➕ weighted score accumulation
- 🧷 fixed-priority tie-breaking
代码和方案之外,也想把这段比赛经历留在这里。
从反复调模型、改融合,到最后来到决赛现场,中间有很多忐忑等待结果的时刻。一次精心设计的改动不一定有效,一个极其合理的方案也可能在真实数据上失效。也是在这个过程中,我们慢慢学会了怎么面对结果波动,怎么从错误提交里判断问题,怎么在深度模型、特征工程、候选集筛选之间做取舍。这个过程的收获,远比结果重要。对我们来说,这几张照片记录的不只是一次获奖,也记录了那段把一件事认真做完的时间并最终得到认可的经历。
希望以后再回看这个仓库时,除了看到代码和结果,也能想起当时一路做下来时的投入、紧张和开心。
![]() |
![]() |
![]() |
如需完整决赛最终提交包,可通过邮箱联系。Email: gengsihang2025@163.com
This project is released under the GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE for details.




