nextrec 0.4.22__py3-none-any.whl → 0.4.24__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nextrec/__version__.py +1 -1
- nextrec/basic/layers.py +96 -46
- nextrec/basic/metrics.py +128 -114
- nextrec/basic/model.py +94 -91
- nextrec/basic/summary.py +36 -2
- nextrec/data/dataloader.py +2 -0
- nextrec/data/preprocessor.py +137 -5
- nextrec/loss/listwise.py +19 -6
- nextrec/loss/pairwise.py +6 -4
- nextrec/loss/pointwise.py +8 -6
- nextrec/models/multi_task/aitm.py +0 -0
- nextrec/models/multi_task/apg.py +0 -0
- nextrec/models/multi_task/cross_stitch.py +0 -0
- nextrec/models/multi_task/esmm.py +5 -28
- nextrec/models/multi_task/mmoe.py +6 -28
- nextrec/models/multi_task/pepnet.py +335 -0
- nextrec/models/multi_task/ple.py +21 -40
- nextrec/models/multi_task/poso.py +17 -39
- nextrec/models/multi_task/share_bottom.py +5 -28
- nextrec/models/multi_task/snr_trans.py +0 -0
- nextrec/models/ranking/afm.py +3 -27
- nextrec/models/ranking/autoint.py +5 -38
- nextrec/models/ranking/dcn.py +1 -26
- nextrec/models/ranking/dcn_v2.py +6 -34
- nextrec/models/ranking/deepfm.py +2 -29
- nextrec/models/ranking/dien.py +2 -28
- nextrec/models/ranking/din.py +2 -27
- nextrec/models/ranking/eulernet.py +3 -30
- nextrec/models/ranking/ffm.py +0 -26
- nextrec/models/ranking/fibinet.py +8 -32
- nextrec/models/ranking/fm.py +0 -29
- nextrec/models/ranking/lr.py +0 -30
- nextrec/models/ranking/masknet.py +4 -30
- nextrec/models/ranking/pnn.py +4 -28
- nextrec/models/ranking/widedeep.py +0 -32
- nextrec/models/ranking/xdeepfm.py +0 -30
- nextrec/models/retrieval/dssm.py +4 -28
- nextrec/models/retrieval/dssm_v2.py +4 -28
- nextrec/models/retrieval/mind.py +2 -22
- nextrec/models/retrieval/sdm.py +4 -24
- nextrec/models/retrieval/youtube_dnn.py +4 -25
- nextrec/models/sequential/hstu.py +0 -18
- nextrec/utils/model.py +91 -4
- nextrec/utils/types.py +35 -0
- {nextrec-0.4.22.dist-info → nextrec-0.4.24.dist-info}/METADATA +8 -6
- nextrec-0.4.24.dist-info/RECORD +86 -0
- nextrec-0.4.22.dist-info/RECORD +0 -81
- {nextrec-0.4.22.dist-info → nextrec-0.4.24.dist-info}/WHEEL +0 -0
- {nextrec-0.4.22.dist-info → nextrec-0.4.24.dist-info}/entry_points.txt +0 -0
- {nextrec-0.4.22.dist-info → nextrec-0.4.24.dist-info}/licenses/LICENSE +0 -0
nextrec/models/ranking/deepfm.py
CHANGED
|
@@ -42,8 +42,6 @@ embedding,无需手工构造交叉特征即可端到端训练,常用于 CTR/
|
|
|
42
42
|
- CTR/CVR 任务的常用强基线
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
|
-
import torch.nn as nn
|
|
46
|
-
|
|
47
45
|
from nextrec.basic.features import DenseFeature, SequenceFeature, SparseFeature
|
|
48
46
|
from nextrec.basic.layers import FM, LR, MLP, EmbeddingLayer
|
|
49
47
|
from nextrec.basic.heads import TaskHead
|
|
@@ -65,16 +63,6 @@ class DeepFM(BaseModel):
|
|
|
65
63
|
sparse_features: list[SparseFeature] | None = None,
|
|
66
64
|
sequence_features: list[SequenceFeature] | None = None,
|
|
67
65
|
mlp_params: dict | None = None,
|
|
68
|
-
target: list[str] | str | None = None,
|
|
69
|
-
task: str | list[str] | None = None,
|
|
70
|
-
optimizer: str = "adam",
|
|
71
|
-
optimizer_params: dict | None = None,
|
|
72
|
-
loss: str | nn.Module | None = "bce",
|
|
73
|
-
loss_params: dict | list[dict] | None = None,
|
|
74
|
-
embedding_l1_reg=0.0,
|
|
75
|
-
dense_l1_reg=0.0,
|
|
76
|
-
embedding_l2_reg=0.0,
|
|
77
|
-
dense_l2_reg=0.0,
|
|
78
66
|
**kwargs,
|
|
79
67
|
):
|
|
80
68
|
|
|
@@ -82,24 +70,14 @@ class DeepFM(BaseModel):
|
|
|
82
70
|
sparse_features = sparse_features or []
|
|
83
71
|
sequence_features = sequence_features or []
|
|
84
72
|
mlp_params = mlp_params or {}
|
|
85
|
-
optimizer_params = optimizer_params or {}
|
|
86
|
-
if loss is None:
|
|
87
|
-
loss = "bce"
|
|
88
73
|
|
|
89
74
|
super(DeepFM, self).__init__(
|
|
90
75
|
dense_features=dense_features,
|
|
91
76
|
sparse_features=sparse_features,
|
|
92
77
|
sequence_features=sequence_features,
|
|
93
|
-
target=target,
|
|
94
|
-
task=task or self.default_task,
|
|
95
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
96
|
-
dense_l1_reg=dense_l1_reg,
|
|
97
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
98
|
-
dense_l2_reg=dense_l2_reg,
|
|
99
78
|
**kwargs,
|
|
100
79
|
)
|
|
101
80
|
|
|
102
|
-
self.loss = loss
|
|
103
81
|
self.fm_features = sparse_features + sequence_features
|
|
104
82
|
self.deep_features = dense_features + sparse_features + sequence_features
|
|
105
83
|
self.embedding = EmbeddingLayer(features=self.deep_features)
|
|
@@ -110,18 +88,13 @@ class DeepFM(BaseModel):
|
|
|
110
88
|
self.linear = LR(fm_emb_dim_total)
|
|
111
89
|
self.fm = FM(reduce_sum=True)
|
|
112
90
|
self.mlp = MLP(input_dim=mlp_input_dim, **mlp_params)
|
|
113
|
-
|
|
91
|
+
|
|
92
|
+
self.prediction_layer = TaskHead(task_type=self.task)
|
|
114
93
|
|
|
115
94
|
# Register regularization weights
|
|
116
95
|
self.register_regularization_weights(
|
|
117
96
|
embedding_attr="embedding", include_modules=["linear", "mlp"]
|
|
118
97
|
)
|
|
119
|
-
self.compile(
|
|
120
|
-
optimizer=optimizer,
|
|
121
|
-
optimizer_params=optimizer_params,
|
|
122
|
-
loss=loss,
|
|
123
|
-
loss_params=loss_params,
|
|
124
|
-
)
|
|
125
98
|
|
|
126
99
|
def forward(self, x):
|
|
127
100
|
input_deep = self.embedding(x=x, features=self.deep_features, squeeze_dim=True)
|
nextrec/models/ranking/dien.py
CHANGED
|
@@ -58,6 +58,7 @@ from nextrec.basic.layers import (
|
|
|
58
58
|
)
|
|
59
59
|
from nextrec.basic.heads import TaskHead
|
|
60
60
|
from nextrec.basic.model import BaseModel
|
|
61
|
+
from nextrec.utils.types import ActivationName
|
|
61
62
|
|
|
62
63
|
|
|
63
64
|
class AUGRU(nn.Module):
|
|
@@ -211,19 +212,9 @@ class DIEN(BaseModel):
|
|
|
211
212
|
mlp_params: dict | None = None,
|
|
212
213
|
gru_hidden_size: int = 64,
|
|
213
214
|
attention_hidden_units: list[int] | None = None,
|
|
214
|
-
attention_activation:
|
|
215
|
+
attention_activation: ActivationName = "sigmoid",
|
|
215
216
|
use_negsampling: bool = False,
|
|
216
217
|
aux_loss_weight: float = 1.0,
|
|
217
|
-
target: list[str] | str | None = None,
|
|
218
|
-
task: str | list[str] | None = None,
|
|
219
|
-
optimizer: str = "adam",
|
|
220
|
-
optimizer_params: dict | None = None,
|
|
221
|
-
loss: str | nn.Module | None = "bce",
|
|
222
|
-
loss_params: dict | list[dict] | None = None,
|
|
223
|
-
embedding_l1_reg=0.0,
|
|
224
|
-
dense_l1_reg=0.0,
|
|
225
|
-
embedding_l2_reg=0.0,
|
|
226
|
-
dense_l2_reg=0.0,
|
|
227
218
|
**kwargs,
|
|
228
219
|
):
|
|
229
220
|
|
|
@@ -232,24 +223,14 @@ class DIEN(BaseModel):
|
|
|
232
223
|
sequence_features = sequence_features or []
|
|
233
224
|
mlp_params = mlp_params or {}
|
|
234
225
|
attention_hidden_units = attention_hidden_units or [80, 40]
|
|
235
|
-
optimizer_params = optimizer_params or {}
|
|
236
|
-
if loss is None:
|
|
237
|
-
loss = "bce"
|
|
238
226
|
|
|
239
227
|
super(DIEN, self).__init__(
|
|
240
228
|
dense_features=dense_features,
|
|
241
229
|
sparse_features=sparse_features,
|
|
242
230
|
sequence_features=sequence_features,
|
|
243
|
-
target=target,
|
|
244
|
-
task=task or self.default_task,
|
|
245
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
246
|
-
dense_l1_reg=dense_l1_reg,
|
|
247
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
248
|
-
dense_l2_reg=dense_l2_reg,
|
|
249
231
|
**kwargs,
|
|
250
232
|
)
|
|
251
233
|
|
|
252
|
-
self.loss = loss
|
|
253
234
|
self.use_negsampling = use_negsampling
|
|
254
235
|
self.aux_loss_weight = float(aux_loss_weight)
|
|
255
236
|
self.auxiliary_cache = None
|
|
@@ -361,13 +342,6 @@ class DIEN(BaseModel):
|
|
|
361
342
|
],
|
|
362
343
|
)
|
|
363
344
|
|
|
364
|
-
self.compile(
|
|
365
|
-
optimizer=optimizer,
|
|
366
|
-
optimizer_params=optimizer_params,
|
|
367
|
-
loss=loss,
|
|
368
|
-
loss_params=loss_params,
|
|
369
|
-
)
|
|
370
|
-
|
|
371
345
|
def forward(self, x):
|
|
372
346
|
self.auxiliary_cache = None
|
|
373
347
|
if self.candidate_feature:
|
nextrec/models/ranking/din.py
CHANGED
|
@@ -58,6 +58,7 @@ from nextrec.basic.layers import (
|
|
|
58
58
|
)
|
|
59
59
|
from nextrec.basic.heads import TaskHead
|
|
60
60
|
from nextrec.basic.model import BaseModel
|
|
61
|
+
from nextrec.utils.types import ActivationName
|
|
61
62
|
|
|
62
63
|
|
|
63
64
|
class DIN(BaseModel):
|
|
@@ -78,18 +79,8 @@ class DIN(BaseModel):
|
|
|
78
79
|
candidate_feature_name: str | None = None,
|
|
79
80
|
mlp_params: dict | None = None,
|
|
80
81
|
attention_hidden_units: list[int] | None = None,
|
|
81
|
-
attention_activation:
|
|
82
|
+
attention_activation: ActivationName = "dice",
|
|
82
83
|
attention_use_softmax: bool = True,
|
|
83
|
-
target: list[str] | str | None = None,
|
|
84
|
-
task: str | list[str] | None = None,
|
|
85
|
-
optimizer: str = "adam",
|
|
86
|
-
optimizer_params: dict | None = None,
|
|
87
|
-
loss: str | nn.Module | None = "bce",
|
|
88
|
-
loss_params: dict | list[dict] | None = None,
|
|
89
|
-
embedding_l1_reg=0.0,
|
|
90
|
-
dense_l1_reg=0.0,
|
|
91
|
-
embedding_l2_reg=0.0,
|
|
92
|
-
dense_l2_reg=0.0,
|
|
93
84
|
**kwargs,
|
|
94
85
|
):
|
|
95
86
|
|
|
@@ -98,20 +89,11 @@ class DIN(BaseModel):
|
|
|
98
89
|
sequence_features = sequence_features or []
|
|
99
90
|
mlp_params = mlp_params or {}
|
|
100
91
|
attention_hidden_units = attention_hidden_units or [80, 40]
|
|
101
|
-
optimizer_params = optimizer_params or {}
|
|
102
|
-
if loss is None:
|
|
103
|
-
loss = "bce"
|
|
104
92
|
|
|
105
93
|
super(DIN, self).__init__(
|
|
106
94
|
dense_features=dense_features,
|
|
107
95
|
sparse_features=sparse_features,
|
|
108
96
|
sequence_features=sequence_features,
|
|
109
|
-
target=target,
|
|
110
|
-
task=task or self.default_task,
|
|
111
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
112
|
-
dense_l1_reg=dense_l1_reg,
|
|
113
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
114
|
-
dense_l2_reg=dense_l2_reg,
|
|
115
97
|
**kwargs,
|
|
116
98
|
)
|
|
117
99
|
|
|
@@ -182,13 +164,6 @@ class DIN(BaseModel):
|
|
|
182
164
|
include_modules=["attention", "mlp", "candidate_attention_proj"],
|
|
183
165
|
)
|
|
184
166
|
|
|
185
|
-
self.compile(
|
|
186
|
-
optimizer=optimizer,
|
|
187
|
-
optimizer_params=optimizer_params,
|
|
188
|
-
loss=loss,
|
|
189
|
-
loss_params=loss_params,
|
|
190
|
-
)
|
|
191
|
-
|
|
192
167
|
def forward(self, x):
|
|
193
168
|
# Get candidate item embedding
|
|
194
169
|
if self.candidate_feature is None:
|
|
@@ -32,7 +32,7 @@ EulerNet 使用欧拉公式将特征嵌入映射到复数域,通过复数相
|
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
from __future__ import annotations
|
|
35
|
-
|
|
35
|
+
from typing import Literal
|
|
36
36
|
import torch
|
|
37
37
|
import torch.nn as nn
|
|
38
38
|
import torch.nn.functional as F
|
|
@@ -61,7 +61,7 @@ class EulerInteractionLayer(nn.Module):
|
|
|
61
61
|
num_fields: int,
|
|
62
62
|
num_orders: int,
|
|
63
63
|
use_implicit: bool = True,
|
|
64
|
-
norm:
|
|
64
|
+
norm: Literal["bn", "ln"] | None = "ln", # None | "bn" | "ln"
|
|
65
65
|
eps: float = 1e-9,
|
|
66
66
|
):
|
|
67
67
|
super().__init__()
|
|
@@ -203,42 +203,22 @@ class EulerNet(BaseModel):
|
|
|
203
203
|
num_layers: int = 2,
|
|
204
204
|
num_orders: int = 8,
|
|
205
205
|
use_implicit: bool = True,
|
|
206
|
-
norm:
|
|
206
|
+
norm: Literal["bn", "ln"] | None = "ln",
|
|
207
207
|
use_linear: bool = False,
|
|
208
|
-
target: list[str] | str | None = None,
|
|
209
|
-
task: str | list[str] | None = None,
|
|
210
|
-
optimizer: str = "adam",
|
|
211
|
-
optimizer_params: dict | None = None,
|
|
212
|
-
loss: str | nn.Module | None = "bce",
|
|
213
|
-
loss_params: dict | list[dict] | None = None,
|
|
214
|
-
embedding_l1_reg=0.0,
|
|
215
|
-
dense_l1_reg=0.0,
|
|
216
|
-
embedding_l2_reg=0.0,
|
|
217
|
-
dense_l2_reg=0.0,
|
|
218
208
|
**kwargs,
|
|
219
209
|
):
|
|
220
210
|
|
|
221
211
|
dense_features = dense_features or []
|
|
222
212
|
sparse_features = sparse_features or []
|
|
223
213
|
sequence_features = sequence_features or []
|
|
224
|
-
optimizer_params = optimizer_params or {}
|
|
225
|
-
if loss is None:
|
|
226
|
-
loss = "bce"
|
|
227
214
|
|
|
228
215
|
super(EulerNet, self).__init__(
|
|
229
216
|
dense_features=dense_features,
|
|
230
217
|
sparse_features=sparse_features,
|
|
231
218
|
sequence_features=sequence_features,
|
|
232
|
-
target=target,
|
|
233
|
-
task=task or self.default_task,
|
|
234
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
235
|
-
dense_l1_reg=dense_l1_reg,
|
|
236
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
237
|
-
dense_l2_reg=dense_l2_reg,
|
|
238
219
|
**kwargs,
|
|
239
220
|
)
|
|
240
221
|
|
|
241
|
-
self.loss = loss
|
|
242
222
|
self.use_linear = use_linear
|
|
243
223
|
|
|
244
224
|
self.linear_features = dense_features + sparse_features + sequence_features
|
|
@@ -303,13 +283,6 @@ class EulerNet(BaseModel):
|
|
|
303
283
|
embedding_attr="embedding", include_modules=modules
|
|
304
284
|
)
|
|
305
285
|
|
|
306
|
-
self.compile(
|
|
307
|
-
optimizer=optimizer,
|
|
308
|
-
optimizer_params=optimizer_params,
|
|
309
|
-
loss=loss,
|
|
310
|
-
loss_params=loss_params,
|
|
311
|
-
)
|
|
312
|
-
|
|
313
286
|
def forward(self, x):
|
|
314
287
|
field_emb = self.embedding(
|
|
315
288
|
x=x, features=self.interaction_features, squeeze_dim=False
|
nextrec/models/ranking/ffm.py
CHANGED
|
@@ -63,35 +63,16 @@ class FFM(BaseModel):
|
|
|
63
63
|
dense_features: list[DenseFeature] | None = None,
|
|
64
64
|
sparse_features: list[SparseFeature] | None = None,
|
|
65
65
|
sequence_features: list[SequenceFeature] | None = None,
|
|
66
|
-
target: list[str] | str | None = None,
|
|
67
|
-
task: str | list[str] | None = None,
|
|
68
|
-
optimizer: str = "adam",
|
|
69
|
-
optimizer_params: dict | None = None,
|
|
70
|
-
loss: str | nn.Module | None = "bce",
|
|
71
|
-
loss_params: dict | list[dict] | None = None,
|
|
72
|
-
embedding_l1_reg=0.0,
|
|
73
|
-
dense_l1_reg=0.0,
|
|
74
|
-
embedding_l2_reg=0.0,
|
|
75
|
-
dense_l2_reg=0.0,
|
|
76
66
|
**kwargs,
|
|
77
67
|
):
|
|
78
68
|
dense_features = dense_features or []
|
|
79
69
|
sparse_features = sparse_features or []
|
|
80
70
|
sequence_features = sequence_features or []
|
|
81
|
-
optimizer_params = optimizer_params or {}
|
|
82
|
-
if loss is None:
|
|
83
|
-
loss = "bce"
|
|
84
71
|
|
|
85
72
|
super(FFM, self).__init__(
|
|
86
73
|
dense_features=dense_features,
|
|
87
74
|
sparse_features=sparse_features,
|
|
88
75
|
sequence_features=sequence_features,
|
|
89
|
-
target=target,
|
|
90
|
-
task=task or self.default_task,
|
|
91
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
92
|
-
dense_l1_reg=dense_l1_reg,
|
|
93
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
94
|
-
dense_l2_reg=dense_l2_reg,
|
|
95
76
|
**kwargs,
|
|
96
77
|
)
|
|
97
78
|
|
|
@@ -154,13 +135,6 @@ class FFM(BaseModel):
|
|
|
154
135
|
embedding_attr="field_aware_embeddings", include_modules=["linear_dense"]
|
|
155
136
|
)
|
|
156
137
|
|
|
157
|
-
self.compile(
|
|
158
|
-
optimizer=optimizer,
|
|
159
|
-
optimizer_params=optimizer_params,
|
|
160
|
-
loss=loss,
|
|
161
|
-
loss_params=loss_params,
|
|
162
|
-
)
|
|
163
|
-
|
|
164
138
|
def field_aware_key(
|
|
165
139
|
self, src_feature: SparseFeature | SequenceFeature, target_field
|
|
166
140
|
) -> str:
|
|
@@ -41,8 +41,7 @@ FiBiNET 是一个 CTR 预估模型,通过 SENET 重新分配特征字段的重
|
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
43
|
import torch
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
from typing import Literal
|
|
46
45
|
from nextrec.basic.features import DenseFeature, SequenceFeature, SparseFeature
|
|
47
46
|
from nextrec.basic.layers import (
|
|
48
47
|
LR,
|
|
@@ -71,19 +70,13 @@ class FiBiNET(BaseModel):
|
|
|
71
70
|
sparse_features: list[SparseFeature] | None = None,
|
|
72
71
|
sequence_features: list[SequenceFeature] | None = None,
|
|
73
72
|
mlp_params: dict | None = None,
|
|
74
|
-
interaction_combo:
|
|
75
|
-
|
|
73
|
+
interaction_combo: Literal[
|
|
74
|
+
"01", "11", "10", "00"
|
|
75
|
+
] = "11", # "0": Hadamard, "1": Bilinear
|
|
76
|
+
bilinear_type: Literal[
|
|
77
|
+
"field_all", "field_each", "field_interaction"
|
|
78
|
+
] = "field_interaction",
|
|
76
79
|
senet_reduction: int = 3,
|
|
77
|
-
target: list[str] | str | None = None,
|
|
78
|
-
task: str | list[str] | None = None,
|
|
79
|
-
optimizer: str = "adam",
|
|
80
|
-
optimizer_params: dict | None = None,
|
|
81
|
-
loss: str | nn.Module | None = "bce",
|
|
82
|
-
loss_params: dict | list[dict] | None = None,
|
|
83
|
-
embedding_l1_reg=0.0,
|
|
84
|
-
dense_l1_reg=0.0,
|
|
85
|
-
embedding_l2_reg=0.0,
|
|
86
|
-
dense_l2_reg=0.0,
|
|
87
80
|
**kwargs,
|
|
88
81
|
):
|
|
89
82
|
|
|
@@ -91,24 +84,14 @@ class FiBiNET(BaseModel):
|
|
|
91
84
|
sparse_features = sparse_features or []
|
|
92
85
|
sequence_features = sequence_features or []
|
|
93
86
|
mlp_params = mlp_params or {}
|
|
94
|
-
optimizer_params = optimizer_params or {}
|
|
95
|
-
if loss is None:
|
|
96
|
-
loss = "bce"
|
|
97
87
|
|
|
98
88
|
super(FiBiNET, self).__init__(
|
|
99
89
|
dense_features=dense_features,
|
|
100
90
|
sparse_features=sparse_features,
|
|
101
91
|
sequence_features=sequence_features,
|
|
102
|
-
target=target,
|
|
103
|
-
task=task or self.default_task,
|
|
104
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
105
|
-
dense_l1_reg=dense_l1_reg,
|
|
106
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
107
|
-
dense_l2_reg=dense_l2_reg,
|
|
108
92
|
**kwargs,
|
|
109
93
|
)
|
|
110
94
|
|
|
111
|
-
self.loss = loss
|
|
112
95
|
self.linear_features = sparse_features + sequence_features
|
|
113
96
|
self.interaction_features = sparse_features + sequence_features
|
|
114
97
|
|
|
@@ -166,7 +149,7 @@ class FiBiNET(BaseModel):
|
|
|
166
149
|
num_pairs = self.num_fields * (self.num_fields - 1) // 2
|
|
167
150
|
interaction_dim = num_pairs * self.embedding_dim * 2
|
|
168
151
|
self.mlp = MLP(input_dim=interaction_dim, **mlp_params)
|
|
169
|
-
self.prediction_layer = TaskHead(task_type=self.
|
|
152
|
+
self.prediction_layer = TaskHead(task_type=self.task)
|
|
170
153
|
|
|
171
154
|
# Register regularization weights
|
|
172
155
|
self.register_regularization_weights(
|
|
@@ -180,13 +163,6 @@ class FiBiNET(BaseModel):
|
|
|
180
163
|
],
|
|
181
164
|
)
|
|
182
165
|
|
|
183
|
-
self.compile(
|
|
184
|
-
optimizer=optimizer,
|
|
185
|
-
optimizer_params=optimizer_params,
|
|
186
|
-
loss=loss,
|
|
187
|
-
loss_params=loss_params,
|
|
188
|
-
)
|
|
189
|
-
|
|
190
166
|
def forward(self, x):
|
|
191
167
|
input_linear = self.embedding(
|
|
192
168
|
x=x, features=self.linear_features, squeeze_dim=True
|
nextrec/models/ranking/fm.py
CHANGED
|
@@ -38,8 +38,6 @@ FM 是一种通过分解二阶特征交互矩阵、以线性复杂度建模特
|
|
|
38
38
|
- 结构简单、表现强健,常作 CTR 基线
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
|
-
import torch.nn as nn
|
|
42
|
-
|
|
43
41
|
from nextrec.basic.features import DenseFeature, SequenceFeature, SparseFeature
|
|
44
42
|
from nextrec.basic.layers import FM as FMInteraction
|
|
45
43
|
from nextrec.basic.heads import TaskHead
|
|
@@ -61,16 +59,6 @@ class FM(BaseModel):
|
|
|
61
59
|
dense_features: list[DenseFeature] | None = None,
|
|
62
60
|
sparse_features: list[SparseFeature] | None = None,
|
|
63
61
|
sequence_features: list[SequenceFeature] | None = None,
|
|
64
|
-
target: list[str] | str | None = None,
|
|
65
|
-
task: str | list[str] | None = None,
|
|
66
|
-
optimizer: str = "adam",
|
|
67
|
-
optimizer_params: dict | None = None,
|
|
68
|
-
loss: str | nn.Module | None = "bce",
|
|
69
|
-
loss_params: dict | list[dict] | None = None,
|
|
70
|
-
embedding_l1_reg=0.0,
|
|
71
|
-
dense_l1_reg=0.0,
|
|
72
|
-
embedding_l2_reg=0.0,
|
|
73
|
-
dense_l2_reg=0.0,
|
|
74
62
|
**kwargs,
|
|
75
63
|
):
|
|
76
64
|
|
|
@@ -82,19 +70,9 @@ class FM(BaseModel):
|
|
|
82
70
|
dense_features=dense_features,
|
|
83
71
|
sparse_features=sparse_features,
|
|
84
72
|
sequence_features=sequence_features,
|
|
85
|
-
target=target,
|
|
86
|
-
task=task or self.default_task,
|
|
87
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
88
|
-
dense_l1_reg=dense_l1_reg,
|
|
89
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
90
|
-
dense_l2_reg=dense_l2_reg,
|
|
91
73
|
**kwargs,
|
|
92
74
|
)
|
|
93
75
|
|
|
94
|
-
self.loss = loss
|
|
95
|
-
if self.loss is None:
|
|
96
|
-
self.loss = "bce"
|
|
97
|
-
|
|
98
76
|
self.fm_features = sparse_features + sequence_features
|
|
99
77
|
if len(self.fm_features) == 0:
|
|
100
78
|
raise ValueError("FM requires at least one sparse or sequence feature.")
|
|
@@ -111,13 +89,6 @@ class FM(BaseModel):
|
|
|
111
89
|
embedding_attr="embedding", include_modules=["linear"]
|
|
112
90
|
)
|
|
113
91
|
|
|
114
|
-
self.compile(
|
|
115
|
-
optimizer=optimizer,
|
|
116
|
-
optimizer_params=optimizer_params,
|
|
117
|
-
loss=loss,
|
|
118
|
-
loss_params=loss_params,
|
|
119
|
-
)
|
|
120
|
-
|
|
121
92
|
def forward(self, x):
|
|
122
93
|
input_fm = self.embedding(x=x, features=self.fm_features, squeeze_dim=False)
|
|
123
94
|
y_linear = self.linear(input_fm.flatten(start_dim=1))
|
nextrec/models/ranking/lr.py
CHANGED
|
@@ -38,8 +38,6 @@ LR 是 CTR/排序任务中最经典的线性基线模型。它将稠密、稀疏
|
|
|
38
38
|
- 权重可解释性强
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
|
-
import torch.nn as nn
|
|
42
|
-
|
|
43
41
|
from nextrec.basic.features import DenseFeature, SequenceFeature, SparseFeature
|
|
44
42
|
from nextrec.basic.layers import EmbeddingLayer, LR as LinearLayer
|
|
45
43
|
from nextrec.basic.heads import TaskHead
|
|
@@ -60,41 +58,20 @@ class LR(BaseModel):
|
|
|
60
58
|
dense_features: list[DenseFeature] | None = None,
|
|
61
59
|
sparse_features: list[SparseFeature] | None = None,
|
|
62
60
|
sequence_features: list[SequenceFeature] | None = None,
|
|
63
|
-
target: list[str] | str | None = None,
|
|
64
|
-
task: str | list[str] | None = None,
|
|
65
|
-
optimizer: str = "adam",
|
|
66
|
-
optimizer_params: dict | None = None,
|
|
67
|
-
loss: str | nn.Module | None = "bce",
|
|
68
|
-
loss_params: dict | list[dict] | None = None,
|
|
69
|
-
embedding_l1_reg=0.0,
|
|
70
|
-
dense_l1_reg=0.0,
|
|
71
|
-
embedding_l2_reg=0.0,
|
|
72
|
-
dense_l2_reg=0.0,
|
|
73
61
|
**kwargs,
|
|
74
62
|
):
|
|
75
63
|
|
|
76
64
|
dense_features = dense_features or []
|
|
77
65
|
sparse_features = sparse_features or []
|
|
78
66
|
sequence_features = sequence_features or []
|
|
79
|
-
optimizer_params = optimizer_params or {}
|
|
80
|
-
if loss is None:
|
|
81
|
-
loss = "bce"
|
|
82
67
|
|
|
83
68
|
super(LR, self).__init__(
|
|
84
69
|
dense_features=dense_features,
|
|
85
70
|
sparse_features=sparse_features,
|
|
86
71
|
sequence_features=sequence_features,
|
|
87
|
-
target=target,
|
|
88
|
-
task=task or self.default_task,
|
|
89
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
90
|
-
dense_l1_reg=dense_l1_reg,
|
|
91
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
92
|
-
dense_l2_reg=dense_l2_reg,
|
|
93
72
|
**kwargs,
|
|
94
73
|
)
|
|
95
74
|
|
|
96
|
-
self.loss = loss
|
|
97
|
-
|
|
98
75
|
self.embedding = EmbeddingLayer(features=self.all_features)
|
|
99
76
|
linear_input_dim = self.embedding.input_dim
|
|
100
77
|
self.linear = LinearLayer(linear_input_dim)
|
|
@@ -104,13 +81,6 @@ class LR(BaseModel):
|
|
|
104
81
|
embedding_attr="embedding", include_modules=["linear"]
|
|
105
82
|
)
|
|
106
83
|
|
|
107
|
-
self.compile(
|
|
108
|
-
optimizer=optimizer,
|
|
109
|
-
optimizer_params=optimizer_params,
|
|
110
|
-
loss=loss,
|
|
111
|
-
loss_params=loss_params,
|
|
112
|
-
)
|
|
113
|
-
|
|
114
84
|
def forward(self, x):
|
|
115
85
|
input_linear = self.embedding(x=x, features=self.all_features, squeeze_dim=True)
|
|
116
86
|
y = self.linear(input_linear)
|
|
@@ -56,7 +56,7 @@ embedding 表示生成一个个性化的 “mask” 向量,通过逐元素的
|
|
|
56
56
|
import torch
|
|
57
57
|
import torch.nn as nn
|
|
58
58
|
import torch.nn.functional as F
|
|
59
|
-
|
|
59
|
+
from typing import Literal
|
|
60
60
|
from nextrec.basic.features import DenseFeature, SequenceFeature, SparseFeature
|
|
61
61
|
from nextrec.basic.layers import MLP, EmbeddingLayer
|
|
62
62
|
from nextrec.basic.heads import TaskHead
|
|
@@ -167,48 +167,28 @@ class MaskNet(BaseModel):
|
|
|
167
167
|
dense_features: list[DenseFeature] | None = None,
|
|
168
168
|
sparse_features: list[SparseFeature] | None = None,
|
|
169
169
|
sequence_features: list[SequenceFeature] | None = None,
|
|
170
|
-
architecture:
|
|
170
|
+
architecture: Literal[
|
|
171
|
+
"serial", "parallel"
|
|
172
|
+
] = "parallel", # "serial" or "parallel"
|
|
171
173
|
num_blocks: int = 3,
|
|
172
174
|
mask_hidden_dim: int = 64,
|
|
173
175
|
block_hidden_dim: int = 256,
|
|
174
176
|
block_dropout: float = 0.0,
|
|
175
177
|
mlp_params: dict | None = None,
|
|
176
|
-
target: list[str] | str | None = None,
|
|
177
|
-
task: str | list[str] | None = None,
|
|
178
|
-
optimizer: str = "adam",
|
|
179
|
-
optimizer_params: dict | None = None,
|
|
180
|
-
loss: str | nn.Module | None = "bce",
|
|
181
|
-
loss_params: dict | list[dict] | None = None,
|
|
182
|
-
embedding_l1_reg=0.0,
|
|
183
|
-
dense_l1_reg=0.0,
|
|
184
|
-
embedding_l2_reg=0.0,
|
|
185
|
-
dense_l2_reg=0.0,
|
|
186
178
|
**kwargs,
|
|
187
179
|
):
|
|
188
180
|
dense_features = dense_features or []
|
|
189
181
|
sparse_features = sparse_features or []
|
|
190
182
|
sequence_features = sequence_features or []
|
|
191
|
-
target = target or []
|
|
192
183
|
mlp_params = mlp_params or {}
|
|
193
|
-
optimizer_params = optimizer_params or {}
|
|
194
184
|
|
|
195
185
|
super().__init__(
|
|
196
186
|
dense_features=dense_features,
|
|
197
187
|
sparse_features=sparse_features,
|
|
198
188
|
sequence_features=sequence_features,
|
|
199
|
-
target=target,
|
|
200
|
-
task=task or self.default_task,
|
|
201
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
202
|
-
dense_l1_reg=dense_l1_reg,
|
|
203
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
204
|
-
dense_l2_reg=dense_l2_reg,
|
|
205
189
|
**kwargs,
|
|
206
190
|
)
|
|
207
191
|
|
|
208
|
-
if loss is None:
|
|
209
|
-
loss = "bce"
|
|
210
|
-
self.loss = loss
|
|
211
|
-
|
|
212
192
|
self.dense_features = dense_features
|
|
213
193
|
self.sparse_features = sparse_features
|
|
214
194
|
self.sequence_features = sequence_features
|
|
@@ -293,12 +273,6 @@ class MaskNet(BaseModel):
|
|
|
293
273
|
self.register_regularization_weights(
|
|
294
274
|
embedding_attr="embedding", include_modules=["mask_blocks", "final_mlp"]
|
|
295
275
|
)
|
|
296
|
-
self.compile(
|
|
297
|
-
optimizer=optimizer,
|
|
298
|
-
optimizer_params=optimizer_params,
|
|
299
|
-
loss=loss,
|
|
300
|
-
loss_params=loss_params,
|
|
301
|
-
)
|
|
302
276
|
|
|
303
277
|
def forward(self, x: dict[str, torch.Tensor]) -> torch.Tensor:
|
|
304
278
|
field_emb = self.embedding(x=x, features=self.mask_features, squeeze_dim=False)
|
nextrec/models/ranking/pnn.py
CHANGED
|
@@ -36,7 +36,7 @@ PNN 是一种 CTR 预估模型,通过将线性信号与乘积信号结合,
|
|
|
36
36
|
|
|
37
37
|
import torch
|
|
38
38
|
import torch.nn as nn
|
|
39
|
-
|
|
39
|
+
from typing import Literal
|
|
40
40
|
from nextrec.basic.features import DenseFeature, SequenceFeature, SparseFeature
|
|
41
41
|
from nextrec.basic.layers import MLP, EmbeddingLayer
|
|
42
42
|
from nextrec.basic.heads import TaskHead
|
|
@@ -59,18 +59,10 @@ class PNN(BaseModel):
|
|
|
59
59
|
sparse_features: list[SparseFeature] | None = None,
|
|
60
60
|
sequence_features: list[SequenceFeature] | None = None,
|
|
61
61
|
mlp_params: dict | None = None,
|
|
62
|
-
product_type:
|
|
62
|
+
product_type: Literal[
|
|
63
|
+
"inner", "outer", "both"
|
|
64
|
+
] = "inner", # "inner" (IPNN), "outer" (OPNN), "both" (PNN*)
|
|
63
65
|
outer_product_dim: int | None = None,
|
|
64
|
-
target: list[str] | str | None = None,
|
|
65
|
-
task: str | list[str] | None = None,
|
|
66
|
-
optimizer: str = "adam",
|
|
67
|
-
optimizer_params: dict | None = None,
|
|
68
|
-
loss: str | nn.Module | None = "bce",
|
|
69
|
-
loss_params: dict | list[dict] | None = None,
|
|
70
|
-
embedding_l1_reg=0.0,
|
|
71
|
-
dense_l1_reg=0.0,
|
|
72
|
-
embedding_l2_reg=0.0,
|
|
73
|
-
dense_l2_reg=0.0,
|
|
74
66
|
**kwargs,
|
|
75
67
|
):
|
|
76
68
|
|
|
@@ -80,20 +72,11 @@ class PNN(BaseModel):
|
|
|
80
72
|
mlp_params = mlp_params or {}
|
|
81
73
|
if outer_product_dim is not None and outer_product_dim <= 0:
|
|
82
74
|
raise ValueError("outer_product_dim must be a positive integer.")
|
|
83
|
-
optimizer_params = optimizer_params or {}
|
|
84
|
-
if loss is None:
|
|
85
|
-
loss = "bce"
|
|
86
75
|
|
|
87
76
|
super(PNN, self).__init__(
|
|
88
77
|
dense_features=dense_features,
|
|
89
78
|
sparse_features=sparse_features,
|
|
90
79
|
sequence_features=sequence_features,
|
|
91
|
-
target=target,
|
|
92
|
-
task=task or self.default_task,
|
|
93
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
94
|
-
dense_l1_reg=dense_l1_reg,
|
|
95
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
96
|
-
dense_l2_reg=dense_l2_reg,
|
|
97
80
|
**kwargs,
|
|
98
81
|
)
|
|
99
82
|
|
|
@@ -144,13 +127,6 @@ class PNN(BaseModel):
|
|
|
144
127
|
embedding_attr="embedding", include_modules=modules
|
|
145
128
|
)
|
|
146
129
|
|
|
147
|
-
self.compile(
|
|
148
|
-
optimizer=optimizer,
|
|
149
|
-
optimizer_params=optimizer_params,
|
|
150
|
-
loss=loss,
|
|
151
|
-
loss_params=loss_params,
|
|
152
|
-
)
|
|
153
|
-
|
|
154
130
|
def compute_inner_products(self, field_emb: torch.Tensor) -> torch.Tensor:
|
|
155
131
|
interactions = []
|
|
156
132
|
for i in range(self.num_fields - 1):
|