Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/images/models/dcn_v2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/models/dcn_v2_cross.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions docs/source/models/dcn.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ model_config {
group_type: DEEP
}
dcn_v1 {
cross_tower {
cross {
cross_num: 3
}
deep_tower {
deep {
hidden_units: [256, 128]
}
final_dnn {
final {
hidden_units: [64, 32]
}
}
Expand All @@ -57,11 +57,11 @@ model_config {
}
```

- cross_tower
- cross
- cross_num: 交叉层层数,默认为3
- deep_tower
- deep
- hidden_units: dnn每一层的channel数目,即神经元的数目
- final_dnn: 整合cross_tower, deep_tower的全连接层
- final: 整合cross层, deep层的全连接层

## 参考论文

Expand Down
83 changes: 83 additions & 0 deletions docs/source/models/dcn_v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# DCN V2

## 简介

### DCN v2

相对于DCN v1模型,主要的改进点在于:

1. Wide侧-Cross Network中用矩阵替代向量,方阵可以分解成2个低维矩阵;
1. 提出2种模型结构,传统的Wide&Deep并行 + Wide&Deep串行。
![dcn_v2](../../images/models/dcn_v2.jpg)
![dcn_v2_cross](../../images/models/dcn_v2_cross.jpg)

## 配置说明

### DCNV2

```
model_config {
feature_groups {
group_name: "features"
feature_names: "user_id"
feature_names: "cms_segid"
feature_names: "cms_group_id"
feature_names: "final_gender_code"
feature_names: "age_level"
feature_names: "pvalue_level"
feature_names: "shopping_level"
feature_names: "occupation"
feature_names: "new_user_class_level"
feature_names: "pid"
feature_names: "adgroup_id"
feature_names: "cate_id"
feature_names: "campaign_id"
feature_names: "customer"
feature_names: "brand"
feature_names: "price"
group_type: DEEP
}
dcn_v2 {
backbone {
hidden_units: 512
hidden_units: 256
hidden_units: 128
}
cross {
cross_num: 2
low_rank: 32
}
deep {
hidden_units: 512
hidden_units: 256
}
final {
hidden_units: 128
hidden_units: 32
}
}
num_class: 1
metrics {
auc {}
}
losses {
binary_cross_entropy {}
}
}
```

- backbone: dnn层,可选配置,特征在进入cross层的时候是否要经过dnn层的处理
- cross
- cross_num: 交叉层层数,默认为3
- low_rank: cross层中大矩阵分解成2个低维矩阵的维度
- deep
- hidden_units: dnn每一层的channel数目,即神经元的数目
- final: 整合cross层, deep层的全连接层

### 示例Config

[dcn_v2_demo.config](https://tzrec.oss-cn-beijing.aliyuncs.com/config/models/dcn_v2_criteo.config)

### 参考论文

[DCN v2](https://arxiv.org/abs/2008.13535)
90 changes: 90 additions & 0 deletions docs/source/models/xdeepfm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# xDeepFM

### 简介

xDeepFM模型延续了deep&cross network(参考[DCN](https://easyrec.readthedocs.io/en/latest/models/dcn.html))模型的建模思想。不过,在建模显式高阶交叉特征时,采用了不同于deep&cross network的方式,文章称为compressed interaction network(CIN),并将CIN网络与深度神经网络结合,最后输入到输出层。

![xdeepfm.png](../../images/models/xdeepfm.png)

### 配置说明

组件化模型
Comment thread
tiankongdeguiji marked this conversation as resolved.
Outdated

```protobuf

model_config {
feature_groups {
group_name: "wide"
feature_names: 'user_id'
feature_names: 'cms_segid'
feature_names: 'cms_group_id'
feature_names: 'age_level'
feature_names: 'pvalue_level'
feature_names: 'shopping_level'
feature_names: 'occupation'
feature_names: 'new_user_class_level'
feature_names: 'tag_category_list'
feature_names: 'tag_brand_list'
feature_names: 'adgroup_id'
feature_names: 'cate_id'
feature_names: 'campaign_id'
feature_names: 'customer'
feature_names: 'brand'
feature_names: 'price'
feature_names: 'pid'
group_type: WIDE
}
feature_groups {
group_name: "deep"
feature_names: 'user_id'
feature_names: 'cms_segid'
feature_names: 'cms_group_id'
feature_names: 'age_level'
feature_names: 'pvalue_level'
feature_names: 'shopping_level'
feature_names: 'occupation'
feature_names: 'new_user_class_level'
feature_names: 'tag_category_list'
feature_names: 'tag_brand_list'
feature_names: 'adgroup_id'
feature_names: 'cate_id'
feature_names: 'campaign_id'
feature_names: 'customer'
feature_names: 'brand'
feature_names: 'price'
feature_names: 'pid'
group_type: DEEP
}
xdeepfm {
cin {
cin_layer_size: [64, 64]
}
deep {
hidden_units: [128, 64]
}
final {
hidden_units: [64, 32]
}
}
metrics {
auc {}
}
losses {
binary_cross_entropy {}
}
}
```

- cin: 特征交叉层
- cin_layer_size: cin每层要输出的维度
- deep
- hidden_units: dnn每一层的channel数目,即神经元的数目
- final: 整合cross层, deep层的全连接层

### 示例Config

[xdeepfm_criteo.config](https://tzrec.oss-cn-beijing.aliyuncs.com/config/models/xdeepfm_criteo.config)

### 参考论文

[xDeepFM](https://arxiv.org/pdf/1803.05170)
11 changes: 5 additions & 6 deletions tzrec/models/dcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,18 @@ def __init__(
self.group_name = self.embedding_group.group_names()[0]
feature_dim = self.embedding_group.group_total_dim(self.group_name)
self.cross = Cross(
input_dim=feature_dim, **config_to_kwargs(self._model_config.cross_tower)
input_dim=feature_dim, **config_to_kwargs(self._model_config.cross)
)
self.deep = MLP(
in_features=feature_dim, **config_to_kwargs(self._model_config.deep_tower)
in_features=feature_dim, **config_to_kwargs(self._model_config.deep)
)
deep_output_dim = self._model_config.deep_tower.hidden_units[-1]
final_dnn_input_dim = feature_dim + deep_output_dim
final_dnn_input_dim = self.cross.output_dim() + self.deep.output_dim()
self.final_dnn = MLP(
in_features=final_dnn_input_dim,
**config_to_kwargs(self._model_config.final_dnn),
**config_to_kwargs(self._model_config.final),
)
self.output_linear = nn.Linear(
self._model_config.final_dnn.hidden_units[-1], self._num_class, bias=False
self.final_dnn.output_dim(), self._num_class, bias=False
)

def predict(self, batch: Batch) -> Dict[str, torch.Tensor]:
Expand Down
6 changes: 3 additions & 3 deletions tzrec/models/dcn_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ def test_DCNV1(self, graph_type) -> None:
model_config = model_pb2.ModelConfig(
feature_groups=feature_groups,
dcn_v1=rank_model_pb2.DCNV1(
cross_tower=module_pb2.Cross(cross_num=3),
deep_tower=module_pb2.MLP(hidden_units=[8, 4]),
final_dnn=module_pb2.MLP(hidden_units=[2]),
cross=module_pb2.Cross(cross_num=3),
deep=module_pb2.MLP(hidden_units=[8, 4]),
final=module_pb2.MLP(hidden_units=[2]),
),
losses=[
loss_pb2.LossConfig(binary_cross_entropy=loss_pb2.BinaryCrossEntropy())
Expand Down
88 changes: 88 additions & 0 deletions tzrec/models/dcn_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Copyright (c) 2025, Alibaba Group;
Comment thread
tiankongdeguiji marked this conversation as resolved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Any, Dict, List, Optional

import torch
from torch import nn

from tzrec.datasets.utils import Batch
from tzrec.features.feature import BaseFeature
from tzrec.models.rank_model import RankModel
from tzrec.modules.interaction import CrossV2
from tzrec.modules.mlp import MLP
from tzrec.protos.model_pb2 import ModelConfig
from tzrec.utils.config_util import config_to_kwargs


class DCNV2(RankModel):
"""Deep cross network v2.

Args:
model_config (ModelConfig): an instance of ModelConfig.
features (list): list of features.
labels (list): list of label names.
sample_weights (list): sample weight names.
"""

def __init__(
self,
model_config: ModelConfig,
features: List[BaseFeature],
labels: List[str],
sample_weights: Optional[List[str]] = None,
**kwargs: Any,
) -> None:
super().__init__(model_config, features, labels, sample_weights, **kwargs)
self.init_input()
self.group_name = self.embedding_group.group_names()[0]
feature_dim = self.embedding_group.group_total_dim(self.group_name)

self.backbone = None
if self._model_config.HasField("backbone"):
self.backbone = MLP(
in_features=feature_dim, **config_to_kwargs(self._model_config.backbone)
)
feature_dim = self.backbone.output_dim()

self.cross = CrossV2(
input_dim=feature_dim, **config_to_kwargs(self._model_config.cross)
)
final_input_dim = self.cross.output_dim()
self.deep = None
if self._model_config.HasField("deep"):
in_features = self.embedding_group.group_total_dim(self.group_name)
self.deep = MLP(
in_features=in_features, **config_to_kwargs(self._model_config.deep)
)
final_input_dim += self.deep.output_dim()
self.final = MLP(
in_features=final_input_dim,
**config_to_kwargs(self._model_config.final),
)
self.output_mlp = nn.Linear(
self.final.output_dim(), self._num_class, bias=False
)

def predict(self, batch: Batch) -> Dict[str, torch.Tensor]:
"""Forward method."""
feature_dict = self.build_input(batch)
features = feature_dict[self.group_name]
if self.backbone:
net = self.backbone(features)
else:
net = features
net = self.cross(net)
if self.deep:
deep_net = self.deep(features)
net = torch.concat([net, deep_net], dim=-1)
out = self.output_mlp(self.final(net))
return self._output_to_prediction(out)
Loading