在当今信息爆炸的时代,社交媒体和数字平台已经成为我们获取信息、交流观点以及发现新内容的主要途径。然而,随着内容数量的剧增,用户面临着信息过载和质量参差不齐的挑战。为了解决这一问题,基于图的去中心化社会推荐过滤器应运而生。
本文所涉及所有资源均在传知代码平台可获取
目录
概述
算法流程
核心代码
写在最后
概述
由于这些社会关系可以轻松地用图结构数据来表示,因此图神经网络在这一领域具有很大的发展潜力。然而,现有的基于图的算法在处理数据时往往忽略了用户或事件的偏好偏移量。作者给出的一个示例说明了这种偏移量的重要性:挑剔的用户给出的低评分并不一定意味着他们对产品的态度是消极的,因为这些用户通常会给出低评分,这可能会导致图结构数据分析产生误差。现有的方法通常将这种偏差作为标量融入模型训练中,但作者认为这种做法不足以捕捉所有相关信息。此外,作者指出,用户之间的社会联系也应被考虑在内,因为具有相似偏好的用户往往会对彼此产生更大的影响。基于此,作者提出了一种新的算法来解决这些问题。
作者将评价偏移量处理为向量,并将其融入到用户和事件的表征学习中。具体做法是计算用户与其他用户的评价差异向量,从而获得每个用户的评价偏移。具体做法是,他们对原始图进行去中心化处理,然后从中学习到用户和事件的表征。去中心化的图是基于原始图中的统计信息生成的。接着,作者提出了一种用户-用户之间社会关系的建模方式,并将其融入到预测规则中,以提高推荐表现。然后,基于去中心化图,他们提出了一种基于图神经网络(GNN)的社会推荐协同过滤模型。最后,作者在两个数据集上验证了所提出算法的有效性,证明了其在处理用户偏好偏移量和社会关系建模方面的优势。原论文中采用了大量的数学公式来表示算法过程,这里笔者认为实际上读起来有点费力,所以本文主要从感性的角度来对这篇论文进行讲解,尽量少用公式而是用文字描述来给大家建立一个感性的理解。
原论文链接:https://ieeexplore.ieee.org/abstract/document/9721542
模版代码链接:https://github.com/MEICRS/GDSRec_rank
算法流程
下面我们来具体介绍一下算法的原理。首先,我们的数据集中包含用户和事件(item)两类对象,用户对item会有一个评分(rating)。具体任务是预测数据集R中未观察到的评分,然后返回用于推荐的排名列表。
原文采用的建图方式是将用户和事件作为节点,用户-事件之间的连线权重为关系系数Tij,用于衡量两个用户的相似度。
关系系数的计算方式可以看作是设定一个阈值,当两个用户对同一个事件的评分差距在阈值之内时,就将相似度加一,累加起来就是两个用户的相似度,这里称为关系系数。而用户-事件连线的权重为用户对事件的评分。然而,作者指出,直接使用这种原始图会带来一些不足,也就是无法准确反映真正的用户偏好。这是因为用户对事件的评分可能受到不同用户的打分标准的影响,从而导致误解用户的真实偏好。因此,作者对图结构进行了去中心化处理,以更好地捕捉用户的真实偏好。
去中心化图有三种不同的边:用户-事件、事件-用户、用户-用户。对于每个用户-事件交互的边,用原始权重减去所有权重的平均值得到新的权重,而用户-用户连线的权重保持不变。通过这种方式,作者将统计信息融入到图中。接下来,作者针对这种去中心化图进行了对用户、事件、社会联系三种方向的建模,从而计算出三种潜在因素偏移量。依据这些偏移量,可以计算出最终用户ui和事件vj的最终偏好评分,即:
然后我们具体介绍一下作者提出的三种建模方式。我们以用户建模(user modeling)为例,期望得到的输出是潜在因素偏移量hui。整个流程可以用上面的公式表示,我们可以逐步拆分这个过程。
然后我们具体介绍一下作者提出的三种建模方式。我们以用户建模(user modeling)为例,期望得到的输出是潜在因素偏移量hui。整个流程可以用上面的公式表示,我们可以逐步拆分这个过程。
首先,需要提到的是,在这个过程中使用的用户-事件交互权重都是进行取整后的。原文指出,使用小数进行embedding不太方便,但同时也提到一些量化方法可以解决这个问题,他们将这部分留作未来工作。前面提到,这篇文章的一大贡献是将评价偏移量处理为向量。
具体做法是将事件vlvl与用户-事件交互的权重进行embedding后的表征进行拼接,然后通过一个多层感知机进行处理,从而融入到学习过程中。q,sq,s分别是事件uu和社会关联rr的表征,LULU是多层感知机,这种方法可以将该向量融入用户表征的学习过程中。
同时,作者指出,一个用户和相关联事件之间的每个关联对用户潜在因素的影响贡献是不同的。因此,他们采用了注意力机制来捕捉用户偏好中的差异。公式8中xx前面乘的系数实际上是注意力权重。需要注意的是,在输入注意力网络时,他们将前面的评价偏移向量与用户的embedding向量进行了拼接,然后通过一个两层神经网络进行处理。通过这一流程,就可以得到用户的潜在因素偏移量hui。
事件建模(item modeling)和社会关系建模(social modeling)的处理方式与用户建模类似。三种建模处理后,我们可以得到三种潜在因素偏移量。基于此,偏好评分可以通过三层神经网络获得,用公式9,10,11表示。这个偏好评分可以理解为包括用户自己的意见和对其社会关联用户评级的参考。对于用户ui的社会关联用户,我们可以用相同的方式得到他们的偏好评分,从而得到方程f的返回值,计算方式如公式12。
最终,我们回到前面公式4就可以计算出用户ui和事件vj之间的最终评分。以这种方式就可以实现对用户更全面偏好信息的捕获,以及考虑到有着更强社会关联的用户对用户ui的影响。
核心代码
main.py文件在这里仍然是起到一个调用模型和所有函数进行数据输入、处理、训练、结果输出的功能,值得注意的是这里原文作者使用了config参数定义的方式,让整个工程看起来更加简洁、标准:
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
import pickle
import torch
from torch.utils.data import DataLoader
from utils import collate_fn
from model.GDSRec_model import GDSRec_Engine
config = {
'model': 'GDSRec',
'dataset': 'Ciao', # Ciao/Epinions
'optimizer': 'adam',
'l2_regularization': 0.01,
'embed_size': 64,
'batch_size': 128,
'layers': [256,128,128,64,64],
'epoch': 20,
'lr': 0.0005, # 0.01, 0.001, 0.0001
'lr_dc': 0.1, # learning rate decay
'lr_dc_step': 100, # the number steps for decay
'test':False,
'model_dir': 'checkpoints/{}_{}_best_checkpoint.model'
}
print(config)
here = os.path.dirname(os.path.abspath(__file__))
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)
config['device'] = device
workdir = 'C:/Users/meicr/Desktop/GDSRec_rank/data/'
with open(workdir + config['dataset'] + '/' + config['model'] + '_dataset.pkl', 'rb') as f:
train_dataset, evaluate_dataset, test_dataset, user_count, item_count = pickle.loads(f.read())
config['num_users'] = user_count
config['num_items'] = item_count
config['num_rates'] = 5
if config['test'] is False:
engine = GDSRec_Engine(config)
train_loader = DataLoader(train_dataset, batch_size=config['batch_size'], shuffle=True, collate_fn=collate_fn)
evaluate_loader = DataLoader(evaluate_dataset, batch_size=config['batch_size'], shuffle=False,
collate_fn=collate_fn)
index_sum = []
for epoch in range(config['epoch']):
print('Epoch {} starts !'.format(epoch))
engine.train_an_epoch(train_loader, epoch)
recall, ndcg = engine.evaluate(evaluate_loader, epoch)
if epoch == 0:
pre_sum = recall + ndcg
index_sum.append(0)
else:
if recall + ndcg < pre_sum:
index_sum.append(1)
else:
pre_sum = recall + ndcg
index_sum.append(0)
if sum(index_sum[-10:]) == 10:
break
if epoch == 0:
best_sum = recall + ndcg
engine.save()
elif recall + ndcg > best_sum:
best_sum = recall + ndcg
engine.save()
else:
engine = GDSRec_Engine(config)
print('Load checkpoint and testing...')
engine.resume()
test_loader = DataLoader(test_dataset, batch_size=config['batch_size'], shuffle=True, collate_fn=collate_fn)
recall, ndcg = engine.evaluate(test_loader, epoch_id=0)
这里preprocess.py文件的作用是对我们输入的数据进行了处理和分析得到模型可以处理的对象,主要包括格式转换、用户相似度计算之类的功能
"""
@author: Jiajia Chan
@date: 20 June, 2020
"""
import random
import argparse
import pickle
import pandas as pd
from scipy.io import loadmat
from rating_data import SingleGenerator
from trust_data import SocialGenerator
random.seed(1234)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--dataset', default='Ciao', help='dataset name: Ciao/Epinions')
parser.add_argument('--test_prop', default=0.2, help='the proportion of data used for test')
args = parser.parse_args()
workdir = 'data/'
click_f = loadmat(workdir + args.dataset + '/rating.mat')['rating']
trust_f = loadmat(workdir + args.dataset + '/trustnetwork.mat')['trustnetwork']
click_dt = pd.DataFrame(click_f)
trust_dt = pd.DataFrame(trust_f, columns=['userID', 'freID'])
click_dt = click_dt[[0, 1, 3]]
click_dt.dropna(inplace=True)
click_dt.drop_duplicates(inplace=True)
click_dt.columns = ['userID', 'itemID', 'rating']
trust_dt.dropna(inplace=True)
trust_dt.drop_duplicates(inplace=True)
single_generator = SingleGenerator(ratings=click_dt, prob=args.test_prop)
social_generator = SocialGenerator(singlegenerator=single_generator, trust=trust_dt)
GDSRec_dataset = social_generator.instance_GDSRec_dataset()
general_dataset = single_generator.instance_general_dataset()
with open(workdir + args.dataset +'/' + 'GDSRec' + '_dataset.pkl', 'wb') as f:
str1 = pickle.dumps(GDSRec_dataset)
f.write(str1)
f.close()
我们在github官方链接上只能找到一个数据集Ciao(原论文是在Ciao和Epinions上都进行了实验),我们需要将数据集整理成上述格式,这里可以打开看一下。整理的格式如右图所示,第一列是学生id, 第二列是问题id,第三列是无关变量原文代码中并没有用到,第四列是rating,trustnetwork.mat文件中保存的是学生与学生之间的关系网络。因此我们在进行本地私有数据集训练时也需要将数据处理成对应的格式
该篇论文作者在github上公布了源代码,但笔者下载下来实际运行了之后发现完全按照模版代码运行仍然会出现一些问题。研究之后发现可能是原作者在编写代码后改动了数据集目录格式,导致一些设定的环境路径参数错误。如果我们想要跑通代码或者在本地运行自己的数据集进行实验,还需要对相应的参数进行修改,修改后的代码我已经放在本文附件中了,并且在附件的压缩包内新增了一个Readme文件来提示大家如何修改数据集路径为自己的私有数据集
写在最后
本文深入探讨了基于图的去中心化社会推荐过滤器作为应对信息过载和数据操控挑战的创新解决方案。通过分析其核心原理和优势,我们理解了这一技术如何利用复杂的图数据结构,实现更精准、透明的个性化推荐服务。
首先,我们探讨了基于图的推荐系统如何有效地捕捉用户、内容和社交关系之间的多维度交互,从而提升推荐的准确性和用户满意度。其次,本文详细讨论了去中心化设计的重要性,如何增强数据隐私保护、抵御信息操控,以及提升平台的信任度和社会效益。
在实际应用方面,我们分析了基于图的推荐过滤器在不同场景中的成功案例,展示了其在提升信息质量、增强社交互动和保障用户权益方面的显著优势。此外,本文还探讨了未来发展的潜力,包括结合机器学习和人工智能技术进一步优化推荐算法,以及推动去中心化社交平台的普及和应用。
综上所述,基于图的去中心化社会推荐过滤器不仅是推荐系统领域的重要创新,更是推动数字社会发展、保护用户权益的关键技术之一。随着技术的不断进步和应用的拓展,相信这一技术将为构建开放、透明的数字社会平台带来更广阔的前景和机遇。
详细复现过程的项目源码、数据和预训练好的模型可从该文章下方附件获取。