【传知代码】一款轻量级的隐私保护推荐系统(论文复现)

news2024/9/27 23:24:01

在当今信息爆炸的时代,个性化推荐系统在我们的日常生活中扮演着越来越重要的角色。然而,随着个人数据的广泛收集和利用,隐私保护成为了一个不可忽视的挑战。为了平衡推荐系统的效用与用户隐私的保护,一款轻量级的隐私保护推荐系统应运而生。本文将深入探讨这样一种系统的设计理念、关键技术以及其在实际应用中的潜力和优势。通过探索如何在保证个性化推荐效果的同时,有效保护用户隐私,我们将揭示出一种新兴的技术趋势,为未来智能化应用的发展开辟新的可能性。

本文所涉及所有资源均在传知代码平台可获取

目录

概述

项目设计

核心代码

写在最后


概述

        本文的主要内容是介绍了一种名为LightFR的轻量级联邦推荐系统,该系统采用隐私保护的矩阵分解技术。文章首先回顾了矩阵分解、学习哈希和联邦推荐系统等相关领域的研究,然后详细介绍了LightFR的框架和算法,并从存储/通信效率、推荐效率和隐私保护等多个方面论证了其优越性。接下来,文章通过实验验证了LightFR的有效性和效率,并讨论了其对用户隐私的保护能力,主要创新点如下所示:

1)提出了一种轻量级、隐私保护的联邦推荐系统(FRS),名为LightFR,以解决现有工作中的效率和隐私问题。

2)通过学习哈希技术获得用户和项目的二进制表示,以有效解决联邦设置中的离散优化问题。

3)设计了一种高效的联邦离散算法,以在服务器和客户端之间嵌入用户偏好,同时减少资源消耗和保护隐私。

4)解释了为什么现有的方法没有考虑效率和隐私问题,以及它们在实际FRS中的主要挑战。

解决的主要问题:

现有问题

1)现有的联邦推荐系统(FRS)在资源效率和隐私保护方面存在挑战。

2)高成本的资源消耗和通信开销限制了现有方法在大规模推荐场景中的应用。

3)提高用户隐私保护的能力对于现实世界的FRS至关重要,但现有方法在这方面的考虑不足。

解决问题

1)开发一种轻量级且隐私保护的联邦推荐系统(FRS),以降低资源成本并提高隐私保护能力。

2)通过学习哈希技术获得用户和项目的二进制表示,从而有效解决效率和隐私问题。

3)设计一种在服务器和客户端之间高效的联邦离散算法,以嵌入用户偏好到离散汉明空间,同时降低服务器和客户端的资源利用,保护用户隐私。

论文提出了一种名为LightFR的轻量级联邦推荐方法,它通过矩阵分解和隐私保护的学习哈希技术实现轻量级、高效且安全的推荐。

项目设计

实验设计包括以下几个方面:

1)数据集:使用四个不同规模的公开数据集(MovieLens-1M、Filmtrust、Douban-Movie 和 Ciao)进行实验分析,以全面反映模型性能。

2)评估指标:使用两个常用的评估指标,即 Hit Ratio(HR)和 Normalized Discounted Cumulative Gain(NDCG),以评估模型性能和验证其有效性。

3)实验方法:对比中心化经典矩阵分解模型(如PMF、SVD++和DDL)和联邦矩阵分解基线(如FederatedMF)与提出的 LightFR 模型。分析不同超参数(如二进制编码长度 f、权衡参数 λ 和选定客户比例 p)对性能的影响。

本文的最核心创新点包括以下几点:

1)提出了一种轻量级的联邦推荐系统(LightFR),它通过学习哈希技术获得用户和项目的二进制表示,从而有效解决资源效率和隐私保护问题。

2)设计了一种高效的联邦离散算法,用于在服务器和客户端之间进行训练离散参数,实现了在保护隐私的方式下提高资源效率。

3)从理论角度证明了LightFR在存储/通信效率、推理效率和隐私保护方面的优越性。

