torch-rechub 0.0.3__py3-none-any.whl → 0.0.5__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.
Files changed (64) hide show
  1. torch_rechub/__init__.py +14 -0
  2. torch_rechub/basic/activation.py +54 -54
  3. torch_rechub/basic/callback.py +33 -33
  4. torch_rechub/basic/features.py +87 -94
  5. torch_rechub/basic/initializers.py +92 -92
  6. torch_rechub/basic/layers.py +994 -720
  7. torch_rechub/basic/loss_func.py +223 -34
  8. torch_rechub/basic/metaoptimizer.py +76 -72
  9. torch_rechub/basic/metric.py +251 -250
  10. torch_rechub/models/generative/__init__.py +6 -0
  11. torch_rechub/models/generative/hllm.py +249 -0
  12. torch_rechub/models/generative/hstu.py +189 -0
  13. torch_rechub/models/matching/__init__.py +13 -11
  14. torch_rechub/models/matching/comirec.py +193 -188
  15. torch_rechub/models/matching/dssm.py +72 -66
  16. torch_rechub/models/matching/dssm_facebook.py +77 -79
  17. torch_rechub/models/matching/dssm_senet.py +28 -16
  18. torch_rechub/models/matching/gru4rec.py +85 -87
  19. torch_rechub/models/matching/mind.py +103 -101
  20. torch_rechub/models/matching/narm.py +82 -76
  21. torch_rechub/models/matching/sasrec.py +143 -140
  22. torch_rechub/models/matching/sine.py +148 -151
  23. torch_rechub/models/matching/stamp.py +81 -83
  24. torch_rechub/models/matching/youtube_dnn.py +75 -71
  25. torch_rechub/models/matching/youtube_sbc.py +98 -98
  26. torch_rechub/models/multi_task/__init__.py +7 -5
  27. torch_rechub/models/multi_task/aitm.py +83 -84
  28. torch_rechub/models/multi_task/esmm.py +56 -55
  29. torch_rechub/models/multi_task/mmoe.py +58 -58
  30. torch_rechub/models/multi_task/ple.py +116 -130
  31. torch_rechub/models/multi_task/shared_bottom.py +45 -45
  32. torch_rechub/models/ranking/__init__.py +14 -11
  33. torch_rechub/models/ranking/afm.py +65 -63
  34. torch_rechub/models/ranking/autoint.py +102 -0
  35. torch_rechub/models/ranking/bst.py +61 -63
  36. torch_rechub/models/ranking/dcn.py +38 -38
  37. torch_rechub/models/ranking/dcn_v2.py +59 -69
  38. torch_rechub/models/ranking/deepffm.py +131 -123
  39. torch_rechub/models/ranking/deepfm.py +43 -42
  40. torch_rechub/models/ranking/dien.py +191 -191
  41. torch_rechub/models/ranking/din.py +93 -91
  42. torch_rechub/models/ranking/edcn.py +101 -117
  43. torch_rechub/models/ranking/fibinet.py +42 -50
  44. torch_rechub/models/ranking/widedeep.py +41 -41
  45. torch_rechub/trainers/__init__.py +4 -3
  46. torch_rechub/trainers/ctr_trainer.py +288 -128
  47. torch_rechub/trainers/match_trainer.py +336 -170
  48. torch_rechub/trainers/matching.md +3 -0
  49. torch_rechub/trainers/mtl_trainer.py +356 -207
  50. torch_rechub/trainers/seq_trainer.py +427 -0
  51. torch_rechub/utils/data.py +492 -360
  52. torch_rechub/utils/hstu_utils.py +198 -0
  53. torch_rechub/utils/match.py +457 -274
  54. torch_rechub/utils/model_utils.py +233 -0
  55. torch_rechub/utils/mtl.py +136 -126
  56. torch_rechub/utils/onnx_export.py +220 -0
  57. torch_rechub/utils/visualization.py +271 -0
  58. torch_rechub-0.0.5.dist-info/METADATA +402 -0
  59. torch_rechub-0.0.5.dist-info/RECORD +64 -0
  60. {torch_rechub-0.0.3.dist-info → torch_rechub-0.0.5.dist-info}/WHEEL +1 -2
  61. {torch_rechub-0.0.3.dist-info → torch_rechub-0.0.5.dist-info/licenses}/LICENSE +21 -21
  62. torch_rechub-0.0.3.dist-info/METADATA +0 -177
  63. torch_rechub-0.0.3.dist-info/RECORD +0 -55
  64. torch_rechub-0.0.3.dist-info/top_level.txt +0 -1
