知识图谱(Knowledge Graph,KG)可以理解成一个知识库,用来存储实体与实体之间的关系。知识图谱可以为机器学习算法提供更多的信息,帮助模型更好地完成任务。

在推荐算法中融入电影的知识图谱,能够将没有任何历史数据的新电影精准地推荐给目标用户。

实例描述

现有一个电影评分数据集和一个电影相关的知识图谱。电影评分数据集里包含用户、电影及评分;电影相关的知识图谱中包含电影的类型、导演等属性。

要求:从知识图谱中找出电影间的潜在特征,并借助该特征及电影评分数据集,实现基于电影的推荐系统。

本实例使用了一个多任务学习的端到端框架MKR。该框架能够将两个不同任务的低层特征抽取出来,并融合在一起实现联合训练,从而达到最优的结果。有关MKR的更多介绍可以参考以下链接:

https://arxiv.org/pdf/1901.08907.pdf

一、准备数据集

在1901.08907.pdf的相关代码链接中有3个数据集:图书数据集、电影数据集和音乐数据集。本例使用电影数据集,具体链接如下:

https://github.com/hwwang55/MKR/tree/master/data/movie

该数据集中一共有3个文件。

  • item_index2entity_id.txt:电影的ID与序号。具体内容如图1所示,第1列是电影ID,第2列是序号。
  • kg.txt:电影的知识图谱。图2中显示了知识图谱的SPO三元组(Subject-Predicate-Object),第1列是电影ID,第2列是关系,第3列是目标实体。
  • ratings.dat:用户的评分数据集。具体内容如图3所示,列与列之间用“::”符号进行分割,第1列是用户ID,第2列是电影ID,第3列是电影评分,第4列是评分时间(可以忽略)。

二、预处理数据

数据预处理主要是对原始数据集中的有用数据进行提取、转化。该过程会生成两个文件。

  • kg_final.txt:转化后的知识图谱文件。将文件kg.txt中的字符串类型数据转成序列索引类型数据,如图4所示。
  • ratings_final.txt:转化后的用户评分数据集。第1列将ratings.dat中的用户ID变成序列索引。第2列没有变化。第3列将ratings.dat中的评分按照阈值5进行转化,如果评分大于等于5,则标注为1,表明用户对该电影感兴趣。否则标注为0,表明用户对该电影不感兴趣。具体内容如图5所示。

三、搭建MKR模型

MKR模型由3个子模型组成,完整结构如图6所示。具体描述如下。

  • 推荐算法模型:如图6的左侧部分所示,将用户和电影作为输入,模型的预测结果为用户对该电影的喜好分数,数值为0~1。
  • 交叉压缩单元模型:如图6的中间部分,在低层将左右两个模型桥接起来。将电影评分数据集中的电影向量与知识图谱中的电影向量特征融合起来,再分别放回各自的模型中,进行监督训练。
  • 知识图谱词嵌入(Knowledge Graph Embedding,KGE)模型:如图6的右侧部分,将知识图谱三元组中的前2个(电影ID和关系实体)作为输入,预测出第3个(目标实体)。

图6 MKR框架

在3个子模型中,最关键的是交叉压缩单元模型。下面就先从该模型开始一步一步地实现MKR框架。

1.交叉压缩单元模型

交叉压缩单元模型可以被当作一个网络层叠加使用。如图7所示的是交叉压缩单元在第l层到第l+1层的结构。图7中,最下面一行为该单元的输入,左侧的是用户评论电影数据集中的电影向量,右侧的是知识图谱中的电影向量。

图7 交叉压缩单元模型的结构

交叉压缩单元模型的具体处理过程如下:

(1)将与进行矩阵相乘得到。

(2)将复制一份,并进行转置得到。实现特征交叉融合。

(3)将经过权重矩阵进行线性变化(与矩阵相乘)。

(4)将经过权重矩阵进行线性变化。

(5)将(3)与(4)的结果相加,再与偏置参数相加,得到。将用于推荐算法模型的后续计算。

(6)按照第(3)、(4)、(5)步的做法,同理可以得到。将用于知识图谱词嵌入模型的后续计算。

用tf.layer接口实现交叉压缩单元模型,具体代码如下。

代码:

    import numpy as np
