nextrec 0.4.22__py3-none-any.whl → 0.4.23__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/metrics.py +1 -2
- nextrec/basic/model.py +68 -73
- nextrec/basic/summary.py +36 -2
- 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/esmm.py +3 -26
- nextrec/models/multi_task/mmoe.py +2 -24
- nextrec/models/multi_task/ple.py +13 -35
- nextrec/models/multi_task/poso.py +4 -28
- nextrec/models/multi_task/share_bottom.py +1 -24
- 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 +5 -33
- 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 +0 -24
- nextrec/models/retrieval/dssm_v2.py +0 -24
- nextrec/models/retrieval/mind.py +0 -20
- nextrec/models/retrieval/sdm.py +0 -20
- nextrec/models/retrieval/youtube_dnn.py +0 -21
- nextrec/models/sequential/hstu.py +0 -18
- nextrec/utils/model.py +79 -1
- nextrec/utils/types.py +35 -0
- {nextrec-0.4.22.dist-info → nextrec-0.4.23.dist-info}/METADATA +7 -5
- nextrec-0.4.23.dist-info/RECORD +81 -0
- nextrec-0.4.22.dist-info/RECORD +0 -81
- {nextrec-0.4.22.dist-info → nextrec-0.4.23.dist-info}/WHEEL +0 -0
- {nextrec-0.4.22.dist-info → nextrec-0.4.23.dist-info}/entry_points.txt +0 -0
- {nextrec-0.4.22.dist-info → nextrec-0.4.23.dist-info}/licenses/LICENSE +0 -0
nextrec/models/ranking/dcn_v2.py
CHANGED
|
@@ -45,7 +45,7 @@ DCN v2 在原始 DCN 基础上,将标量交叉权重升级为向量/矩阵参
|
|
|
45
45
|
|
|
46
46
|
import torch
|
|
47
47
|
import torch.nn as nn
|
|
48
|
-
|
|
48
|
+
from typing import Literal
|
|
49
49
|
from nextrec.basic.features import DenseFeature, SequenceFeature, SparseFeature
|
|
50
50
|
from nextrec.basic.layers import MLP, EmbeddingLayer
|
|
51
51
|
from nextrec.basic.heads import TaskHead
|
|
@@ -193,53 +193,32 @@ class DCNv2(BaseModel):
|
|
|
193
193
|
sparse_features: list[SparseFeature] | None = None,
|
|
194
194
|
sequence_features: list[SequenceFeature] | None = None,
|
|
195
195
|
cross_num: int = 3,
|
|
196
|
-
cross_type:
|
|
197
|
-
architecture:
|
|
196
|
+
cross_type: Literal["matrix", "mix", "low_rank"] = "matrix",
|
|
197
|
+
architecture: Literal["parallel", "stacked"] = "parallel",
|
|
198
198
|
low_rank: int = 32,
|
|
199
199
|
num_experts: int = 4,
|
|
200
200
|
mlp_params: dict | None = None,
|
|
201
|
-
target: list[str] | str | None = None,
|
|
202
|
-
task: str | list[str] | None = None,
|
|
203
|
-
optimizer: str = "adam",
|
|
204
|
-
optimizer_params: dict | None = None,
|
|
205
|
-
loss: str | nn.Module | None = "bce",
|
|
206
|
-
loss_params: dict | list[dict] | None = None,
|
|
207
|
-
embedding_l1_reg=0.0,
|
|
208
|
-
dense_l1_reg=0.0,
|
|
209
|
-
embedding_l2_reg=0.0,
|
|
210
|
-
dense_l2_reg=0.0,
|
|
211
201
|
**kwargs,
|
|
212
202
|
):
|
|
213
203
|
dense_features = dense_features or []
|
|
214
204
|
sparse_features = sparse_features or []
|
|
215
205
|
sequence_features = sequence_features or []
|
|
216
|
-
|
|
217
|
-
if loss is None:
|
|
218
|
-
loss = "bce"
|
|
206
|
+
mlp_params = mlp_params or {}
|
|
219
207
|
|
|
220
208
|
super(DCNv2, self).__init__(
|
|
221
209
|
dense_features=dense_features,
|
|
222
210
|
sparse_features=sparse_features,
|
|
223
211
|
sequence_features=sequence_features,
|
|
224
|
-
target=target,
|
|
225
|
-
task=task or self.default_task,
|
|
226
|
-
embedding_l1_reg=embedding_l1_reg,
|
|
227
|
-
dense_l1_reg=dense_l1_reg,
|
|
228
|
-
embedding_l2_reg=embedding_l2_reg,
|
|
229
|
-
dense_l2_reg=dense_l2_reg,
|
|
230
212
|
**kwargs,
|
|
231
213
|
)
|
|
232
214
|
|
|
233
|
-
self.all_features = dense_features + sparse_features + sequence_features
|
|
234
215
|
self.embedding = EmbeddingLayer(features=self.all_features)
|
|
235
216
|
input_dim = self.embedding.input_dim
|
|
236
217
|
|
|
237
|
-
architecture = architecture.lower()
|
|
238
218
|
if architecture not in {"parallel", "stacked"}:
|
|
239
219
|
raise ValueError("architecture must be 'parallel' or 'stacked'.")
|
|
240
220
|
self.architecture = architecture
|
|
241
221
|
|
|
242
|
-
cross_type = cross_type.lower()
|
|
243
222
|
if cross_type == "matrix":
|
|
244
223
|
self.cross_network = CrossNetV2(input_dim=input_dim, num_layers=cross_num)
|
|
245
224
|
elif cross_type in {"mix", "low_rank"}:
|
|
@@ -271,20 +250,13 @@ class DCNv2(BaseModel):
|
|
|
271
250
|
final_input_dim = input_dim
|
|
272
251
|
|
|
273
252
|
self.final_layer = nn.Linear(final_input_dim, 1)
|
|
274
|
-
self.prediction_layer = TaskHead(task_type=self.
|
|
253
|
+
self.prediction_layer = TaskHead(task_type=self.task)
|
|
275
254
|
|
|
276
255
|
self.register_regularization_weights(
|
|
277
256
|
embedding_attr="embedding",
|
|
278
257
|
include_modules=["cross_network", "mlp", "final_layer"],
|
|
279
258
|
)
|
|
280
259
|
|
|
281
|
-
self.compile(
|
|
282
|
-
optimizer=optimizer,
|
|
283
|
-
optimizer_params=optimizer_params,
|
|
284
|
-
loss=loss,
|
|
285
|
-
loss_params=loss_params,
|
|
286
|
-
)
|
|
287
|
-
|
|
288
260
|
def forward(self, x) -> torch.Tensor:
|
|
289
261
|
input_flat = self.embedding(x=x, features=self.all_features, squeeze_dim=True)
|
|
290
262
|
cross_out = self.cross_network(input_flat)
|
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)
|