nets.py 5.0 KB
Newer Older
D
dongdaxiang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#Copyright (c) 2016 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.

import paddle.fluid as fluid
import paddle.fluid.layers.nn as nn
import paddle.fluid.layers.tensor as tensor
import paddle.fluid.layers.control_flow as cf
import paddle.fluid.layers.io as io
Z
add ssr  
zhangwenhui03 已提交
20 21 22 23 24 25 26 27 28


class BowEncoder(object):
    """ bow-encoder """

    def __init__(self):
        self.param_name = ""

    def forward(self, emb):
Z
zhang wenhui 已提交
29
        return fluid.layers.sequence_pool(input=emb, pool_type='sum')
Z
add ssr  
zhangwenhui03 已提交
30 31 32 33 34 35 36 37 38 39


class GrnnEncoder(object):
    """ grnn-encoder """

    def __init__(self, param_name="grnn", hidden_size=128):
        self.param_name = param_name
        self.hidden_size = hidden_size

    def forward(self, emb):
Z
zhang wenhui 已提交
40 41 42 43
        fc0 = fluid.layers.fc(input=emb,
                              size=self.hidden_size * 3,
                              param_attr=self.param_name + "_fc.w",
                              bias_attr=False)
Z
add ssr  
zhangwenhui03 已提交
44

Z
zhang wenhui 已提交
45
        gru_h = fluid.layers.dynamic_gru(
Z
add ssr  
zhangwenhui03 已提交
46 47 48 49 50
            input=fc0,
            size=self.hidden_size,
            is_reverse=False,
            param_attr=self.param_name + ".param",
            bias_attr=self.param_name + ".bias")
Z
zhang wenhui 已提交
51
        return fluid.layers.sequence_pool(input=gru_h, pool_type='max')
D
dongdaxiang 已提交
52

D
dongdaxiang 已提交
53 54 55 56

class PairwiseHingeLoss(object):
    def __init__(self, margin=0.8):
        self.margin = margin
Z
add ssr  
zhangwenhui03 已提交
57

D
dongdaxiang 已提交
58
    def forward(self, pos, neg):
Z
zhang wenhui 已提交
59
        loss_part1 = fluid.layers.elementwise_sub(
Z
zhang wenhui 已提交
60 61 62 63
            fluid.layers.fill_constant(
                shape=[fluid.layers.shape(pos)[0], 1],
                value=self.margin,
                dtype='float32'),
D
dongdaxiang 已提交
64
            pos)
Z
zhang wenhui 已提交
65 66
        loss_part2 = fluid.layers.elementwise_add(loss_part1, neg)
        loss_part3 = fluid.layers.elementwise_max(
Z
zhang wenhui 已提交
67 68 69 70
            fluid.layers.fill_constant(
                shape=[fluid.layers.shape(loss_part2)[0], 1],
                value=0.0,
                dtype='float32'),
D
dongdaxiang 已提交
71 72 73 74 75 76
            loss_part2)
        return loss_part3


class SequenceSemanticRetrieval(object):
    """ sequence semantic retrieval model """
Z
add ssr  
zhangwenhui03 已提交
77

D
dongdaxiang 已提交
78 79 80 81 82 83 84 85
    def __init__(self, embedding_size, embedding_dim, hidden_size):
        self.embedding_size = embedding_size
        self.embedding_dim = embedding_dim
        self.emb_shape = [self.embedding_size, self.embedding_dim]
        self.hidden_size = hidden_size
        self.user_encoder = GrnnEncoder(hidden_size=hidden_size)
        self.item_encoder = BowEncoder()
        self.pairwise_hinge_loss = PairwiseHingeLoss()
Z
add ssr  
zhangwenhui03 已提交
86

D
dongdaxiang 已提交
87 88
    def get_correct(self, x, y):
        less = tensor.cast(cf.less_than(x, y), dtype='float32')
Z
zhang wenhui 已提交
89
        correct = fluid.layers.reduce_sum(less)
D
dongdaxiang 已提交
90 91 92
        return correct

    def train(self):
Z
zhang wenhui 已提交
93 94 95 96 97 98 99
        user_data = fluid.data(
            name="user", shape=[None, 1], dtype="int64", lod_level=1)
        pos_item_data = fluid.data(
            name="p_item", shape=[None, 1], dtype="int64", lod_level=1)
        neg_item_data = fluid.data(
            name="n_item", shape=[None, 1], dtype="int64", lod_level=1)
        user_emb = fluid.embedding(
Z
add ssr  
zhangwenhui03 已提交
100
            input=user_data, size=self.emb_shape, param_attr="emb.item")
Z
zhang wenhui 已提交
101
        pos_item_emb = fluid.embedding(
Z
add ssr  
zhangwenhui03 已提交
102
            input=pos_item_data, size=self.emb_shape, param_attr="emb.item")
Z
zhang wenhui 已提交
103
        neg_item_emb = fluid.embedding(
Z
add ssr  
zhangwenhui03 已提交
104
            input=neg_item_data, size=self.emb_shape, param_attr="emb.item")
D
dongdaxiang 已提交
105 106 107
        user_enc = self.user_encoder.forward(user_emb)
        pos_item_enc = self.item_encoder.forward(pos_item_emb)
        neg_item_enc = self.item_encoder.forward(neg_item_emb)
Z
zhang wenhui 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121
        user_hid = fluid.layers.fc(input=user_enc,
                                   size=self.hidden_size,
                                   param_attr='user.w',
                                   bias_attr="user.b")
        pos_item_hid = fluid.layers.fc(input=pos_item_enc,
                                       size=self.hidden_size,
                                       param_attr='item.w',
                                       bias_attr="item.b")
        neg_item_hid = fluid.layers.fc(input=neg_item_enc,
                                       size=self.hidden_size,
                                       param_attr='item.w',
                                       bias_attr="item.b")
        cos_pos = fluid.layers.cos_sim(user_hid, pos_item_hid)
        cos_neg = fluid.layers.cos_sim(user_hid, neg_item_hid)
D
dongdaxiang 已提交
122
        hinge_loss = self.pairwise_hinge_loss.forward(cos_pos, cos_neg)
Z
zhang wenhui 已提交
123
        avg_cost = fluid.layers.mean(hinge_loss)
D
dongdaxiang 已提交
124
        correct = self.get_correct(cos_neg, cos_pos)
D
dongdaxiang 已提交
125

Z
add ssr  
zhangwenhui03 已提交
126 127
        return [user_data, pos_item_data,
                neg_item_data], cos_pos, avg_cost, correct