import tensorflow as tf
from sklearn.metrics import roc_auc_score
from tensorflow.python.layers import base class CrossCompressUnit(base.Layer): #定义交叉压缩单元模型类
def __init__(self, dim, name=None):
super(CrossCompressUnit, self).__init__(name)
self.dim = dim
self.f_vv = tf.layers.Dense(1, use_bias = False) #构建权重矩阵
self.f_ev = tf.layers.Dense(1, use_bias = False)
self.f_ve = tf.layers.Dense(1, use_bias = False)
self.f_ee = tf.layers.Dense(1, use_bias = False)
self.bias_v = self.add_weight(name='bias_v', #构建偏置权重
shape=dim,
initializer=tf.zeros_initializer()) self.bias_e = self.add_weight(name='bias_e',
shape=dim,
initializer=tf.zeros_initializer()) def _call(self, inputs):
v, e = inputs #v和e的形状为[batch_size, dim]
v = tf.expand_dims(v, dim=2) #v的形状为 [batch_size, dim, 1]
e = tf.expand_dims(e, dim=1) #e的形状为 [batch_size, 1, dim] c_matrix = tf.matmul(v, e)#c_matrix的形状为 [batch_size, dim, dim]
c_matrix_transpose = tf.transpose(c_matrix, perm=[0, 2, 1])
#c_matrix的形状为[batch_size * dim, dim]
c_matrix = tf.reshape(c_matrix, [-1, self.dim])
c_matrix_transpose = tf.reshape(c_matrix_transpose, [-1, self.dim]) #v_output的形状为[batch_size, dim]
v_output = tf.reshape(
self.f_vv(c_matrix) + self.f_ev(c_matrix_transpose),
[-1, self.dim]
) + self.bias_v e_output = tf.reshape(
self.f_ve(c_matrix) + self.f_ee(c_matrix_transpose),
[-1, self.dim]
) + self.bias_e
#返回结果
return v_output, e_output

代码第10行,用tf.layers.Dense方法定义了不带偏置的全连接层,并在代码第34行,将该全连接层作用于交叉后的特征向量,实现压缩的过程。

2.将交叉压缩单元模型集成到MKR框架中

在MKR框架中,推荐算法模型和知识图谱词嵌入模型的处理流程几乎一样。可以进行同步处理。在实现时,将整个处理过程横向拆开,分为低层和高层两部分。

—低层:将所有的输入映射成词嵌入向量,将需要融合的向量(图6中的v和h)输入交叉压缩单元,不需要融合的向量(图6中的u和r)进行同步的全连接层处理。

—高层:推荐算法模型和知识图谱词嵌入模型分别将低层的传上来的特征连接在一起,通过全连接层回归到各自的目标结果。

具体实现的代码如下。

代码7-14 MKR(续)

    class MKR(object):
