model.py 7.4 KB
Newer Older
T
tangwei 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#   Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.

15 16
import paddle.fluid as fluid

17 18
from paddlerec.core.utils import envs
from paddlerec.core.model import Model as ModelBase
19 20 21 22 23 24 25 26 27 28


class Model(ModelBase):
    def __init__(self, config):
        ModelBase.__init__(self, config)

    def xdeepfm_net(self):
        init_value_ = 0.1
        initer = fluid.initializer.TruncatedNormalInitializer(
            loc=0.0, scale=init_value_)
T
for mat  
tangwei 已提交
29

30
        is_distributed = True if envs.get_trainer() == "CtrTrainer" else False
T
tangwei 已提交
31 32 33 34
        sparse_feature_number = envs.get_global_env(
            "hyper_parameters.sparse_feature_number", None, self._namespace)
        sparse_feature_dim = envs.get_global_env(
            "hyper_parameters.sparse_feature_dim", None, self._namespace)
T
for mat  
tangwei 已提交
35

36
        # ------------------------- network input --------------------------
T
for mat  
tangwei 已提交
37

T
tangwei 已提交
38 39
        num_field = envs.get_global_env("hyper_parameters.num_field", None,
                                        self._namespace)
X
xujiaqi01 已提交
40 41 42 43 44
        raw_feat_idx = self._sparse_data_var[1]
        raw_feat_value = self._dense_data_var[0]
        self.label = self._sparse_data_var[0]

        feat_idx = raw_feat_idx
T
tangwei 已提交
45 46
        feat_value = fluid.layers.reshape(
            raw_feat_value, [-1, num_field, 1])  # None * num_field * 1
47 48 49 50 51 52 53 54

        feat_embeddings = fluid.embedding(
            input=feat_idx,
            is_sparse=True,
            dtype='float32',
            size=[sparse_feature_number + 1, sparse_feature_dim],
            padding_idx=0,
            param_attr=fluid.ParamAttr(initializer=initer))
T
tangwei 已提交
55 56 57
        feat_embeddings = fluid.layers.reshape(feat_embeddings, [
            -1, num_field, sparse_feature_dim
        ])  # None * num_field * embedding_size
58
        feat_embeddings = feat_embeddings * feat_value  # None * num_field * embedding_size
T
for mat  
tangwei 已提交
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
        # -------------------- linear  --------------------

        weights_linear = fluid.embedding(
            input=feat_idx,
            is_sparse=True,
            dtype='float32',
            size=[sparse_feature_number + 1, 1],
            padding_idx=0,
            param_attr=fluid.ParamAttr(initializer=initer))
        weights_linear = fluid.layers.reshape(
            weights_linear, [-1, num_field, 1])  # None * num_field * 1
        b_linear = fluid.layers.create_parameter(
            shape=[1],
            dtype='float32',
            default_initializer=fluid.initializer.ConstantInitializer(value=0))
        y_linear = fluid.layers.reduce_sum(
            (weights_linear * feat_value), 1) + b_linear
T
for mat  
tangwei 已提交
77

78 79
        # -------------------- CIN  --------------------

T
tangwei 已提交
80 81
        layer_sizes_cin = envs.get_global_env(
            "hyper_parameters.layer_sizes_cin", None, self._namespace)
82 83 84 85 86 87 88
        Xs = [feat_embeddings]
        last_s = num_field
        for s in layer_sizes_cin:
            # calculate Z^(k+1) with X^k and X^0
            X_0 = fluid.layers.reshape(
                fluid.layers.transpose(Xs[0], [0, 2, 1]),
                [-1, sparse_feature_dim, num_field,
T
for mat  
tangwei 已提交
89
                 1])  # None, embedding_size, num_field, 1