4)通过大量实验证明,LightFR在推荐准确性、资源节约和数据隐私方面明显优于现有的联邦推荐方法。

核心代码

下面这个 Client 类体现了联邦学习在推荐系统中的应用,其中每个客户端独立地更新其模型(哈希表示),并可以在本地进行模型性能评估。整个过程旨在优化用户的哈希表示,使其能够更好地捕捉用户的偏好和行为模式,同时在联邦学习的框架下保持用户数据的隐私性:

import numpy as np
from Metrics import Metrics
class Client:
    def __init__(self, configs):
        self.bu = None #客户端的哈希表示
        self.D = None  # 与项目相关的全局参数
        self.data_u = None #特定客户端的用户数据
        self.data_bin_u = None #特定客户端的用户数据的二进制表示
        self.data_len_u = None #特定客户端的用户数据的长度
        self.configs = configs
    def client_update(self, client, master_flag):
        '''
        client process, could be implemented in parallel
        :param master_flag:
        :param bu:
        :param D:
        :param data_u:
        :param data_bin_u:
        :param l:
        :return:
        '''
        while True:
            flag = 0
            for k in range(self.configs.code_len):
                dk = client.D[:, k]
                buk_hat = np.sum(
                    ( client.data_u - np.dot(client.D, client.bu.T)) * dk * client.data_bin_u) + 2 * self.configs.lambdaa * client.data_len_u * client.bu[k]
                buk_new = np.sign(self.K(buk_hat, client.bu[k]))
                if (client.bu[k] != buk_new):
                    flag = 1
                    client.bu[k] = buk_new
            if (flag == 0):
                break
            master_flag = 1

        return client.bu, master_flag

    def get_inter_params(self, i, k):
        di = self.D[i, :]
        grads = (self.data_u[i] - np.dot(self.bu, di.T)) * self.bu[k] * self.data_bin_u[i]
        grads_len = self.data_bin_u[i]
        return grads, grads_len

    def K(self, x, y):
        return x if x != 0 else y

    def calculate_loss(self):
        local_loss = np.sum((self.data_u - np.dot(self.D, self.bu)) ** 2 * self.data_bin_u)
        return local_loss

    def evaluate_local(self, items, val_data):
        configs = {'top_k': 10, 'num_negative_test': 49, }
        metric = Metrics(configs)
        bus = self.bu
        dis = self.D[items]
        rating_pred = np.multiply(bus, dis)
        preds = np.sum(rating_pred, axis=1)
        val_data['pred'] = preds.tolist()

        hr = metric.get_hit_ratio(val_data)
        ndcg = metric.get_ndcg(val_data)
        return hr, ndcg

下面 Base 类提供了一个推荐系统基本框架,包括数据处理、模型初始化和评估。这个类能够处理用户和项目的交互数据,生成评分矩阵,并对推荐模型的性能进行评估。通过这种方式,它为构建更复杂的推荐系统模型提供了基础:

# -*- coding: utf-8 -*-
import numpy as np
import scipy.linalg as la
from collections import defaultdict
from math import log
import pandas as pd
import torch
from DataLoader import DataLoaderCenter
from Metrics import Metrics