def __init__(self, args, n_users, n_items, n_entities, n_relations):
self._parse_args(n_users, n_items, n_entities, n_relations)
self._build_inputs()
self._build_low_layers(args) #构建低层模型
self._build_high_layers(args) #构建高层模型
self._build_loss(args)
self._build_train(args) def _parse_args(self, n_users, n_items, n_entities, n_relations):
self.n_user = n_users
self.n_item = n_items
self.n_entity = n_entities
self.n_relation = n_relations #收集训练参数,用于计算l2损失
self.vars_rs = []
self.vars_kge = [] def _build_inputs(self):
self.user_indices=tf.placeholder(tf.int32, [None], 'userInd')
self.item_indices=tf.placeholder(tf.int32, [None],'itemInd')
self.labels = tf.placeholder(tf.float32, [None], 'labels')
self.head_indices =tf.placeholder(tf.int32, [None],'headInd')
self.tail_indices =tf.placeholder(tf.int32, [None], 'tail_indices')
self.relation_indices=tf.placeholder(tf.int32, [None], 'relInd')
def _build_model(self, args):
self._build_low_layers(args)
self._build_high_layers(args) def _build_low_layers(self, args):
#生成词嵌入向量
self.user_emb_matrix = tf.get_variable('user_emb_matrix',
[self.n_user, args.dim])
self.item_emb_matrix = tf.get_variable('item_emb_matrix',
[self.n_item, args.dim])
self.entity_emb_matrix = tf.get_variable('entity_emb_matrix',
[self.n_entity, args.dim])
self.relation_emb_matrix = tf.get_variable('relation_emb_matrix',
[self.n_relation, args.dim]) #获取指定输入对应的词嵌入向量,形状为[batch_size, dim]
self.user_embeddings = tf.nn.embedding_lookup(
self.user_emb_matrix, self.user_indices)
self.item_embeddings = tf.nn.embedding_lookup(
self.item_emb_matrix, self.item_indices)
self.head_embeddings = tf.nn.embedding_lookup(
self.entity_emb_matrix, self.head_indices)
self.relation_embeddings = tf.nn.embedding_lookup(
self.relation_emb_matrix, self.relation_indices)
self.tail_embeddings = tf.nn.embedding_lookup(
self.entity_emb_matrix, self.tail_indices) for _ in range(args.L):#按指定参数构建多层MKR结构
#定义全连接层
user_mlp = tf.layers.Dense(args.dim, activation=tf.nn.relu)
tail_mlp = tf.layers.Dense(args.dim, activation=tf.nn.relu)
cc_unit = CrossCompressUnit(args.dim)#定义CrossCompress单元
#实现MKR结构的正向处理
self.user_embeddings = user_mlp(self.user_embeddings)
self.tail_embeddings = tail_mlp(self.tail_embeddings)
self.item_embeddings, self.head_embeddings = cc_unit(
[self.item_embeddings, self.head_embeddings])
#收集训练参数
self.vars_rs.extend(user_mlp.variables)
self.vars_kge.extend(tail_mlp.variables)
self.vars_rs.extend(cc_unit.variables)
self.vars_kge.extend(cc_unit.variables) def _build_high_layers(self, args):
#推荐算法模型
use_inner_product = True #指定相似度分数计算的方式
if use_inner_product: #内积方式
#self.scores的形状为[batch_size]
self.scores = tf.reduce_sum(self.user_embeddings * self.item_embeddings, axis=1)
else:
#self.user_item_concat的形状为[batch_size, dim * 2]
self.user_item_concat = tf.concat(
[self.user_embeddings, self.item_embeddings], axis=1)
for _ in range(args.H - 1):
rs_mlp = tf.layers.Dense(args.dim * 2, activation=tf.nn.relu)
#self.user_item_concat的形状为[batch_size, dim * 2]
self.user_item_concat = rs_mlp(self.user_item_concat)
self.vars_rs.extend(rs_mlp.variables)
#定义全连接层
rs_pred_mlp = tf.layers.Dense(1, activation=tf.nn.relu)
#self.scores的形状为[batch_size]
self.scores = tf.squeeze(rs_pred_mlp(self.user_item_concat))
self.vars_rs.extend(rs_pred_mlp.variables) #收集参数
self.scores_normalized = tf.nn.sigmoid(self.scores) #知识图谱词嵌入模型
self.head_relation_concat = tf.concat( #形状为[batch_size, dim * 2]
[self.head_embeddings, self.relation_embeddings], axis=1)
for _ in range(args.H - 1):
kge_mlp = tf.layers.Dense(args.dim * 2, activation=tf.nn.relu)
#self.head_relation_concat的形状为[batch_size, dim* 2]
self.head_relation_concat = kge_mlp(self.head_relation_concat)
self.vars_kge.extend(kge_mlp.variables) kge_pred_mlp = tf.layers.Dense(args.dim, activation=tf.nn.relu)
#self.tail_pred的形状为[batch_size, args.dim]
self.tail_pred = kge_pred_mlp(self.head_relation_concat)
self.vars_kge.extend(kge_pred_mlp.variables)
self.tail_pred = tf.nn.sigmoid(self.tail_pred) self.scores_kge = tf.nn.sigmoid(tf.reduce_sum(self.tail_embeddings * self.tail_pred, axis=1))
self.rmse = tf.reduce_mean(
tf.sqrt(tf.reduce_sum(tf.square(self.tail_embeddings - self.tail_pred), axis=1) / args.dim))

代码第115~132行是推荐算法模型的高层处理部分,该部分有两种处理方式:

  • 使用内积的方式,计算用户向量和电影向量的相似度。有关相似度的更多知识,可以参考8.1.10小节的注意力机制。
  • 将用户向量和电影向量连接起来,再通过全连接层处理计算出用户对电影的喜好分值。

