CMN 《Collaborative Memory Network for Recommendation Systems》

一. 论文解读

协同记忆网络 (CMN) 不但能够捕获协同过滤中隐向量的全局结构,还能对局部相似用户的行为进行建模。其记忆模块通过注意力机制很好的对用户-物品近邻关系进行了编码;输出模块利用用户-物品的记忆编码进行排序分数的输出。多层记忆模块的堆叠能玩挖掘更复杂的用户-物品关系。

1. 模型结构:
CMN 《Collaborative Memory Network for Recommendation Systems》_第1张图片
CMN.png
2. 计算流程:
2.1 User Embedding 的计算

如果 Hop == 1:

else:

其中, 表示对物品 产生过反馈的所有用户, 分别表示用户 和物品 的 embedding 向量。

2.2 Neighborhood Attention 的计算


这里的 表示用户 的另外一个嵌入向量。

2.3 Output Module


其中 ,, 表示激活函数。

3. 损失函数:


其中,, 表示用户 交互过的正样本, 表示负样本。

二. 代码实现

1. 系统环境
  • tensorflow 2.0
  • python 3.6.8

代码实现主要利用tensorflow.keras,其中将 和 最后的预测层抽象成了 Layer 的子类。

2. z_ui 计算层
class HopLayer(tf.keras.layers.Layer):
    """
    计算z_ui
    """
    def __init__(self, activation=tf.nn.relu, embedding_size=32, **kwargs):
        super().__init__(**kwargs)
        self.activation = activation
        self.embedding_size = embedding_size

    def build(self, input_shape):
        self.w = self.add_weight(name='w',
                                 shape=[self.embedding_size, self.embedding_size],
                                 initializer=tf.zeros_initializer())
        self.b = self.add_weight(name='b',
                                 shape=[self.embedding_size],
                                 initializer=tf.zeros_initializer())

    def call(self, inputs):
        z_ui, o_ui = inputs
        outputs = self.activation(tf.matmul(z_ui, self.w) + o_ui + self.b)
        return outputs
2. 输出层
class PredictLayer(tf.keras.layers.Layer):
    """
    计算输出
    """

    def __init__(self, activation=tf.nn.relu, embedding_size=32, **kwargs):
        self.activation = activation
        self.embedding_size = embedding_size
        super().__init__(**kwargs)

    def build(self, input_shape):
        """
        :param input_shape: [[batch_size, embedding_size], []
        :return:
        """
        self.u = self.add_weight(name='u',
                                 shape=[self.embedding_size, self.embedding_size],
                                 initializer=tf.zeros_initializer())
        self.w = self.add_weight(name='w',
                                 shape=[self.embedding_size, self.embedding_size],
                                 initializer=tf.zeros_initializer())
        self.b = self.add_weight(name='b',
                                 shape=[self.embedding_size],
                                 initializer=tf.zeros_initializer())
        self.v = self.add_weight(name='v',
                                 shape=[self.embedding_size],
                                 initializer=tf.zeros_initializer())

    def call(self, inputs):
        user_embeddings, item_embeddings, hop_ouput = inputs
        inner = tf.matmul(tf.multiply(user_embeddings, item_embeddings), self.u) + tf.matmul(hop_ouput, self.w) + self.b
        outputs = tf.matmul(self.activation(inner), tf.expand_dims(self.v, axis=-1))

        return outputs
3. CMN 模型
class CMN(tf.keras.Model):

    def __init__(self, user_size, item_size, neighbor_size, embedding_size=32, hops=1,
                 activation=tf.nn.relu, l2_reg=0.01, **kwargs):
        super().__init__(**kwargs)
        self.hops = hops
        self.neighbor_size = neighbor_size
        self.user_embedding = tf.keras.layers.Embedding(user_size, embedding_size,
                                                        embeddings_regularizer=tf.keras.regularizers.l2(l2_reg))
        self.item_embedding = tf.keras.layers.Embedding(item_size, embedding_size,
                                                        embeddings_regularizer=tf.keras.regularizers.l2(l2_reg))
        self.neighbor_embedding = tf.keras.layers.Embedding(user_size, embedding_size,
                                                            embeddings_regularizer=tf.keras.regularizers.l2(l2_reg))
        self.hop_layer = HopLayer(activation=activation, embedding_size=embedding_size)
        self.predict_layer = PredictLayer(activation=activation, embedding_size=embedding_size)

    def call(self, inputs):
        user_ids, item_ids, neighbors = inputs
        user_embeddings = self.user_embedding(user_ids)  # [batch_size, embedding_size]
        item_embeddings = self.item_embedding(item_ids)
        # [batch_size, neighbor_size]
        neighbors = tf.keras.preprocessing.sequence.pad_sequences(neighbors, maxlen=self.neighbor_size)
        neighbor_embeddings = self.neighbor_embedding(neighbors)  # [batch_size, neighbor_size, embedding_size]

        if self.hops == 1:
            # [batch_size, neighbor_size, 1]
            q_ui = tf.matmul(neighbor_embeddings, tf.expand_dims(user_embeddings, axis=-1)) + \
                   tf.matmul(neighbor_embeddings, tf.expand_dims(item_embeddings, axis=-1))
            p_ui = tf.nn.softmax(q_ui, axis=1)
            # [batch_size, embedding_size]
            o_ui = tf.squeeze(tf.matmul(tf.transpose(p_ui, perm=[0, 2, 1]), neighbor_embeddings))
        else:
            query = user_embeddings + item_embeddings  # z_0
            for i in range(self.hops):
                # [batch_size, neighbor_size, 1]
                q_ui = tf.matmul(neighbor_embeddings, tf.expand_dims(query, axis=-1))
                p_ui = tf.nn.softmax(q_ui, axis=1)
                # [batch_size, embedding_size]
                o_ui = tf.squeeze(tf.matmul(tf.transpose(p_ui, perm=[0, 2, 1]), neighbor_embeddings))
                query = self.hop_layer((query, o_ui))

        predictions = self.predict_layer((user_embeddings, item_embeddings, o_ui))

        return predictions

【参考】

  1. https://arxiv.org/abs/1804.10862

你可能感兴趣的:(CMN 《Collaborative Memory Network for Recommendation Systems》)