class Base:

    def __init__(self):
        self.user = {}
        self.item = {}
        self.id2user = {}
        self.id2item = {}
        self.u_i_r = defaultdict(dict)
        self.i_u_r = defaultdict(dict)
        self.minVal = 0.5
        self.maxVal = 4
        self.dataset_name = 'filmtrust'
        self.federated_train_data_path = 'data/' + self.dataset_name + '/' + self.dataset_name + '_train.csv'
        self.federated_valid_data_path = 'data/' + self.dataset_name + '/' + self.dataset_name + '_val.csv'
        self.federated_test_data_path = 'data/' + self.dataset_name + '/' + self.dataset_name + '_test.csv'
        pass


    def init_model(self):
        self.generate_vocabulary()
        self.rating_matrix, self.rating_matrix_bin, self.globalmean = self.get_rating_matrix()
        self.B = np.sign(np.array(np.random.randn(len(self.user), self.configs.code_len) / (self.configs.code_len ** 0.5)))
        self.D = np.sign(np.array(np.random.randn(len(self.item), self.configs.code_len) / (self.configs.code_len ** 0.5)))
        self.loss, self.last_delta_loss = 0.0, 0.0

    def trainSet(self):
        with open(self.federated_train_data_path, 'r') as f:
            for index, line in enumerate(f):
                if index != 0:  # 去除headers
                    u, i, r = line.strip('\r\n').split(',')
                    r = 2 * self.configs.code_len * (float(r)) - self.configs.code_len
                    yield (int(u), int(i), float(r))

    def containUser(self, user_id):
        if user_id in self.user:
            return True
        else:
            return False

    def containItem(self, item_id):
        if item_id in self.item:
            return True
        else:
            return False

    def valid_test_Set(self, path):
        with open(path, 'r') as f:
            for index, line in enumerate(f):
                if index != 0:  # 去除headers
                    u, i, r = line.strip('\r\n').split(',')
                    # r = 2 * self.code_len * (float(int(r) - self.minVal) / (self.maxVal - self.minVal) + 0.01) - self.code_len
                    yield (int(u), int(i), float(r))

    def read_federated_valid_dataset(self, path):
        data_val = pd.read_csv(path)
        return data_val

    def generate_vocabulary(self):
        for index, line in enumerate(self.trainSet()):
            user_id, item_id, rating = line
            self.u_i_r[user_id][item_id] = rating
            self.i_u_r[item_id][user_id] = rating
            if user_id not in self.user:
                self.user[user_id] = len(self.user)
                self.id2user[self.user[user_id]] = user_id
            if item_id not in self.item:
                self.item[item_id] = len(self.item)
                self.id2item[self.item[item_id]] = item_id

        for index, line in enumerate(self.valid_test_Set(self.federated_valid_data_path)):
            user_id, item_id, rating = line
            self.u_i_r[user_id][item_id] = rating
            self.i_u_r[item_id][user_id] = rating
            if user_id not in self.user:
                self.user[user_id] = len(self.user)
                self.id2user[self.user[user_id]] = user_id
            if item_id not in self.item:
                self.item[item_id] = len(self.item)
                self.id2item[self.item[item_id]] = item_id

        for index, line in enumerate(self.valid_test_Set(self.federated_test_data_path)):
            user_id, item_id, rating = line
            self.u_i_r[user_id][item_id] = rating
            self.i_u_r[item_id][user_id] = rating
            if user_id not in self.user:
                self.user[user_id] = len(self.user)
                self.id2user[self.user[user_id]] = user_id
            if item_id not in self.item:
                self.item[item_id] = len(self.item)
                self.id2item[self.item[item_id]] = item_id


    def get_rating_matrix(self):
        rating_matrix = np.zeros((len(self.user), len(self.item)))  # (943, 1596)
        globalmean = 0.0
        lens = 0
        for index, line in enumerate(self.trainSet()):
            lens += 1
            user_id, item_id, rating = line
            globalmean += rating
            rating_matrix[self.user[user_id]][self.item[item_id]] = int(rating)
        rating_matrix_bin = (rating_matrix > 0).astype('int')
        globalmean = globalmean / (lens)
        return rating_matrix, rating_matrix_bin, globalmean

    def K(self, x, y):
        return x if x != 0 else y

    def valid_test_model(self, path):
        pre_true_dict = defaultdict(list)
        for index, line in enumerate(self.valid_test_Set(path)):
            user_id, item_id, rating = line
            if (self.containUser(user_id) and self.containItem(item_id)):
                bu = self.B[self.user[user_id], :]
                di = self.D[self.item[item_id], :]
                pre = np.dot(bu, di)
            elif (self.containUser(user_id) and not self.containItem(item_id)):
                pre = sum(self.u_i_r[user_id].values()) / float(len(self.u_i_r[user_id]))
            elif (not self.containUser(user_id) and self.containItem(item_id)):
                pre = sum(self.i_u_r[item_id].values()) / float(len(self.i_u_r[item_id]))
            else:
                pre = self.globalmean
            pre_true_dict[user_id].append([pre, rating])
        metrics = Metrics()
        ndcg_10 = metrics.calDCG_k(pre_true_dict, 10)
        return ndcg_10