代码第132行,通过激活函数sigmoid对分值结果scores进行非线性变化,将模型的最终结果映射到标签的值域中。

代码第136~152行是知识图谱词嵌入模型的高层处理部分。具体步骤如下:

(1)将电影向量和知识图谱中的关系向量连接起来。

(2)将第(1)步的结果通过全连接层处理,得到知识图谱三元组中的目标实体向量。

(3)将生成的目标实体向量与真实的目标实体向量矩阵相乘,得到相似度分值。

(4)对第(3)步的结果进行激活函数sigmoid计算,将值域映射到0~1中。

3.实现MKR框架的反向结构

MKR框架的反向结构主要是loss值的计算,其loss值一共分为3部分:推荐算法模型模型的loss值、知识图谱词嵌入模型的loss值和参数权重的正则项。具体实现的代码如下。

代码7-14 MKR(续)

        def _build_loss(self, args):
#计算推荐算法模型的loss值
self.base_loss_rs = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(labels=self.labels, logits=self.scores))
self.l2_loss_rs = tf.nn.l2_loss(self.user_embeddings) + tf.nn.l2_loss (self.item_embeddings)
for var in self.vars_rs:
self.l2_loss_rs += tf.nn.l2_loss(var)
self.loss_rs = self.base_loss_rs + self.l2_loss_rs * args.l2_weight #计算知识图谱词嵌入模型的loss值
self.base_loss_kge = -self.scores_kge
self.l2_loss_kge = tf.nn.l2_loss(self.head_embeddings) + tf.nn.l2_loss (self.tail_embeddings)
for var in self.vars_kge: #计算L2正则
self.l2_loss_kge += tf.nn.l2_loss(var)
self.loss_kge = self.base_loss_kge + self.l2_loss_kge * args.l2_weight def _build_train(self, args): #定义优化器
self.optimizer_rs = tf.train.AdamOptimizer(args.lr_rs).minimize(self.loss_rs)
self.optimizer_kge = tf.train.AdamOptimizer(args.lr_kge). minimize(self. loss_kge) def train_rs(self, sess, feed_dict): #训练推荐算法模型
return sess.run([self.optimizer_rs, self.loss_rs], feed_dict) def train_kge(self, sess, feed_dict): #训练知识图谱词嵌入模型
return sess.run([self.optimizer_kge, self.rmse], feed_dict) def eval(self, sess, feed_dict): #评估模型
labels, scores = sess.run([self.labels, self.scores_normalized], feed_dict)
auc = roc_auc_score(y_true=labels, y_score=scores)
predictions = [1 if i >= 0.5 else 0 for i in scores]
acc = np.mean(np.equal(predictions, labels))
return auc, acc def get_scores(self, sess, feed_dict):
return sess.run([self.item_indices, self.scores_normalized], feed_dict)

代码第173、176行, 分别是训练推荐算法模型和训练知识图谱词嵌入模型的方法。因为在训练的过程中,两个子模型需要交替的进行独立训练,所以将其分开定义。

四、训练模型并输出结果

训练模型的代码在本书配套的“7-15 train.py”文件中,读者可以自行参考。代码运行后输出以下结果:

……
epoch 9 train auc: 0.9540 acc: 0.8817 eval auc: 0.9158 acc: 0.8407 test auc: 0.9155 acc: 0.8399

在输出的结果中,分别显示了模型在训练、评估、测试环境下的分值。

转载:

https://cloud.tencent.com/developer/article/1492199

