layers.py 9.5 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.

X
xiexionghang 已提交
15
import paddle.fluid as fluid
T
tangwei 已提交
16

17
from paddlerec.core.layer import Layer
X
xiexionghang 已提交
18

X
xiexionghang 已提交
19

T
tangwei 已提交
20
class EmbeddingFuseLayer(Layer):
X
xiexionghang 已提交
21 22
    """R
    """
T
tangwei 已提交
23

X
xiexionghang 已提交
24
    def __init__(self, config):
X
xiexionghang 已提交
25 26
        """R
        """
X
xiexionghang 已提交
27 28
        self._cvm = config['cvm']
        self._name = config['name']
X
xiexionghang 已提交
29
        self._slots = [str(slot) for slot in config['slots']]
X
xiexionghang 已提交
30 31
        self._mf_dim = config['mf_dim']
        self._backward = config['backward']
T
tangwei 已提交
32
        self._emb_dim = self._mf_dim + 3  # append show ctr lr
X
xiexionghang 已提交
33
        self._emb_layers = []
T
tangwei 已提交
34

T
tangwei 已提交
35
    def generate(self, param):
X
xiexionghang 已提交
36 37
        """R
        """
X
xiexionghang 已提交
38 39 40 41 42 43 44
        show_clk = fluid.layers.concat(
            [param['layer']['show'], param['layer']['click']], axis=1)
        show_clk.stop_gradient = True
        data_var = []
        for slot in self._slots:
            l = fluid.layers.data(name=slot, shape=[1], dtype="int64", lod_level=1)
            data_var.append(l)
X
xiexionghang 已提交
45
            emb = fluid.layers.embedding(input=l, size=[10, self._emb_dim], \
T
tangwei 已提交
46 47
                                         is_sparse=True, is_distributed=True,
                                         param_attr=fluid.ParamAttr(name="embedding"))
X
xiexionghang 已提交
48 49 50 51
            emb = fluid.layers.sequence_pool(input=emb, pool_type='sum')
            emb = fluid.layers.continuous_value_model(emb, show_clk, self._cvm)
            self._emb_layers.append(emb)
        output = fluid.layers.concat(input=self._emb_layers, axis=1, name=self._name)
X
xiexionghang 已提交
52
        return output, {'data_var': data_var}
X
xiexionghang 已提交
53

X
xiexionghang 已提交
54

X
xiexionghang 已提交
55
class LabelInputLayer(Layer):
X
xiexionghang 已提交
56 57
    """R
    """
T
tangwei 已提交
58

X
xiexionghang 已提交
59
    def __init__(self, config):
X
xiexionghang 已提交
60 61
        """R
        """
X
xiexionghang 已提交
62 63 64 65 66
        self._name = config['name']
        self._dim = config.get('dim', 1)
        self._data_type = config.get('data_type', "int64")
        self._label_idx = config['label_idx']

T
tangwei 已提交
67
    def generate(self, param):
X
xiexionghang 已提交
68 69 70
        """R
        """
        label = fluid.layers.data(name=self._name, shape=[-1, self._dim], \
T
tangwei 已提交
71
                                  dtype=self._data_type, lod_level=0, append_batch_size=False)
X
xiexionghang 已提交
72 73
        cast_label = fluid.layers.cast(label, dtype='float32')
        cast_label.stop_gradient = True
X
xiexionghang 已提交
74 75
        return cast_label, {'data_var': [label]}

X
xiexionghang 已提交
76

T
tangwei 已提交
77
class TagInputLayer(Layer):
X
xiexionghang 已提交
78 79
    """R
    """
T
tangwei 已提交
80

X
xiexionghang 已提交
81
    def __init__(self, config):
X
xiexionghang 已提交
82 83
        """R
        """
X
xiexionghang 已提交
84 85 86 87 88
        self._name = config['name']
        self._tag = config['tag']
        self._dim = config.get('dim', 1)
        self._data_type = config['data_type']

T
tangwei 已提交
89
    def generate(self, param):
X
xiexionghang 已提交
90 91 92
        """R
        """
        output = fluid.layers.data(name=self._name, shape=[-1, self._dim], \
T
tangwei 已提交
93
                                   dtype=self._data_type, lod_level=0, append_batch_size=False, stop_gradient=True)
X
xiexionghang 已提交
94 95
        return output, {'data_var': [output]}

T
tangwei 已提交
96 97

class ParamLayer(Layer):
X
xiexionghang 已提交
98 99
    """R
    """
T
tangwei 已提交
100