写在最后

本文详细探讨了一款轻量级的隐私保护推荐系统的设计与实施。通过介绍其核心理念和关键技术,我们深入理解了如何在个性化推荐和用户隐私保护之间取得平衡。这种系统通过采用匿名化数据处理、去标识化技术和分布式计算等手段,有效降低了数据泄露的风险,同时保证了推荐的个性化和准确性。随着隐私问题日益成为社会关注的焦点,这样的技术创新不仅提升了用户的信任和满意度,也为未来智能化应用的发展指明了方向。未来,随着技术的进一步进化和隐私法规的完善,这种轻量级的隐私保护推荐系统有望在更广泛的应用场景中发挥重要作用,推动数字化社会的可持续发展。

详细复现过程的项目源码、数据和预训练好的模型可从该文章下方附件获取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1975315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

装win7出现0x0000007b蓝屏原因分析及解决方法

最近有网友问我装win7出现0x0000007b蓝屏怎么办?0x0000007b电脑蓝屏通常情况是硬盘的存储控制器驱动加载错误导致故障。出现0x0000007b蓝屏代码的原因有很多比如硬盘模式、安装的系统没有集成相关的磁盘控制器驱动等,下面小编就教大家装win7出现0x000000…

VFS(虚拟文件系统)是什么,有真实的文件系统吗?

文章目录 1 VFS(虚拟文件系统)是什么1.1 VFS 的设计目的 2 VFS 的工作原理2.1 VFS 的文件操作流程 3 真实的文件系统3.1 常见的真实文件系统3.2 真实文件系统与 VFS 的关系 4 总结封面 1 VFS(虚拟文件系统)是什么 虚拟文件系统&a…

水论文如何找创新,优秀者模仿,末尾有例子示范_来自B站水论文的程序猿

系列文章目录 文章目录 系列文章目录一、水论文如何找创新关键在“找”1、相似领域找2、找到后3、如何稍微改动4、 自己领域找 二、示例 一、水论文如何找创新关键在“找” 1、相似领域找 比如某人研究视频描述中的单句视频描述,他可以去密集视频描述领域找相关论…

springMVC中从Excel文件中导入导出数据

目录 1. 数据库展示2. 导入依赖3. 写方法3.1 导入数据3.2 导出数据 4. 效果5. 不足6. 参考链接 1. 数据库展示 2. 导入依赖 pom.xml <!--文件上传处理--><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId>&…

邻接表(链式存储)实现图的存储

目录 一. 前言 二. 用邻接表创建无向网的完整源代码 一. 前言 无向图邻接表的形式如下所示&#xff1a; 其中类如v1的结点为头结点&#xff0c;头结点后面的结点为边结点&#xff0c;表示与头结点中顶点相连的边的信息。 采用邻接表创建无向网的算法思路&#xff1a; 1&#…

GPU爆显存 | Windows下杀死GPU进程释放显存

文章目录 0 问题引入1 解决方案 0 问题引入 深度学习的时候&#xff0c;用CUDA加速训练了&#xff0c;但是进程没有完全结束&#xff0c;再跑的时候爆显存了。 1 解决方案 查看当前的GPU进程 nvidia-smi通过如下命令来杀死指定的进程。 taskkill /PID PID号 /F //例如&am…

单工和双工、半双工和全双工、波特率

目录 一、单工和双工 二、半双工和全双工 三、波特率 &#x1f308;你好呀&#xff01;我是 程序猿 &#x1f30c; 2024感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#xff0c;挖掘无限可能&#xff0c;共同成长&#xff01; 一、单工和双工 单工&#xff1a…

ComfyUI: 报EP Error错误(onnxruntime)