90 91
            X_k = fluid.layers.reshape(
                fluid.layers.transpose(Xs[-1], [0, 2, 1]),
T
tangwei 已提交
92 93
                [-1, sparse_feature_dim, 1,
                 last_s])  # None, embedding_size, 1, last_s
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
            Z_k_1 = fluid.layers.matmul(
                X_0, X_k)  # None, embedding_size, num_field, last_s

            # compresses Z^(k+1) to X^(k+1)
            Z_k_1 = fluid.layers.reshape(Z_k_1, [
                -1, sparse_feature_dim, last_s * num_field
            ])  # None, embedding_size, last_s*num_field
            Z_k_1 = fluid.layers.transpose(
                Z_k_1, [0, 2, 1])  # None, s*num_field, embedding_size
            Z_k_1 = fluid.layers.reshape(
                Z_k_1, [-1, last_s * num_field, 1, sparse_feature_dim]
            )  # None, last_s*num_field, 1, embedding_size  (None, channal_in, h, w) 
            X_k_1 = fluid.layers.conv2d(
                Z_k_1,
                num_filters=s,
                filter_size=(1, 1),
                act=None,
                bias_attr=False,
                param_attr=fluid.ParamAttr(
                    initializer=initer))  # None, s, 1, embedding_size
            X_k_1 = fluid.layers.reshape(
                X_k_1, [-1, s, sparse_feature_dim])  # None, s, embedding_size

            Xs.append(X_k_1)
            last_s = s

        # sum pooling
        y_cin = fluid.layers.concat(Xs[1:],
                                    1)  # None, (num_field++), embedding_size
        y_cin = fluid.layers.reduce_sum(y_cin, -1)  # None, (num_field++)
        y_cin = fluid.layers.fc(input=y_cin,
                                size=1,
                                act=None,
                                param_attr=fluid.ParamAttr(initializer=initer),
                                bias_attr=None)
        y_cin = fluid.layers.reduce_sum(y_cin, dim=-1, keep_dim=True)

        # -------------------- DNN --------------------

T
tangwei 已提交
133 134 135 136
        layer_sizes_dnn = envs.get_global_env(
            "hyper_parameters.layer_sizes_dnn", None, self._namespace)
        act = envs.get_global_env("hyper_parameters.act", None,
                                  self._namespace)
137
        y_dnn = fluid.layers.reshape(feat_embeddings,
T
for mat  
tangwei 已提交
138
                                     [-1, num_field * sparse_feature_dim])
139
        for s in layer_sizes_dnn:
T
tangwei 已提交
140 141 142 143 144 145
            y_dnn = fluid.layers.fc(
                input=y_dnn,
                size=s,
                act=act,
                param_attr=fluid.ParamAttr(initializer=initer),
                bias_attr=None)
146 147 148 149 150 151 152 153 154
        y_dnn = fluid.layers.fc(input=y_dnn,
                                size=1,
                                act=None,
                                param_attr=fluid.ParamAttr(initializer=initer),
                                bias_attr=None)

        # ------------------- xDeepFM ------------------

        self.predict = fluid.layers.sigmoid(y_linear + y_cin + y_dnn)
T
for mat  
tangwei 已提交
155

156
    def train_net(self):
X
xjqbest 已提交
157
        self._init_slots()
158 159
        self.xdeepfm_net()

T
tangwei 已提交
160 161 162 163
        cost = fluid.layers.log_loss(
            input=self.predict,
            label=fluid.layers.cast(self.label, "float32"),
            epsilon=0.0000001)
164 165 166 167 168 169 170
        batch_cost = fluid.layers.reduce_mean(cost)
        self._cost = batch_cost

        # for auc
        predict_2d = fluid.layers.concat([1 - self.predict, self.predict], 1)
        label_int = fluid.layers.cast(self.label, 'int64')
        auc_var, batch_auc_var, _ = fluid.layers.auc(input=predict_2d,
T
for mat  
tangwei 已提交
171 172
                                                     label=label_int,
                                                     slide_steps=0)
173 174
        self._metrics["AUC"] = auc_var
        self._metrics["BATCH_AUC"] = batch_auc_var
T
for mat  
tangwei 已提交
175

176
    def optimizer(self):
T
tangwei 已提交
177 178
        learning_rate = envs.get_global_env("hyper_parameters.learning_rate",
                                            None, self._namespace)
179 180 181
        optimizer = fluid.optimizer.Adam(learning_rate, lazy_mode=True)
        return optimizer

X
xjqbest 已提交
182 183
    def infer_net(self):
        self.train_net()