X
xiexionghang 已提交
101
    def __init__(self, config):
X
xiexionghang 已提交
102 103
        """R
        """
X
xiexionghang 已提交
104 105 106 107 108 109 110
        self._name = config['name']
        self._coln = config['coln']
        self._table_id = config.get('table_id', -1)
        self._init_range = config.get('init_range', 1)
        self._data_type = config.get('data_type', 'float32')
        self._config = config

T
tangwei 已提交
111
    def generate(self, param):
X
xiexionghang 已提交
112 113
        """R
        """
T
tangwei 已提交
114
        return self._config, {'inference_param': {'name': 'param', 'params': [], 'table_id': self._table_id}}
X
xiexionghang 已提交
115

X
xiexionghang 已提交
116

T
tangwei 已提交
117
class SummaryLayer(Layer):
X
xiexionghang 已提交
118 119
    """R
    """
T
tangwei 已提交
120

X
xiexionghang 已提交
121
    def __init__(self, config):
X
xiexionghang 已提交
122 123
        """R
        """
X
xiexionghang 已提交
124 125 126 127 128
        self._name = config['name']
        self._table_id = config.get('table_id', -1)
        self._data_type = config.get('data_type', 'float32')
        self._config = config

T
tangwei 已提交
129
    def generate(self, param):
X
xiexionghang 已提交
130 131
        """R
        """
T
tangwei 已提交
132
        return self._config, {'inference_param': {'name': 'summary', 'params': [], 'table_id': self._table_id}}
X
xiexionghang 已提交
133

X
xiexionghang 已提交
134

T
tangwei 已提交
135
class NormalizationLayer(Layer):
X
xiexionghang 已提交
136 137
    """R
    """
T
tangwei 已提交
138

X
xiexionghang 已提交
139
    def __init__(self, config):
X
xiexionghang 已提交
140 141
        """R
        """
X
xiexionghang 已提交
142 143
        self._name = config['name']
        self._input = config['input']
T
tangwei 已提交
144
        self._summary = config['summary']
X
xiexionghang 已提交
145 146
        self._table_id = config.get('table_id', -1)

T
tangwei 已提交
147
    def generate(self, param):
X
xiexionghang 已提交
148 149
        """R
        """
X
xiexionghang 已提交
150 151 152
        input_layer = param['layer'][self._input[0]]
        summary_layer = param['layer'][self._summary]
        if len(self._input) > 0:
T
tangwei 已提交
153
            input_list = [param['layer'][i] for i in self._input]
X
xiexionghang 已提交
154 155
            input_layer = fluid.layers.concat(input=input_list, axis=1)
        bn = fluid.layers.data_norm(input=input_layer, name=self._name, epsilon=1e-4, param_attr={
T
tangwei 已提交
156
            "batch_size": 1e4, "batch_sum_default": 0.0, "batch_square": 1e4})
X
xiexionghang 已提交
157
        inference_param = [self._name + '.batch_size', self._name + '.batch_sum', self._name + '.batch_square_sum']
T
tangwei 已提交
158 159
        return bn, {'inference_param': {'name': 'summary', \
                                        'params': inference_param, 'table_id': summary_layer.get('table_id', -1)}}
X
xiexionghang 已提交
160

X
xiexionghang 已提交
161

T
tangwei 已提交
162
class FCLayer(Layer):
X
xiexionghang 已提交
163 164
    """R
    """
T
tangwei 已提交
165

X
xiexionghang 已提交
166
    def __init__(self, config):
X
xiexionghang 已提交
167 168
        """R
        """
X
xiexionghang 已提交
169 170 171 172 173 174
        self._name = config['name']
        self._param = config['param']
        self._input = config['input']
        self._bias = config.get('bias', True)
        self._act_func = config.get('act_func', None)

T
tangwei 已提交
175
    def generate(self, param):
X
xiexionghang 已提交
176 177
        """R
        """
X
xiexionghang 已提交
178 179 180
        param_layer = param['layer'][self._param]
        input_layer = param['layer'][self._input[0]]
        if len(self._input) > 0:
T
tangwei 已提交
181
            input_list = [param['layer'][i] for i in self._input]
X
xiexionghang 已提交
182 183 184 185 186
            input_layer = fluid.layers.concat(input=input_list, axis=1)
        input_coln = input_layer.shape[1]
        scale = param_layer['init_range'] / (input_coln ** 0.5)
        bias = None
        if self._bias:
T
tangwei 已提交
187 188
            bias = fluid.ParamAttr(learning_rate=1.0,
                                   initializer=fluid.initializer.NormalInitializer(loc=0.0, scale=scale))
X
xiexionghang 已提交
189
        fc = fluid.layers.fc(
T
tangwei 已提交
190 191 192 193 194
            name=self._name,
            input=input_layer,
            size=param_layer['coln'],
            act=self._act_func,
            param_attr= \
X
xiexionghang 已提交
195
                fluid.ParamAttr(learning_rate=1.0, \
T
tangwei 已提交
196 197
                                initializer=fluid.initializer.NormalInitializer(loc=0.0, scale=scale)),
            bias_attr=bias)
X
xiexionghang 已提交
198
        inference_param = [self._name + '.w_0', self._name + '.b_0']
T
tangwei 已提交
199 200
        return fc, {'inference_param': {'name': 'param', 'params': inference_param, \
                                        'table_id': param_layer.get('table_id', -1)}}
X
xiexionghang 已提交
201

X
xiexionghang 已提交
202

T
tangwei 已提交
203
class LogLossLayer(Layer):
X
xiexionghang 已提交
204 205
    """R
    """
T
tangwei 已提交
206

X
xiexionghang 已提交
207
    def __init__(self, config):
X
xiexionghang 已提交
208 209
        """R
        """
X
xiexionghang 已提交
210 211 212 213 214 215 216
        self._name = config['name']
        self._label = config['label']
        self._input = config['input']
        self._weight = config.get('weight', None)
        self._metric_label = config.get('metric_label', None)
        self._bound = config.get('bound', [-15.0, 15.0])
        self._extend_output = {
X
xiexionghang 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230
            'metric_label': self._metric_label,
            'metric_dict': {
                'auc': {'var': None},
                'batch_auc': {'var': None},
                'stat_pos': {'var': None, 'data_type': 'int64'},
                'stat_neg': {'var': None, 'data_type': 'int64'},
                'batch_stat_pos': {'var': None, 'data_type': 'int64'},
                'batch_stat_neg': {'var': None, 'data_type': 'int64'},
                'pos_ins_num': {'var': None},
                'abserr': {'var': None},
                'sqrerr': {'var': None},
                'prob': {'var': None},
                'total_ins_num': {'var': None},
                'q': {'var': None}
X
xiexionghang 已提交
231 232
            }
        }
T
tangwei 已提交
233

T
tangwei 已提交
234
    def generate(self, param):
X
xiexionghang 已提交
235 236
        """R
        """
X
xiexionghang 已提交
237 238
        input_layer = param['layer'][self._input[0]]
        label_layer = param['layer'][self._label]
X
xiexionghang 已提交
239
        output = fluid.layers.clip(input_layer, self._bound[0], self._bound[1], name=self._name)
X
xiexionghang 已提交
240 241 242 243 244 245 246
        norm = fluid.layers.sigmoid(output, name=self._name)
        output = fluid.layers.log_loss(norm, fluid.layers.cast(x=label_layer, dtype='float32'))
        if self._weight:
            weight_layer = param['layer'][self._weight]
            output = fluid.layers.elementwise_mul(output, weight_layer)
        output = fluid.layers.mean(x=output)
        self._extend_output['loss'] = output
T
tangwei 已提交
247 248

        # For AUC Metric
X
xiexionghang 已提交
249 250 251 252
        metric = self._extend_output['metric_dict']
        binary_predict = fluid.layers.concat(
            input=[fluid.layers.elementwise_sub(fluid.layers.ceil(norm), norm), norm], axis=1)
        metric['auc']['var'], metric['batch_auc']['var'], [metric['batch_stat_pos']['var'], \
T
tangwei 已提交
253 254
                                                           metric['batch_stat_neg']['var'], metric['stat_pos']['var'],
                                                           metric['stat_neg']['var']] = \
X
xiexionghang 已提交
255
            fluid.layers.auc(input=binary_predict, label=fluid.layers.cast(x=label_layer, dtype='int64'), \
T
tangwei 已提交
256
                             curve='ROC', num_thresholds=32)
X
xiexionghang 已提交
257 258 259 260 261 262

        metric['sqrerr']['var'], metric['abserr']['var'], metric['prob']['var'], metric['q']['var'], \
        metric['pos_ins_num']['var'], metric['total_ins_num']['var'] = \
            fluid.contrib.layers.ctr_metric_bundle(norm, fluid.layers.cast(x=label_layer, dtype='float32'))

        return norm, self._extend_output