源码地址:https://github.com/hwwang55/RippleNet
下面是文件代码的解读,没有提到的内容我觉得大家应该一看就懂,还有下面的解释只是我自己的理解,我很菜,如有误导,本人概不负责:
data_lodaer.py:
load_data:通过加载文件,返回训练数据、评估数据、测试数据、实体表、关系表和水波集合
load_rating:读取评级文件的数据集,并将数据集切分,其中训练:评估:测试为6:2:2。评级数量为评级矩阵的行数,从评级数量范围内不重复地抽取长度为(评级数量*评估比例)个元素组成一维向量作为评估索引,然后用整个数据集减去评估集乘以测试比例得到测试索引,再用数据集减去评估集和测试集得到训练集索引。遍历训练索引,如果评级为1,则将该行添加到用户历史字典中,键为用户id,值为点击内容。然后使用列表推导式更新三个部分的索引列表,更新机制为保留元素在用户历史字典中的列表元素,最后生成训练、评估和测试集
load_kg:加载图谱文件,将加载得到的图谱矩阵通过切片操作再用set()去重取长度得到实体和关系的数量,返回实体数量、关系数量和图谱字典
construct_kg:通过循环加载得到的矩阵构建图谱字典,键为头部实体,值为尾部实体和关系组成的tuple
get_ripplenet_set:将一个创建实例为list的默认字典复制给ripplenet_set,循环用户历史字典,在字典键值对中进行内部跳数(n_hop)循环:如果跳数为0,则最后一跳的尾部实体为用户历史字典中当前键值对的所有值,否则为水波字典中当前键值对列表值中最后一个三元组的第二个元素。紧接着循环尾部实体,将图谱中该实体对应的三元组循环赋值给memories_h,memories_r,memories_t列表。如果头实体的记忆列表中没有元素,则在水波字典中的用户键对应的值列表中追加当前列表的最后一个三元组,否则就为每个用户采样一个固定大小的一跳记忆:随机生成一个范围在头实体列表长度大小,尺寸为记忆数目的列表,列表内元素是否重复取决于列表长度和及记忆数目的大小关系,再通过生成的列表筛选得到一组新的三元组列表追加到用户键对应的值列表中,最终返回水波字典
preprocess.py:
read_item_index_to_entity_id_file:读取样本-实体文件,循环读出的内容:样本索引等于行数据的第一个元素,顿悟id等于行数据的第二个元素。对新样本索引字典中的样本索引键重新赋值,从i=0开始,每次自增1,直到文件读取到最后一行,对实体索引字典中的顿悟id键采取同样操作
convert_rating:将新的样本字典的值赋值给样本集合,用户正负评级分别初始化为空的字典。打开评级文件,从第二行开始循环,清除两边的空字符再用分隔符分开组成array。如果数据集的名称为book,则把array的第二列到最后一列取出来。旧的样本索引等于array的第二列,如果旧样本索引不在新样本索引则跳出本次循环。样本索引等于新的索引字典中旧索引键的值,旧的用户索引等于整数化array的第一列,评级等于浮点化array的第三列。如果评级大于数据集的阈值,就把旧的用户索引和样本索引作为键值对存入用户正评级字典中,否则存入用户负评级字典。循环正字典的键值对,把旧的用户索引和用户数量(通过循环自加1)作为键值对存入新的用户字典中。将新字典中旧用户索引的键值赋值给用户索引。循环正样本,将用户索引和样本索引写入文件中。用样本集合减去正负样本集合得到无监督的样本。紧接着在无监督样本里随机不重复采样长度为正样本长度的列表,循环写入用户索引和样本索引
convert_kg:逐行读取图谱文件的内容并按制表符分离得到旧的头部实体,关系和尾部实体。然后往实体索引字典中添加旧头实体-实体数量键值对和旧尾实体-实体数量键值对,往关系索引字典里添加旧关系-关系数量键值对。再分别取出头实体,关系和尾实体写入文件中
model.py:
_build_inputs:设置样本和标签变量,为头部实体、关系、尾部实体创建三个空的列表。循环总跳数,为三个空列表提前预留好迭代跳数将时产生的相应数据
_build_embedding:初始化实体嵌入矩阵和关系嵌入矩阵,初始化的每一层的输出与输入必须是同方差的,并且前向传播与反向传播时梯度也是同方差的。初始权重值应当为均值为0,的正态分布
_build_model:初始化转换矩阵,创建该矩阵的目的是为了更新每跳结尾的样本嵌入。将实体嵌入矩阵中的索引为样本变量的项取出赋值给样本嵌入矩阵。将空列表赋值给头部实体、关系、尾部实体三个嵌入,随即循环总跳数:在每次循环中分别去实体嵌入矩阵和关系嵌入矩阵中寻找索引为记忆实体和记忆关系列表中该跳的内容对应的矩阵添加到实体嵌入和关系嵌入列表。然后调用"关键处理"方法得到总跳数的响应,再调用预测函数算出模型的分数,再进行sigmod归一化
_key_addressing:循环总跳数:每次循环时,在头部实体嵌入列表的第hop个元素的维度3处增加一个维度然后赋值给扩展的头部实体矩阵,然后将该矩阵和关系嵌入列表中第hop个元素相乘,并删除维度3的轴处大小为1的维度赋值给实体和关系的乘积。在样本嵌入列表的第hop个元素的维度2处增加一个维度赋值给样本矩阵,然后将Rh和v相乘并删除上一步增加的维度得到样本v和实体h在关系R的空间中的相似度,再经过softmax归一化。然后将归一化的概率增加一个维度去和尾部实体嵌入列表的第hop个元素相乘,然后计算上一步的得到的张量各个维度上元素的总和赋值给样本的hop阶响应,然后调用方法更新样本嵌入,最后把hop阶响应添加到响应列表中
predict:把响应列表里面的元素全部取出拼接成一维向量和样本嵌入矩阵相乘,计算各个维度上元素总和赋值给得分
_build_loss:计算给定预测值和真实标签之间的交叉熵损失赋值给基础损失;迭代相加关系r的指标张量的切片(也就是当前跳)和重构的指标矩阵两者之间的平方误差,这一步操作在代码中的做法是头实体、关系、尾实体三个嵌入矩阵相乘再做sigmod归一化然后取各个维度上元素的平均值,循环相加总跳数次,最后再乘以图谱的权重;迭代头实体嵌入、关系嵌入和尾实体嵌入三个列表在当前跳的内容的平方求和再取均值得到三部分的loss,迭代过程中将三者依次相加,循环结束时即可得到最终的正则化器来防止模型过拟合。最后将三种损失相加
_build_train:采用tf中引入了二次方梯度校正全局最优点的Adam优化算法,最小化损失函数
train:将优化器、损失函数和数据放入tf中开始训练
eval:运行会话,计算模型的精准率和召回率