Multi-Task Feature Learning for Knowledge Graph Enhanced Recommendation(知识图谱)的更多相关文章

  1. 【论文翻译】KLMo: Knowledge Graph Enhanced Pretrained Language Model with Fine-Grained Relationships

    KLMo:建模细粒度关系的知识图增强预训练语言模型 (KLMo: Knowledge Graph Enhanced Pretrained Language Model with Fine-Graine ...

  2. Deep Learning 和 Knowledge Graph howto

    领军大家: Geoffrey E. Hinton http://www.cs.toronto.edu/~hinton/ 阅读列表: reading lists and survey papers fo ...

  3. 收藏:左路Deep Learning+右路Knowledge Graph,谷歌引爆大数据

    发表于2013-01-18 11:35| 8827次阅读| 来源sina微博 条评论| 作者邓侃 数据分析智能算法机器学习大数据Google 摘要:文章来自邓侃的博客.数据革命迫在眉睫. 各大公司重兵 ...

  4. 1. 通俗易懂解释知识图谱(Knowledge Graph)

    1. 通俗易懂解释知识图谱(Knowledge Graph) 2. 知识图谱-命名实体识别(NER)详解 3. 哈工大LTP解析 1. 前言 从一开始的Google搜索,到现在的聊天机器人.大数据风控 ...

  5. 知识图谱顶刊综述 - (2021年4月) A Survey on Knowledge Graphs: Representation, Acquisition, and Applications

    知识图谱综述(2021.4) 论文地址:A Survey on Knowledge Graphs: Representation, Acquisition, and Applications 目录 知 ...

  6. (AAAI2020 Yao) Graph Few-shot Learning via knowledge transfer

    22-5-13 seminar上和大家分享了这篇文章 [0]Graph few-shot learning via knowledge transfer 起因是在MLNLP的公众号上看到了张初旭老师讲 ...

  7. 哈工大知识图谱(Knowledge Graph)课程概述

    一.什么是知识图谱 知识(Knowledge)可以理解为 精炼的数据,知识图谱(Knowledge Graph)即是对知识的图形化表示,本质上是一种大规模语义网络 (semantic network) ...

  8. 论文解读(node2vec)《node2vec Scalable Feature Learning for Networks》

    论文题目:<node2vec Scalable Feature Learning for Network>发表时间:  KDD 2016 论文作者:  Aditya Grover;Adit ...

  9. 泡泡一分钟:Stabilize an Unsupervised Feature Learning for LiDAR-based Place Recognition

    Stabilize an Unsupervised Feature Learning for LiDAR-based Place Recognition Peng Yin, Lingyun Xu, Z ...

随机推荐

  1. ASP.NET Core 之跨平台的实时性能监控

    前言 前面我们聊了一下一个应用程序 应该监控的8个关键位置. . 嗯..地址如下: 应用程序的8个关键性能指标以及测量方法 最后卖了个小关子,是关于如何监控ASP.NET Core的. 今天我们就来讲 ...

  2. centos7 spark2.3.1集群搭建

    1.安装jdk 2.安装scala 参照jdk的安装 3.ssh 免密码登录 4.安装hadoop 以上四步请参照   centos7 安装hadoop2.7.6(分布式) 5.安装spark  1) ...

  3. python数据分析3之标签化

  4. Java白皮书(总结一些题目)

    java基础 1.      简述JVM的运行原理? Java平台由Java 虚拟机和Java 应用程序接口搭建,Java语言则是进入这个平台的通道, 用Java语言编写并编译的程序可以运行在这个平台 ...

  5. C++ 工程师养成 每日一题4.5 (迭代器遍历)

    首先说明,当每日一题标号不是整数时代表此题是较为简单的,我在这里整理一遍主要是我做错了(没错是我太菜各位大佬无视就好) 题目: 读入一个字符串str,输出字符串str中的连续最长的数字串 此题思路清晰 ...

  6. 通过excel表格分析学生成绩

    题目要求: 分析文件’课程成绩.xlsx’,至少要完成内容:分析1)每年不同班级平均成绩情况.2)不同年份总体平均成绩情况.3)不同性别学生成绩情况,并分别用合适的图表展示出三个内容的分析结果. 废话 ...

  7. Linux基础(05)socket编程

    Linux的核心思想之一 "一切皆文件" 内容 , socket在Linux内核的实现的代码及TCP和UDP的实现 网络编程常用头文件: https://blog.csdn.net ...

  8. SQL SERVER 数据库查询表信息

    SELECT 表名 then d.name else '' end, 表说明 then isnull(f.value,'') else '' end, 字段序号 = a.colorder, 字段名 = ...

  9. swift版 二分查找 (折半查找)

    二分查找作为一种常见的查找方法,将原本是线性时间提升到了对数时间范围之内,大大缩短了搜索时间,但它有一个前提,就是必须在有序数据中进行查找.废话少说,直接上代码,可复制粘贴直接出结果! import ...

  10. ELK学习笔记之logstash的各个场景应用(配置文件均已实践过)

    详细请参考该文 https://www.cnblogs.com/qingqing74647464/p/9378385.html