推荐 / NOTEBOOK 课程

08 · 多样性、规则与 DPP

真实向量 + 数值验收

真实数据实验只读 · 已保存的实验

已有输出来自保存的教学实验,并非打开页面时重新执行。 代码和原始输出保持不变;数据与历史注释保留原始语言。

多样性、规则与 DPP

Goal

把概念变成可检查的输入、运算、梯度与对照。

数据类型:真实向量 + 数值验收。本地教学参数不是生产默认值;机制实验不是原论文完整复现。

Setup

每本首次从 Setup 起顺序运行,后面的格会复用前面的变量。之后只改一个参数,重跑对应格及下游格。不要把构造数据当作真实业务收益。

PYTHON · 01
from pathlib import Path
import sys
import inspect
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import display, Code

PROJECT = next(p for p in [Path.cwd(), *Path.cwd().parents]
               if (p / "reclab/models.py").exists())
if str(PROJECT) not in sys.path:
    sys.path.insert(0, str(PROJECT))
from reclab.data import Dataset
from reclab.paths import ARTIFACTS, PROCESSED, read_json

plt.rcParams.update({"figure.figsize": (9, 3.8), "font.size": 11,
    "axes.spines.top": False, "axes.spines.right": False,
    "axes.labelcolor": "#182b2b", "text.color": "#182b2b",
    "axes.facecolor": "white", "figure.facecolor": "white",
    "grid.color": "#d4ddda", "axes.axisbelow": True})
dataset = Dataset()
print("Project:", PROJECT)
print("Dataset version:", dataset.manifest["dataset_version"])
print("Python:", sys.executable)
assert Path(sys.executable).parent == PROJECT / ".venv/bin", "请选择 Recommendation Lab 内核"
Notebook 保存的输出 · 本页未执行
Project: /Users/lizuolin/local/recommendation-lab
Dataset version: 2772cab0aca8cb81
Python: /Users/lizuolin/local/recommendation-lab/.venv/bin/python

Steps

讲义对应:06_Rerank_01.pdf, 06_Rerank_02.pdf, 06_Rerank_03.pdf, 06_Rerank_04.pdf, 06_Rerank_05.pdf

真实向量上的 ILD、类目熵与 MMR

ILD 衡量协同向量距离,不等同于独立图文语义。列表变化不是用户反馈。

先预测: 同类目多不一定意味着向量相似吗?

PYTHON · 02
from reclab.learning.systems import ild,category_entropy,constrained_ranking,greedy_dpp,slow_greedy_dpp,exhaustive_dpp
from reclab.retrieval import mmr
vectors=np.load(ARTIFACTS/"runs/baseline-history32/item_vectors.npy")
scores=vectors@vectors[100];pool=np.argsort(-scores[1:])[:80]+1
rows=[]
for lam in [1.,.8,.5]:
    selected,_=mmr(pool.tolist(),scores,vectors,k=10,relevance=lam)
    rows.append({"lambda":lam,"mean_similarity":float(scores[selected].mean()),
        "ILD":ild(vectors,selected),"category_entropy_bits":category_entropy([dataset.items[i-1]["category"] for i in selected])})
display(pd.DataFrame(rows))
Notebook 保存的输出 · 本页未执行
lambda mean_similarity ILD category_entropy_bits
0 1.0 0.819358 0.191529 0.921928
1 0.8 0.819279 0.198008 0.921928
2 0.5 0.808305 0.277409 1.770951

规则与不可行约束

若没有可行候选,本实现明确返回部分结果,不伪造满足规则的完整列表。

先预测: 候选全部来自一个类目时,算法应该放松规则还是少返回?

PYTHON · 03
categories={i:dataset.items[i-1]["category"] for i in pool}
selected=constrained_ranking(pool.tolist(),categories,k=10,max_consecutive=2)
display(pd.DataFrame({"item":selected,"category":[categories[i] for i in selected]}))
for pos in range(2,len(selected)):
    assert not (categories[selected[pos]]==categories[selected[pos-1]]==categories[selected[pos-2]])
