model.py 6.8 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 math

T
tangwei 已提交
17 18
import paddle.fluid as fluid

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


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

    def deepfm_net(self):
        init_value_ = 0.1
        is_distributed = True if envs.get_trainer() == "CtrTrainer" else False
T
tangwei 已提交
30 31 32 33
        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 已提交
34

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

T
tangwei 已提交
37 38 39
        num_field = envs.get_global_env("hyper_parameters.num_field", None,
                                        self._namespace)

X
xujiaqi01 已提交
40 41 42
        raw_feat_idx = self._sparse_data_var[1]
        raw_feat_value = self._dense_data_var[0]
        self.label = self._sparse_data_var[0]
T
tangwei 已提交
43

X
xujiaqi01 已提交
44
        feat_idx = raw_feat_idx
T
tangwei 已提交
45 46 47 48 49
        feat_value = fluid.layers.reshape(
            raw_feat_value, [-1, num_field, 1])  # None * num_field * 1

        reg = envs.get_global_env("hyper_parameters.reg", 1e-4,
                                  self._namespace)
50 51 52 53 54 55 56 57 58 59 60 61 62
        first_weights_re = fluid.embedding(
            input=feat_idx,
            is_sparse=True,
            is_distributed=is_distributed,
            dtype='float32',
            size=[sparse_feature_number + 1, 1],
            padding_idx=0,
            param_attr=fluid.ParamAttr(
                initializer=fluid.initializer.TruncatedNormalInitializer(
                    loc=0.0, scale=init_value_),
                regularizer=fluid.regularizer.L1DecayRegularizer(reg)))
        first_weights = fluid.layers.reshape(
            first_weights_re, shape=[-1, num_field, 1])  # None * num_field * 1
T
tangwei 已提交
63 64
        y_first_order = fluid.layers.reduce_sum((first_weights * feat_value),
                                                1)
65

T
for mat  
tangwei 已提交
66
        # ------------------------- second order term --------------------------
67 68 69 70 71 72 73 74 75 76

        feat_embeddings_re = fluid.embedding(
            input=feat_idx,
            is_sparse=True,
            is_distributed=is_distributed,
            dtype='float32',
            size=[sparse_feature_number + 1, sparse_feature_dim],
            padding_idx=0,
            param_attr=fluid.ParamAttr(
                initializer=fluid.initializer.TruncatedNormalInitializer(
T
tangwei 已提交
77 78
                    loc=0.0,
                    scale=init_value_ / math.sqrt(float(sparse_feature_dim)))))
79 80 81
        feat_embeddings = fluid.layers.reshape(
            feat_embeddings_re,
            shape=[-1, num_field,
T
for mat  
tangwei 已提交
82
                   sparse_feature_dim])  # None * num_field * embedding_size
83
        feat_embeddings = feat_embeddings * feat_value  # None * num_field * embedding_size
T
for mat  
tangwei 已提交
84

85
        # sum_square part
T
tangwei 已提交
86 87
        summed_features_emb = fluid.layers.reduce_sum(
            feat_embeddings, 1)  # None * embedding_size
88 89 90 91 92 93 94 95 96 97
        summed_features_emb_square = fluid.layers.square(
            summed_features_emb)  # None * embedding_size

        # square_sum part
        squared_features_emb = fluid.layers.square(
            feat_embeddings)  # None * num_field * embedding_size
        squared_sum_features_emb = fluid.layers.reduce_sum(
            squared_features_emb, 1)  # None * embedding_size

        y_second_order = 0.5 * fluid.layers.reduce_sum(
T
tangwei 已提交
98 99
            summed_features_emb_square - squared_sum_features_emb,
            1,
100 101
            keep_dim=True)  # None * 1

T
for mat  
tangwei 已提交
102
        # ------------------------- DNN --------------------------
103

T
tangwei 已提交
104 105 106 107
        layer_sizes = envs.get_global_env("hyper_parameters.fc_sizes", None,
                                          self._namespace)
        act = envs.get_global_env("hyper_parameters.act", None,
                                  self._namespace)
108
        y_dnn = fluid.layers.reshape(feat_embeddings,
T
for mat  
tangwei 已提交
109
                                     [-1, num_field * sparse_feature_dim])
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
        for s in layer_sizes:
            y_dnn = fluid.layers.fc(
                input=y_dnn,
                size=s,
                act=act,
                param_attr=fluid.ParamAttr(
                    initializer=fluid.initializer.TruncatedNormalInitializer(
                        loc=0.0, scale=init_value_ / math.sqrt(float(10)))),
                bias_attr=fluid.ParamAttr(
                    initializer=fluid.initializer.TruncatedNormalInitializer(
                        loc=0.0, scale=init_value_)))
        y_dnn = fluid.layers.fc(
            input=y_dnn,
            size=1,
            act=None,
            param_attr=fluid.ParamAttr(
                initializer=fluid.initializer.TruncatedNormalInitializer(
                    loc=0.0, scale=init_value_)),
            bias_attr=fluid.ParamAttr(
                initializer=fluid.initializer.TruncatedNormalInitializer(
                    loc=0.0, scale=init_value_)))
T
for mat  
tangwei 已提交
131 132

        # ------------------------- DeepFM --------------------------
133

T
tangwei 已提交
134 135
        self.predict = fluid.layers.sigmoid(y_first_order + y_second_order +
                                            y_dnn)
T
for mat  
tangwei 已提交
136

137
    def train_net(self):
X
fix  
xujiaqi01 已提交
138
        self.model._init_slots()
139
        self.deepfm_net()
T
for mat  
tangwei 已提交
140 141

        # ------------------------- Cost(logloss) --------------------------
142

T
tangwei 已提交
143 144
        cost = fluid.layers.log_loss(
            input=self.predict, label=fluid.layers.cast(self.label, "float32"))
145
        avg_cost = fluid.layers.reduce_sum(cost)
T
for mat  
tangwei 已提交
146

147 148
        self._cost = avg_cost

T
for mat  
tangwei 已提交
149 150
        # ------------------------- Metric(Auc) --------------------------

151 152 153
        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 已提交
154 155
                                                     label=label_int,
                                                     slide_steps=0)
156 157 158 159
        self._metrics["AUC"] = auc_var
        self._metrics["BATCH_AUC"] = batch_auc_var

    def optimizer(self):
T
tangwei 已提交
160 161
        learning_rate = envs.get_global_env("hyper_parameters.learning_rate",
                                            None, self._namespace)
162 163 164 165
        optimizer = fluid.optimizer.Adam(learning_rate, lazy_mode=True)
        return optimizer

    def infer_net(self, parameter_list):
X
fix  
xujiaqi01 已提交
166
        self.model._init_slots()
X
xujiaqi01 已提交
167
        self.deepfm_net()