@@ -1,63 +1,61 @@
1
- """
2
- Date: create on 26/02/2024, update on 30/04/2022
3
- References:
4
- paper: Behavior Sequence Transformer for E-commerce Recommendation in Alibaba
5
- url: https://arxiv.org/pdf/1905.06874
6
- code: https://github.com/jiwidi/Behavior-Sequence-Transformer-Pytorch/blob/master/pytorch_bst.ipynb
7
- Authors: Tao Fan, thisisevy@foxmail.com
8
- """
9
-
10
- import torch
11
- import torch.nn as nn
12
-
13
- from ...basic.layers import EmbeddingLayer, MLP
14
-
15
-
16
- class BST(nn.Module):
17
- """Behavior Sequence Transformer
18
- Args:
19
- features (list): the list of `Feature Class`. training by MLP. It means the user profile features and context features in origin paper, exclude history and target features.
20
- history_features (list): the list of `Feature Class`,training by ActivationUnit. It means the user behaviour sequence features, eg.item id sequence, shop id sequence.
21
- target_features (list): the list of `Feature Class`, training by ActivationUnit. It means the target feature which will execute target-attention with history feature.
22
- mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}.
23
- nhead (int): the number of heads in the multi-head-attention models.
24
- dropout (float): the dropout value in the multi-head-attention models.
25
- num_layers (Any): the number of sub-encoder-layers in the encoder.
26
- """
27
-
28
- def __init__(self, features, history_features, target_features, mlp_params, nhead=8, dropout=0.2, num_layers=1):
29
- super().__init__()
30
- self.features = features
31
- self.history_features = history_features
32
- self.target_features = target_features
33
- self.num_history_features = len(history_features)
34
- self.embed_dim = target_features[0].embed_dim
35
- self.seq_len = 50
36
- # TODO 在 'torch_rechub.basic.features.SequenceFeature' 中加入seq_len属性
37
- self.all_dims = (len(features) + len(history_features) * (self.seq_len + len(target_features))) * self.embed_dim
38
- self.embedding = EmbeddingLayer(features + history_features + target_features)
39
- self.encoder_layer = nn.TransformerEncoderLayer(d_model=self.embed_dim, nhead=nhead, dropout=dropout)
40
- self.transformer_layers = nn.TransformerEncoder(self.encoder_layer, num_layers=num_layers)
41
- self.mlp = MLP(self.all_dims, activation="leakyrelu",
42
- **mlp_params) # # 定义模型,模型的参数需要我们之前的feature类,用于构建模型的输入层,mlp指定模型后续DNN的结构
43
-
44
- def forward(self, x):
45
- embed_x_features = self.embedding(x, self.features) # (batch_size, num_features, emb_dim)
46
- embed_x_history = self.embedding(x,
47
- self.history_features) # (batch_size, num_history_features, seq_length, emb_dim)
48
- embed_x_target = self.embedding(x, self.target_features) # (batch_size, num_target_features, emb_dim)
49
- attention_pooling = []
50
- for i in range(self.num_history_features):
51
- attention_seq = self.transformer_layers(
52
- torch.cat([torch.squeeze(embed_x_history[:, i, :, :], 1), embed_x_target], dim=1))
53
- attention_pooling.append(attention_seq) # (batch_size, seq_length + num_target_features, emb_dim)
54
- attention_pooling = torch.cat(attention_pooling,
55
- dim=1) # (batch_size, num_history_features * (seq_length + num_target_features), emb_dim)
56
-
57
- mlp_in = torch.cat([
58
- attention_pooling.flatten(start_dim=1),
59
- embed_x_features.flatten(start_dim=1)
60
- ],
61
- dim=1) # (batch_size, N)
62
- y = self.mlp(mlp_in)
63
- return torch.sigmoid(y.squeeze(1))
1
+ """
2
+ Date: create on 26/02/2024, update on 30/04/2022
3
+ References:
4
+ paper: Behavior Sequence Transformer for E-commerce Recommendation in Alibaba
5
+ url: https://arxiv.org/pdf/1905.06874
6
+ code: https://github.com/jiwidi/Behavior-Sequence-Transformer-Pytorch/blob/master/pytorch_bst.ipynb
7
+ Authors: Tao Fan, thisisevy@foxmail.com
8
+ """
9
+
10
+ import torch
11
+ import torch.nn as nn
12
+
13
+ from ...basic.layers import MLP, EmbeddingLayer
14
+
15
+
16
+ class BST(nn.Module):
17
+ """Behavior Sequence Transformer
18
+ Args:
19
+ features (list): the list of `Feature Class`. training by MLP. It means the user profile features and context features in origin paper, exclude history and target features.
20
+ history_features (list): the list of `Feature Class`,training by ActivationUnit. It means the user behaviour sequence features, eg.item id sequence, shop id sequence.
21
+ target_features (list): the list of `Feature Class`, training by ActivationUnit. It means the target feature which will execute target-attention with history feature.
22
+ mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}.
23
+ nhead (int): the number of heads in the multi-head-attention models.
24
+ dropout (float): the dropout value in the multi-head-attention models.
25
+ num_layers (Any): the number of sub-encoder-layers in the encoder.
26
+ """
27
+
28
+ def __init__(self, features, history_features, target_features, mlp_params, nhead=8, dropout=0.2, num_layers=1):
29
+ super().__init__()
30
+ self.features = features
31
+ self.history_features = history_features
32
+ self.target_features = target_features
33
+ self.num_history_features = len(history_features)
34
+ self.embed_dim = target_features[0].embed_dim
35
+ self.seq_len = 50
36
+ # TODO 在 'torch_rechub.basic.features.SequenceFeature' 中加入seq_len属性
37
+ self.all_dims = (len(features) + len(history_features) * (self.seq_len + len(target_features))) * self.embed_dim
38
+ self.embedding = EmbeddingLayer(features + history_features + target_features)
39
+ self.encoder_layer = nn.TransformerEncoderLayer(d_model=self.embed_dim, nhead=nhead, dropout=dropout)
40
+ self.transformer_layers = nn.TransformerEncoder(self.encoder_layer, num_layers=num_layers)
41
+ # # 定义模型,模型的参数需要我们之前的feature类,用于构建模型的输入层,mlp指定模型后续DNN的结构
42
+ self.mlp = MLP(self.all_dims, activation="leakyrelu", **mlp_params)
43
+
44
+ def forward(self, x):
45
+ # (batch_size, num_features, emb_dim)
46
+ embed_x_features = self.embedding(x, self.features)
47
+ # (batch_size, num_history_features, seq_length, emb_dim)
48
+ embed_x_history = self.embedding(x, self.history_features)
49
+ # (batch_size, num_target_features, emb_dim)
50
+ embed_x_target = self.embedding(x, self.target_features)
51
+ attention_pooling = []
52
+ for i in range(self.num_history_features):
53
+ attention_seq = self.transformer_layers(torch.cat([torch.squeeze(embed_x_history[:, i, :, :], 1), embed_x_target], dim=1))
54
+ # (batch_size, seq_length + num_target_features, emb_dim)
55
+ attention_pooling.append(attention_seq)
56
+ # (batch_size, num_history_features * (seq_length + num_target_features), emb_dim)
57
+ attention_pooling = torch.cat(attention_pooling, dim=1)
58
+
59
+ mlp_in = torch.cat([attention_pooling.flatten(start_dim=1), embed_x_features.flatten(start_dim=1)], dim=1) # (batch_size, N)
60
+ y = self.mlp(mlp_in)
61
+ return torch.sigmoid(y.squeeze(1))
@@ -1,38 +1,38 @@
1
- """
2
- Date: create on 12/05/2022
3
- References:
4
- paper: (AKDD'2017) Deep & Cross Network for Ad Click Predictions
5
- url: https://arxiv.org/abs/1708.05123
6
- Authors: Mincai Lai, laimincai@shanghaitech.edu.cn
7
- """
8
-
9
- import torch
10
-
11
- from ...basic.layers import LR, MLP, CrossNetwork, EmbeddingLayer
12
-
13
-
14
- class DCN(torch.nn.Module):
15
- """Deep & Cross Network
16
-
17
- Args:
18
- features (list[Feature Class]): training by the whole module.
19
- mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}
20
- """
21
-
22
- def __init__(self, features, n_cross_layers, mlp_params):
23
- super().__init__()
24
- self.features = features
25
- self.dims = sum([fea.embed_dim for fea in features])
26
-
27
- self.embedding = EmbeddingLayer(features)
28
- self.cn = CrossNetwork(self.dims, n_cross_layers)
29
- self.mlp = MLP(self.dims, output_layer=False, **mlp_params)
30
- self.linear = LR(self.dims + mlp_params["dims"][-1])
31
-
32
- def forward(self, x):
33
- embed_x = self.embedding(x, self.features, squeeze_dim=True)
34
- cn_out = self.cn(embed_x)
35
- mlp_out = self.mlp(embed_x)
36
- x_stack = torch.cat([cn_out, mlp_out], dim=1)
37
- y = self.linear(x_stack)
38
- return torch.sigmoid(y.squeeze(1))
1
+ """
2
+ Date: create on 12/05/2022
3
+ References:
4
+ paper: (AKDD'2017) Deep & Cross Network for Ad Click Predictions
5
+ url: https://arxiv.org/abs/1708.05123
6
+ Authors: Mincai Lai, laimincai@shanghaitech.edu.cn
7
+ """
8
+
9
+ import torch
10
+
11
+ from ...basic.layers import LR, MLP, CrossNetwork, EmbeddingLayer
12
+
13
+
14
+ class DCN(torch.nn.Module):
15
+ """Deep & Cross Network
16
+
17
+ Args:
18
+ features (list[Feature Class]): training by the whole module.
19
+ mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}
20
+ """
21
+
22
+ def __init__(self, features, n_cross_layers, mlp_params):
23
+ super().__init__()
24
+ self.features = features
25
+ self.dims = sum([fea.embed_dim for fea in features])
26
+
27
+ self.embedding = EmbeddingLayer(features)
28
+ self.cn = CrossNetwork(self.dims, n_cross_layers)
29
+ self.mlp = MLP(self.dims, output_layer=False, **mlp_params)
30
+ self.linear = LR(self.dims + mlp_params["dims"][-1])
31
+
32
+ def forward(self, x):
33
+ embed_x = self.embedding(x, self.features, squeeze_dim=True)
34
+ cn_out = self.cn(embed_x)
35
+ mlp_out = self.mlp(embed_x)
36
+ x_stack = torch.cat([cn_out, mlp_out], dim=1)
37
+ y = self.linear(x_stack)
38
+ return torch.sigmoid(y.squeeze(1))
@@ -1,69 +1,59 @@
1
- """
2
- Date: create on 09/01/2022
3
- References:
4
- paper: (WWW'21) Dcn v2: Improved deep & cross network and practical lessons for web-scale learning to rank systems
5
- url: https://arxiv.org/abs/2008.13535
6
- Authors: lailai, lailai_zxy@tju.edu.cn
7
- """
8
- import torch
9
- from ...basic.layers import LR, MLP,CrossNetV2, CrossNetMix, EmbeddingLayer
10
-
11
- class DCNv2(torch.nn.Module):
12
- """Deep & Cross Network with a mixture of low-rank architecture
13
-
14
- Args:
15
- features (list[Feature Class]): training by the whole module.
16
- n_cross_layers (int) : the number of layers of feature intersection layers
17
- mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}
18
- use_low_rank_mixture (bool): True, whether to use a mixture of low-rank architecture
19
- low_rank (int): the rank size of low-rank matrices
20
- num_experts (int): the number of expert networks
21
- """
22
- def __init__(self,
23
- features,
24
- n_cross_layers,
25
- mlp_params,
26
- model_structure="parallel",
27
- use_low_rank_mixture=True,
28
- low_rank=32,
29
- num_experts=4,
30
- **kwargs):
31
- super(DCNv2, self).__init__()
32
- self.features = features
33
- self.dims = sum([fea.embed_dim for fea in features])
34
- self.embedding = EmbeddingLayer(features)
35
- if use_low_rank_mixture:
36
- self.crossnet = CrossNetMix(self.dims, n_cross_layers, low_rank=low_rank, num_experts=num_experts)
37
- else:
38
- self.crossnet = CrossNetV2(self.dims, n_cross_layers)
39
- self.model_structure = model_structure
40
- assert self.model_structure in ["crossnet_only", "stacked", "parallel"], \
41
- "model_structure={} not supported!".format(self.model_structure)
42
- if self.model_structure == "stacked":
43
- self.stacked_dnn = MLP(self.dims,
44
- output_layer=False,
45
- ** mlp_params)
46
- final_dim = mlp_params["dims"][-1]
47
- if self.model_structure == "parallel":
48
- self.parallel_dnn = MLP(self.dims,
49
- output_layer = False,
50
- ** mlp_params)
51
- final_dim = mlp_params["dims"][-1] + self.dims
52
- if self.model_structure == "crossnet_only": # only CrossNet
53
- final_dim = self.dims
54
- self.linear = LR(final_dim)
55
-
56
-
57
- def forward(self, x):
58
- embed_x = self.embedding(x, self.features, squeeze_dim=True)
59
- cross_out = self.crossnet(embed_x)
60
- if self.model_structure == "crossnet_only":
61
- final_out = cross_out
62
- elif self.model_structure == "stacked":
63
- final_out = self.stacked_dnn(cross_out)
64
- elif self.model_structure == "parallel":
65
- dnn_out = self.parallel_dnn(embed_x)
66
- final_out = torch.cat([cross_out, dnn_out], dim=1)
67
- y_pred = self.linear(final_out)
68
- y_pred = torch.sigmoid(y_pred.squeeze(1))
69
- return y_pred
1
+ """
2
+ Date: create on 09/01/2022
3
+ References:
4
+ paper: (WWW'21) Dcn v2: Improved deep & cross network and practical lessons for web-scale learning to rank systems
5
+ url: https://arxiv.org/abs/2008.13535
6
+ Authors: lailai, lailai_zxy@tju.edu.cn
7
+ """
8
+ import torch
9
+
10
+ from ...basic.layers import LR, MLP, CrossNetMix, CrossNetV2, EmbeddingLayer
11
+
12
+
13
+ class DCNv2(torch.nn.Module):
14
+ """Deep & Cross Network with a mixture of low-rank architecture
15
+
16
+ Args:
17
+ features (list[Feature Class]): training by the whole module.
18
+ n_cross_layers (int) : the number of layers of feature intersection layers
19
+ mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}
20
+ use_low_rank_mixture (bool): True, whether to use a mixture of low-rank architecture
21
+ low_rank (int): the rank size of low-rank matrices
22
+ num_experts (int): the number of expert networks
23
+ """
24
+
25
+ def __init__(self, features, n_cross_layers, mlp_params, model_structure="parallel", use_low_rank_mixture=True, low_rank=32, num_experts=4, **kwargs):
26
+ super(DCNv2, self).__init__()
27
+ self.features = features
28
+ self.dims = sum([fea.embed_dim for fea in features])
29
+ self.embedding = EmbeddingLayer(features)
30
+ if use_low_rank_mixture:
31
+ self.crossnet = CrossNetMix(self.dims, n_cross_layers, low_rank=low_rank, num_experts=num_experts)
32
+ else:
33
+ self.crossnet = CrossNetV2(self.dims, n_cross_layers)
34
+ self.model_structure = model_structure
35
+ assert self.model_structure in ["crossnet_only", "stacked", "parallel"], \
36
+ "model_structure={} not supported!".format(self.model_structure)
37
+ if self.model_structure == "stacked":
38
+ self.stacked_dnn = MLP(self.dims, output_layer=False, **mlp_params)
39
+ final_dim = mlp_params["dims"][-1]
40
+ if self.model_structure == "parallel":
41
+ self.parallel_dnn = MLP(self.dims, output_layer=False, **mlp_params)
42
+ final_dim = mlp_params["dims"][-1] + self.dims
43
+ if self.model_structure == "crossnet_only": # only CrossNet
44
+ final_dim = self.dims
45
+ self.linear = LR(final_dim)
46
+
47
+ def forward(self, x):
48
+ embed_x = self.embedding(x, self.features, squeeze_dim=True)
49
+ cross_out = self.crossnet(embed_x)
50
+ if self.model_structure == "crossnet_only":
51
+ final_out = cross_out
52
+ elif self.model_structure == "stacked":
53
+ final_out = self.stacked_dnn(cross_out)
54
+ elif self.model_structure == "parallel":
55
+ dnn_out = self.parallel_dnn(embed_x)
56
+ final_out = torch.cat([cross_out, dnn_out], dim=1)
57
+ y_pred = self.linear(final_out)
58
+ y_pred = torch.sigmoid(y_pred.squeeze(1))
59
+ return y_pred
@@ -1,123 +1,131 @@
1
- """
2
- Date: created on 31/07/2022
3
- References:
4
- paper: FAT-DeepFFM: Field Attentive Deep Field-aware Factorization Machine
5
- url: https://arxiv.org/abs/1905.06336
6
- Authors: Bo Kang, klinux@live.com
7
- """
8
-
9
- import torch
10
- import torch.nn as nn
11
-
12
- from ...basic.layers import CEN, EmbeddingLayer, FFM, MLP
13
-
14
-
15
- class DeepFFM(nn.Module):
16
- """The DeepFFM model, mentioned on the `webpage
17
- <https://cs.nju.edu.cn/31/60/c1654a209248/page.htm>` which is the first
18
- work that introduces FFM model into neural CTR system. It is also described
19
- in the `FAT-DeepFFM paper <https://arxiv.org/abs/1905.06336>`.
20
-
21
- Args:
22
- linear_features (list): the list of `Feature Class`, fed to the linear module.
23
- cross_features (list): the list of `Feature Class`, fed to the ffm module.
24
- embed_dim (int): the dimensionality of categorical value embedding.
25
- mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}
26
- """
27
- def __init__(self, linear_features, cross_features, embed_dim, mlp_params):
28
- super().__init__()
29
- self.linear_features = linear_features
30
- self.cross_features = cross_features
31
-
32
- self.num_fields = len(cross_features)
33
- self.num_field_cross = self.num_fields * (self.num_fields - 1) // 2
34
-
35
- self.ffm = FFM(num_fields=self.num_fields, reduce_sum=False)
36
- self.mlp_out = MLP(self.num_field_cross * embed_dim, **mlp_params)
37
-
38
- self.linear_embedding = EmbeddingLayer(linear_features)
39
- self.ffm_embedding = EmbeddingLayer(cross_features)
40
-
41
- self.b =torch.nn.Parameter(torch.zeros(1))
42
-
43
- # This keeping constant value in module on correct device
44
- # url: https://discuss.pytorch.org/t/keeping-constant-value-in-module-on-correct-device/10129
45
- fields_offset = torch.arange(0, self.num_fields, dtype=torch.long)
46
- self.register_buffer('fields_offset', fields_offset)
47
-
48
-
49
- def forward(self, x):
50
- # compute scores from the linear part of the model, where input is the raw features (Eq. 5, FAT-DeepFFM)
51
- y_linear = self.linear_embedding(x, self.linear_features, squeeze_dim=True).sum(1, keepdim=True) #[batch_size, 1]
52
-
53
- # gather the embeddings. Each feature value corresponds to multiple embeddings, with multiplicity equal to number of features/fields.
54
- # output shape [batch_size, num_field, num_field, emb_dim]
55
- x_ffm = {fea.name: x[fea.name].unsqueeze(1) * self.num_fields + self.fields_offset for fea in self.cross_features}
56
- input_ffm = self.ffm_embedding(x_ffm, self.cross_features, squeeze_dim=False)
57
-
58
- # compute second order field-aware feature crossings, output shape [batch_size, num_field_cross, emb_dim]
59
- em = self.ffm(input_ffm)
60
-
61
- # compute scores from the ffm part of the model, output shape [batch_size, 1]
62
- y_ffm = self.mlp_out(em.flatten(start_dim=1))
63
-
64
- # compute final prediction
65
- y = y_linear + y_ffm
66
- return torch.sigmoid(y.squeeze(1) + self.b)
67
-
68
-
69
- class FatDeepFFM(nn.Module):
70
- """The FAT-DeepFFM model, mentioned in the `FAT-DeepFFM paper
71
- <https://arxiv.org/abs/1905.06336>`. It combines DeepFFM with
72
- Compose-Excitation Network (CENet) field attention mechanism
73
- to highlight the importance of second-order feature crosses.
74
-
75
- Args:
76
- linear_features (list): the list of `Feature Class`, fed to the linear module.
77
- cross_features (list): the list of `Feature Class`, fed to the ffm module.
78
- embed_dim (int): the dimensionality of categorical value embedding.
79
- reduction_ratio (int): the between the dimensions of input layer and hidden layer of the CEN MLP module.
80
- mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}
81
- """
82
-
83
- def __init__(self, linear_features, cross_features, embed_dim, reduction_ratio, mlp_params):
84
- super().__init__()
85
- self.linear_features = linear_features
86
- self.cross_features = cross_features
87
-
88
- self.num_fields = len(cross_features)
89
- self.num_field_cross = self.num_fields * (self.num_fields - 1) // 2
90
-
91
- self.ffm = FFM(num_fields=self.num_fields, reduce_sum=False)
92
- self.cen = CEN(embed_dim, self.num_field_cross, reduction_ratio)
93
- self.mlp_out = MLP(self.num_field_cross * embed_dim, **mlp_params)
94
-
95
- self.linear_embedding = EmbeddingLayer(linear_features)
96
- self.ffm_embedding = EmbeddingLayer(cross_features)
97
-
98
- self.b =torch.nn.Parameter(torch.zeros(1))
99
-
100
- fields_offset = torch.arange(0, self.num_fields, dtype=torch.long)
101
- self.register_buffer('fields_offset', fields_offset)
102
-
103
- def forward(self, x):
104
- # compute scores from the linear part of the model, where input is the raw features (Eq. 5, FAT-DeepFFM)
105
- y_linear = self.linear_embedding(x, self.linear_features, squeeze_dim=True).sum(1, keepdim=True) #[batch_size, 1]
106
-
107
- # gather the embeddings. Each feature value corresponds to multiple embeddings, with multiplicity is equal to the number of features/fields.
108
- # output shape [batch_size, num_field, num_field, emb_dim]
109
- x_ffm = {fea.name: x[fea.name].unsqueeze(1) * self.num_fields + self.fields_offset for fea in self.cross_features}
110
- input_ffm = self.ffm_embedding(x_ffm, self.cross_features, squeeze_dim=False)
111
-
112
- # compute second order field-aware feature crossings, output shape [batch_size, num_field_cross, emb_dim]
113
- em = self.ffm(input_ffm)
114
-
115
- # rescale FFM embeddings with field attention (Eq.10), output shape [batch_size, num_field_cross * emb_dim]
116
- aem = self.cen(em)
117
-
118
- # compute scores from the ffm part of the model, output shape [batch_size, 1]
119
- y_ffm = self.mlp_out(aem)
120
-
121
- # compute final prediction
122
- y = y_linear + y_ffm
123
- return torch.sigmoid(y.squeeze(1) + self.b)
1
+ """
2
+ Date: created on 31/07/2022
3
+ References:
4
+ paper: FAT-DeepFFM: Field Attentive Deep Field-aware Factorization Machine
5
+ url: https://arxiv.org/abs/1905.06336
6
+ Authors: Bo Kang, klinux@live.com
7
+ """
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+
12
+ from ...basic.layers import CEN, FFM, MLP, EmbeddingLayer
13
+
14
+
15
+ class DeepFFM(nn.Module):
16
+ """The DeepFFM model, mentioned on the `webpage
17
+ <https://cs.nju.edu.cn/31/60/c1654a209248/page.htm>` which is the first
18
+ work that introduces FFM model into neural CTR system. It is also described
19
+ in the `FAT-DeepFFM paper <https://arxiv.org/abs/1905.06336>`.
20
+
21
+ Args:
22
+ linear_features (list): the list of `Feature Class`, fed to the linear module.
23
+ cross_features (list): the list of `Feature Class`, fed to the ffm module.
24
+ embed_dim (int): the dimensionality of categorical value embedding.
25
+ mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}
26
+ """
27
+
28
+ def __init__(self, linear_features, cross_features, embed_dim, mlp_params):
29
+ super().__init__()
30
+ self.linear_features = linear_features
31
+ self.cross_features = cross_features
32
+
33
+ self.num_fields = len(cross_features)
34
+ self.num_field_cross = self.num_fields * (self.num_fields - 1) // 2
35
+
36
+ self.ffm = FFM(num_fields=self.num_fields, reduce_sum=False)
37
+ self.mlp_out = MLP(self.num_field_cross * embed_dim, **mlp_params)
38
+
39
+ self.linear_embedding = EmbeddingLayer(linear_features)
40
+ self.ffm_embedding = EmbeddingLayer(cross_features)
41
+
42
+ self.b = torch.nn.Parameter(torch.zeros(1))
43
+
44
+ # This keeping constant value in module on correct device
45
+ # url:
46
+ # https://discuss.pytorch.org/t/keeping-constant-value-in-module-on-correct-device/10129
47
+ fields_offset = torch.arange(0, self.num_fields, dtype=torch.long)
48
+ self.register_buffer('fields_offset', fields_offset)
49
+
50
+ def forward(self, x):
51
+ # compute scores from the linear part of the model, where input is the
52
+ # raw features (Eq. 5, FAT-DeepFFM)
53
+ y_linear = self.linear_embedding(x, self.linear_features, squeeze_dim=True).sum(1, keepdim=True) # [batch_size, 1]
54
+
55
+ # gather the embeddings. Each feature value corresponds to multiple embeddings, with multiplicity equal to number of features/fields.
56
+ # output shape [batch_size, num_field, num_field, emb_dim]
57
+ x_ffm = {fea.name: x[fea.name].unsqueeze(1) * self.num_fields + self.fields_offset for fea in self.cross_features}
58
+ input_ffm = self.ffm_embedding(x_ffm, self.cross_features, squeeze_dim=False)
59
+
60
+ # compute second order field-aware feature crossings, output shape
61
+ # [batch_size, num_field_cross, emb_dim]
62
+ em = self.ffm(input_ffm)
63
+
64
+ # compute scores from the ffm part of the model, output shape
65
+ # [batch_size, 1]
66
+ y_ffm = self.mlp_out(em.flatten(start_dim=1))
67
+
68
+ # compute final prediction
69
+ y = y_linear + y_ffm
70
+ return torch.sigmoid(y.squeeze(1) + self.b)
71
+
72
+
73
+ class FatDeepFFM(nn.Module):
74
+ """The FAT-DeepFFM model, mentioned in the `FAT-DeepFFM paper
75
+ <https://arxiv.org/abs/1905.06336>`. It combines DeepFFM with
76
+ Compose-Excitation Network (CENet) field attention mechanism
77
+ to highlight the importance of second-order feature crosses.
78
+
79
+ Args:
80
+ linear_features (list): the list of `Feature Class`, fed to the linear module.
81
+ cross_features (list): the list of `Feature Class`, fed to the ffm module.
82
+ embed_dim (int): the dimensionality of categorical value embedding.
83
+ reduction_ratio (int): the between the dimensions of input layer and hidden layer of the CEN MLP module.
84
+ mlp_params (dict): the params of the last MLP module, keys include:`{"dims":list, "activation":str, "dropout":float, "output_layer":bool`}
85
+ """
86
+
87
+ def __init__(self, linear_features, cross_features, embed_dim, reduction_ratio, mlp_params):
88
+ super().__init__()
89
+ self.linear_features = linear_features
90
+ self.cross_features = cross_features
91
+
92
+ self.num_fields = len(cross_features)
93
+ self.num_field_cross = self.num_fields * (self.num_fields - 1) // 2
94
+
95
+ self.ffm = FFM(num_fields=self.num_fields, reduce_sum=False)
96
+ self.cen = CEN(embed_dim, self.num_field_cross, reduction_ratio)
97
+ self.mlp_out = MLP(self.num_field_cross * embed_dim, **mlp_params)
98
+
99
+ self.linear_embedding = EmbeddingLayer(linear_features)
100
+ self.ffm_embedding = EmbeddingLayer(cross_features)
101
+
102
+ self.b = torch.nn.Parameter(torch.zeros(1))
103
+
104
+ fields_offset = torch.arange(0, self.num_fields, dtype=torch.long)
105
+ self.register_buffer('fields_offset', fields_offset)
106
+
107
+ def forward(self, x):
108
+ # compute scores from the linear part of the model, where input is the
109
+ # raw features (Eq. 5, FAT-DeepFFM)
110
+ y_linear = self.linear_embedding(x, self.linear_features, squeeze_dim=True).sum(1, keepdim=True) # [batch_size, 1]
111
+
112
+ # gather the embeddings. Each feature value corresponds to multiple embeddings, with multiplicity is equal to the number of features/fields.
113
+ # output shape [batch_size, num_field, num_field, emb_dim]
114
+ x_ffm = {fea.name: x[fea.name].unsqueeze(1) * self.num_fields + self.fields_offset for fea in self.cross_features}
115
+ input_ffm = self.ffm_embedding(x_ffm, self.cross_features, squeeze_dim=False)
116
+
117
+ # compute second order field-aware feature crossings, output shape
118
+ # [batch_size, num_field_cross, emb_dim]
119
+ em = self.ffm(input_ffm)
120
+
121
+ # rescale FFM embeddings with field attention (Eq.10), output shape
122
+ # [batch_size, num_field_cross * emb_dim]
123
+ aem = self.cen(em)
124
+
125
+ # compute scores from the ffm part of the model, output shape
126
+ # [batch_size, 1]
127
+ y_ffm = self.mlp_out(aem)
128
+
129
+ # compute final prediction
130
+ y = y_linear + y_ffm
131
+ return torch.sigmoid(y.squeeze(1) + self.b)