Notebook 保存的输出 · 本页未执行
item category
0 100 819
1 4153 819
2 1172 405
3 4126 532
4 3095 819
5 4311 819
6 1537 1445
7 3424 819
8 398 819
9 4520 1593

DPP:体积、慢速贪心、快速 Cholesky 和穷举

受控随机向量,便于数值验收。贪心 MAP 不是全局最优保证。

先预测: 把两个候选向量设成相同,Gram 行列式会怎样变化?

PYTHON · 04
rng=np.random.default_rng(42)
v=rng.normal(size=(8,8));v/=np.linalg.norm(v,axis=1,keepdims=True)
quality=np.exp(np.linspace(0,1,8));features=v*quality[:,None];kernel=features@features.T
assert np.linalg.eigvalsh(kernel).min()>-1e-8
orthogonal=np.eye(2);duplicate=np.array([[1.,0.],[1.,0.]])
print("Orthogonal/duplicate volume squared:",np.linalg.det(orthogonal@orthogonal.T),np.linalg.det(duplicate@duplicate.T))
display(Code(inspect.getsource(greedy_dpp),language="python"))
fast=greedy_dpp(kernel,3);slow=slow_greedy_dpp(kernel,3)
best_logdet,best_ids=exhaustive_dpp(kernel,3)
assert fast==slow
greedy_logdet=np.linalg.slogdet(kernel[np.ix_(fast,fast)])[1]
assert greedy_logdet<=best_logdet+1e-8
display(pd.DataFrame([{"method":"greedy","items":fast,"logdet":greedy_logdet},{"method":"global exhaustive","items":best_ids,"logdet":best_logdet}]))
Notebook 保存的输出 · 本页未执行
Orthogonal/duplicate volume squared: 1.0 0.0
def greedy_dpp(kernel, k):
    """Incremental Cholesky greedy MAP. It is an approximation to global MAP."""
    n = len(kernel)
    k = min(k, n)
    residual = kernel.diagonal().copy()
    coefficients = np.zeros((k, n))
    selected = []
    for step in range(k):
        item = int(np.argmax(residual))
        if residual[item] <= 1e-12:
            break
        correction = coefficients[:step, item] @ coefficients[:step, :]
        update = (kernel[item, :] - correction) / math.sqrt(residual[item])
        coefficients[step, :] = update
        residual = np.maximum(residual - update**2, 0)
        selected.append(item)
        residual[selected] = -np.inf
    return selected
method items logdet
0 greedy [7, 6, 5] 4.680314
1 global exhaustive (5, 6, 7) 4.680314

Checks

所有断言和输出都可回溯到代码。它们验证算子、数据快照或机制,不是线上收益。

Next Steps

先记录预测,只改一个变量,再运行对应实验格。需要查看辅助函数时,打开 reclab/learning/。

继续阅读原文

本章来源

作者课程中文

王树森 · 工业界的推荐系统

作者课程对应模块;见下方逐份讲义

45份讲义与逐课实践入口;主题有练习不代表完整复现论文。原件保留原语言与原作者权利。

作者课程中文

多样性度量

06_Rerank_01.pdf · 15页

部分方法或机制练习;完整链路与规模未覆盖。

作者课程中文

MMR

06_Rerank_02.pdf · 12页

已有对应方法实验;不代表完整论文或工业效果。

作者课程中文

重排规则

06_Rerank_03.pdf · 8页

对应教学机制可读;原讲义完整方法仍是进阶目标。

作者课程中文

DPP 数学基础

06_Rerank_04.pdf · 17页

对应教学机制可读;原讲义完整方法仍是进阶目标。

作者课程中文

DPP 多样性算法

06_Rerank_05.pdf · 18页

对应教学机制可读;原讲义完整方法仍是进阶目标。

作者课程中文

多样性与探索

08_Improvement_04.pdf · 15页

部分方法或机制练习;完整链路与规模未覆盖。

学习标记可选,仅保存在当前浏览器中。打开页面不会自动标记已学。