协同过滤

用于快速获取数据和训练适用于协同过滤模型的工具

此模块包含您在协同过滤应用中所需的所有高级函数,用于组装数据、获取模型并使用 Learner 进行训练。我们将按顺序介绍这些内容,但您也可以查看协同过滤教程

收集数据


源代码

TabularCollab

 TabularCollab (df, procs=None, cat_names=None, cont_names=None,
                y_names=None, y_block=None, splits=None, do_setup=True,
                device=None, inplace=False, reduce_memory=True)

TabularPandas 的实例,适用于协同过滤(没有连续变量)

这只是为了使用表格应用的内部功能,无需担心。


源代码

CollabDataLoaders

 CollabDataLoaders (*loaders, path:str|pathlib.Path='.', device=None)

协同过滤的基础 DataLoaders

类型 默认值 详情
loaders VAR_POSITIONAL 要封装的 DataLoader 对象
path str | pathlib.Path . 存储导出对象的路径
device NoneType None 放置 DataLoaders 的设备

不应直接使用此类,应优先使用其中一个工厂方法。所有这些工厂方法都接受以下参数:

  • valid_pct: 用于验证的数据集随机百分比(可选 seed
  • user_name: 包含用户的列名(默认为第一列)
  • item_name: 包含项目的列名(默认为第二列)
  • rating_name: 包含评分的列名(默认为第三列)
  • path: 工作文件夹
  • bs: 批大小
  • val_bs: 验证 DataLoader 的批大小(默认为 bs
  • shuffle_train: 是否打乱训练 DataLoader
  • device: 要使用的 PyTorch 设备(默认为 default_device()

源代码

CollabDataLoaders.from_df

 CollabDataLoaders.from_df (ratings, valid_pct=0.2, user_name=None,
                            item_name=None, rating_name=None, seed=None,
                            path='.', bs:int=64, val_bs:int=None,
                            shuffle:bool=True, device=None)

ratings 创建适用于协同过滤的 DataLoaders

类型 默认值 详情
ratings
valid_pct float 0.2
user_name NoneType None
item_name NoneType None
rating_name NoneType None
seed NoneType None
path str | pathlib.Path . 放入 DataLoaders 的路径
bs int 64 批大小
val_bs int None 验证 DataLoader 的批大小
shuffle bool True 是否打乱数据
device NoneType None 放置 DataLoaders 的设备

让我们看一个例子

path = untar_data(URLs.ML_SAMPLE)
ratings = pd.read_csv(path/'ratings.csv')
ratings.head()
110.72% [57344/51790 00:00<00:00]
userId movieId rating timestamp
0 73 1097 4.0 1255504951
1 561 924 3.5 1172695223
2 157 260 3.5 1291598691
3 358 1210 5.0 957481884
4 130 316 2.0 1138999234
dls = CollabDataLoaders.from_df(ratings, bs=64)
dls.show_batch()
userId movieId rating
0 580 736 2.0
1 509 356 4.0
2 105 480 3.0
3 518 595 5.0
4 111 527 4.0
5 384 589 5.0
6 607 2918 3.5
7 460 1291 4.0
8 268 1270 5.0
9 56 586 4.0

源代码

CollabDataLoaders.from_csv

 CollabDataLoaders.from_csv (csv, valid_pct=0.2, user_name=None,
                             item_name=None, rating_name=None, seed=None,
                             path='.', bs:int=64, val_bs:int=None,
                             shuffle:bool=True, device=None)

csv 创建适用于协同过滤的 DataLoaders

类型 默认值 详情
csv
valid_pct float 0.2
user_name NoneType None
item_name NoneType None
rating_name NoneType None
seed NoneType None
path str | pathlib.Path . 放入 DataLoaders 的路径
bs int 64 批大小
val_bs int None 验证 DataLoader 的批大小
shuffle bool True 是否打乱数据
device NoneType None 放置 DataLoaders 的设备
dls = CollabDataLoaders.from_csv(path/'ratings.csv', bs=64)

模型

fastai 为协同过滤提供了两种模型:点乘模型和神经网络模型。


源代码

EmbeddingDotBias

 EmbeddingDotBias (n_factors, n_users, n_items, y_range=None)

协同过滤的基础点乘模型。

该模型使用 n_factors(内部向量的长度)、n_usersn_items 构建。对于给定的用户和项目,它获取相应的权重和偏差并返回

torch.dot(user_w, item_w) + user_b + item_b

可选地,如果传入了 y_range,它会将 SigmoidRange 应用于该结果。

x,y = dls.one_batch()
model = EmbeddingDotBias(50, len(dls.classes['userId']), len(dls.classes['movieId']), y_range=(0,5)
                        ).to(x.device)
out = model(x)
assert (0 <= out).all() and (out <= 5).all()

源代码

EmbeddingDotBias.from_classes

 EmbeddingDotBias.from_classes (n_factors, classes, user=None, item=None,
                                y_range=None)

通过从 classes 推断 n_usersn_items 来构建具有 n_factors 的模型

y_range 被传递给主初始化方法。useritemclasses 中用户和项目的键名(默认分别为第一个和第二个键)。classes 预期是字典,键对应类别列表,例如 CollabDataLoadersdls.classes 的结果

dls.classes
{'userId': ['#na#', 15, 17, 19, 23, 30, 48, 56, 73, 77, 78, 88, 95, 102, 105, 111, 119, 128, 130, 134, 150, 157, 165, 176, 187, 195, 199, 212, 213, 220, 232, 239, 242, 243, 247, 262, 268, 285, 292, 294, 299, 306, 311, 312, 313, 346, 353, 355, 358, 380, 382, 384, 387, 388, 402, 405, 407, 423, 427, 430, 431, 439, 452, 457, 460, 461, 463, 468, 472, 475, 480, 481, 505, 509, 514, 518, 529, 534, 537, 544, 547, 561, 564, 574, 575, 577, 580, 585, 587, 596, 598, 605, 607, 608, 615, 624, 648, 652, 654, 664, 665],
 'movieId': ['#na#', 1, 10, 32, 34, 39, 47, 50, 110, 150, 153, 165, 231, 253, 260, 293, 296, 316, 318, 344, 356, 357, 364, 367, 377, 380, 457, 480, 500, 527, 539, 541, 586, 587, 588, 589, 590, 592, 593, 595, 597, 608, 648, 733, 736, 778, 780, 858, 924, 1036, 1073, 1089, 1097, 1136, 1193, 1196, 1197, 1198, 1200, 1206, 1210, 1213, 1214, 1221, 1240, 1265, 1270, 1291, 1580, 1617, 1682, 1704, 1721, 1732, 1923, 2028, 2396, 2571, 2628, 2716, 2762, 2858, 2918, 2959, 2997, 3114, 3578, 3793, 4226, 4306, 4886, 4963, 4973, 4993, 5349, 5952, 6377, 6539, 7153, 8961, 58559]}

让我们看看如何在实践中使用它

model = EmbeddingDotBias.from_classes(50, dls.classes,  y_range=(0,5)
                                     ).to(x.device)
out = model(x)
assert (0 <= out).all() and (out <= 5).all()

添加了两个便利方法,以便在使用 EmbeddingDotBias.from_classes 创建模型时轻松访问权重和偏差


源代码

EmbeddingDotBias.weight

 EmbeddingDotBias.weight (arr, is_item=True)

arr 中所有项目或用户(基于 is_item)的权重

arr 中的元素预期为类名(这就是为什么模型需要使用 EmbeddingDotBias.from_classes 创建的原因)

mov = dls.classes['movieId'][42] 
w = model.weight([mov])
test_eq(w, model.i_weight(tensor([42])))

源代码

EmbeddingDotBias.bias

 EmbeddingDotBias.bias (arr, is_item=True)

arr 中所有项目或用户(基于 is_item)的偏差

arr 中的元素预期为类名(这就是为什么模型需要使用 EmbeddingDotBias.from_classes 创建的原因)

mov = dls.classes['movieId'][42] 
b = model.bias([mov])
test_eq(b, model.i_bias(tensor([42])))

源代码

EmbeddingNN

 EmbeddingNN (emb_szs, layers, ps:float|MutableSequence=None,
              embed_p:float=0.0, y_range=None, use_bn:bool=True,
              bn_final:bool=False, bn_cont:bool=True,
              act_cls=ReLU(inplace=True), lin_first:bool=True)

继承 TabularModel 创建适用于协同过滤的神经网络。

emb_szs 应该是一个包含两个元组的列表,一个用于用户,一个用于项目,每个元组包含用户/项目的数量和相应的嵌入大小(函数 get_emb_sz 可以提供一个不错的默认值)。所有其他参数都传递给 TabularModel

emb_szs = get_emb_sz(dls.train_ds, {})
model = EmbeddingNN(emb_szs, [50], y_range=(0,5)
                   ).to(x.device)
out = model(x)
assert (0 <= out).all() and (out <= 5).all()

创建一个 Learner

以下函数允许我们从数据快速创建一个用于协同过滤的 Learner


源代码

collab_learner

 collab_learner (dls, n_factors=50, use_nn=False, emb_szs=None,
                 layers=None, config=None, y_range=None, loss_func=None,
                 opt_func:Optimizer|OptimWrapper=<function Adam>,
                 lr:float|slice=0.001, splitter:Callable=<function
                 trainable_params>,
                 cbs:Callback|MutableSequence|None=None,
                 metrics:Callable|MutableSequence|None=None,
                 path:str|Path|None=None, model_dir:str|Path='models',
                 wd:float|int|None=None, wd_bn_bias:bool=False,
                 train_bn:bool=True, moms:tuple=(0.95, 0.85, 0.95),
                 default_cbs:bool=True)

dls 创建一个用于协同过滤的 Learner。

类型 默认值 详情
dls DataLoaders 包含 fastai 或 PyTorch DataLoaderDataLoaders
n_factors int 50
use_nn bool False
emb_szs NoneType None
layers NoneType None
config NoneType None
y_range NoneType None
loss_func 可选 None 损失函数。默认为 dls 的损失函数
opt_func fastai.optimizer.Optimizer | fastai.optimizer.OptimWrapper Adam 训练的优化函数
lr float | slice 0.001 默认学习率
splitter Callable trainable_params 将模型拆分为参数组。默认为一个参数组
cbs fastai.callback.core.Callback | collections.abc.MutableSequence | None None 要添加到 LearnerCallbacks
metrics Union None 在验证集上计算的 Metrics
path str | pathlib.Path | None None 保存、加载和导出模型的父目录。默认为 dlspath
model_dir str | pathlib.Path models 保存和加载模型的子目录
wd float | int | None None 默认权重衰减
wd_bn_bias bool False 将权重衰减应用于归一化和偏差参数
train_bn bool True 训练冻结的归一化层
moms tuple (0.95, 0.85, 0.95) 调度器的默认动量
default_cbs bool True 包含默认的 Callbacks

如果 use_nn=False,使用的模型是带有 n_factorsy_rangeEmbeddingDotBias。否则,它是 EmbeddingNN,您可以为其传递 emb_szs(如果您不提供,将从 dls 使用 get_emb_sz 推断),layers(默认为 [n_factors]y_range,以及可以使用 tabular_config 创建的 config 来定制您的模型。

loss_func 默认为 MSELossFlat,所有其他参数都传递给 Learner

learn = collab_learner(dls, y_range=(0,5))
learn.fit_one_cycle(1)
epoch train_loss valid_loss time
0 2.521979 2.541627 00:00