&#x1f936;背景描述 在使用反推提示词的时候&#xff0c;按照上一篇介绍的方法是可以正常使用的。 但是看后台的时候&#xff0c;发现有一个错误&#xff1a; *************** EP Error *************** EP Error D:\a\_work\1\s\onnxruntime\python\onnxruntime_pybind_s…

分布式领域扩展点设计稿

分布式领域扩展点设计稿 背景坐标设计理念设计图Quick Start相关组件 背景 随着交易业务和基础知识的沉淀&#xff0c;愈发觉得扩展点可以在大型交易分布式架构中可以做更多的事情。 经过一个月的思考&#xff0c;决定将 单点领域扩展点&#xff08;savior-ext&#xff09; 从…

基于SpringBoot+Vue的在线学籍管理系统(带1w+文档)

基于SpringBootVue的在线学籍管理系统(带1w文档) 基于SpringBootVue的在线学籍管理系统(带1w文档) 计算机技术快速发展的同时也促进信息化发展。当下在线学籍管理规模不断扩大&#xff0c;新型管理模式也正逐步推进&#xff0c;推动其信息化发展可以为其改革、进步提供保障。信…

AI周报(7.28-8.3)

AI应用-最小的可穿戴吊坠 AI 设备「Limitless」 Limitless的最大特点是足够小。尺寸只有31.9mm宽&#xff0c;16mm薄&#xff0c;比 AirPods 第一代&#xff08;44.3mm x 21.3mm x 53.5mm&#xff09;还要小&#xff0c;它采用一体式夹式设计&#xff0c;可固定在衣领、口袋上&…

算法小白的进阶之路(力扣9~12)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

轻触之间,静享尊贵 -- 家具缓冲器,优雅生活的守护者

在这个快节奏的时代&#xff0c;家是我们寻找宁静与舒适的空间。当您轻轻触摸门把手&#xff0c;缓缓关闭柜门&#xff0c;那一刻的宁静&#xff0c;不仅仅是一种感觉&#xff0c;它是家具缓冲器带给您的一份尊贵体验。家具缓冲器&#xff0c;就像一位无声的守护者&#xff0c;…

玩转微信公众号变现:从新手到专家的全攻略

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

C++ string(二)

目录 size()三种遍历string的方式auto迭代器capacity size() size:获取它有多少个字符 size_t size() const; int main() {string s1("hello world");size_t ret s1.size();//计算的是\0前面的字符个数cout << ret << endl;//11return 0; }三种遍历st…

【Redis】Centos 7 安装 Redis 5.0

目录 Redis重大版本 Redis 2.6 Redis 2.8 Redis 3.0 Redis 3.2 Redis 4.0 Redis 5.0 Redis 6.0 Redis 7.0 安装并启动Redis 安装scl源 安装Redis5.0 启动Redis 停止Redis Redis重大版本 Redis 借鉴了 Linux 操作系统对于版本号的命名规则&#xff1a;版本号第⼆…

C#裁剪图像的几种方法总结

前言 我们在上位机软件开发过程中经常需要裁剪图像&#xff0c;本文就是对c#中常见的裁剪图像方法进行总结。 1、克隆 直接调用Bitmap的Clone函数&#xff0c;然后指定需要裁剪的区域即可裁剪图像&#xff0c;该种方法不会损失精度 public static Bitmap CropImage_Clone(Bi…

[Bugku] web-CTF-网站被黑

1.开启环境 F12查看源代码 没有信息&#xff0c;扫描目录 扫描出shell.php 抓包尝试 使用密码字典爆破密码 得出flag

TypeScript 基础类型与类型声明

前言 在 JavaScript 中&#xff0c;变量是没有类型的&#xff0c;变量的值的类型是在运行时确定的&#xff0c;这被称为动态类型。 这意味着可以在不同的时间将不同类型的值赋给同一个变量&#xff0c;并且 JavaScript 会在运行时根据当前赋给变量的值来确定其类型。 示例&…

学生管理系统之界面设计

学生管理系统之界面设计 建立工程 新建登录界面