基于社交网络的推荐--包括给用户推荐好友的原理及代码实现

简介: 基于社交网络的推荐--包括给用户推荐好友的原理及代码实现

获取社交网络数据途径


社交网络数据的来源有下面几个:

电子邮件

用户注册信息:比如公司、学校等 (用于冷启动问题)

用户的位置数据:IP地址或者GPS数据

论坛和讨论组 (这个获取的一般是兴趣爱好)

即时聊天工具:QQ

社交网站: Facebook (社交图谱) Twitter (兴趣图谱)


社交网络数据简介


我们用图G(V,E,W)定义一个社交网络:


V是顶点集合,每个顶点是一个用户id

E是边集合,如果Va和Vb有社交关系,即存在E(a,b)

W(a,b)表示边的权重


一般来说,有3种不同的社交网络数据:


双向确认的社交网络数据:一般通过无向图表示

单向关注的社交网络数据:用户关系是单向的,可以通过有向图表示

基于社区的社交网络数据:比如豆瓣小组


基于社交网络的推荐


利用用户的社交网络数据进行推荐优点:

1.好友推荐可以增加推荐的信任度

2.社交网络可以解决冷启动问题

(缺点:由于用户的好友关系可能不是基于共同兴趣产生的,例如a-b是基于b的颜值??所以用户好友的兴趣与用户兴趣不一致)


基于领域的社会化推荐


1)最简单的方法是给用户推荐好友喜欢的物品集合,用户u对物品i的兴趣pui可以通过如下公式计算:

1.png

其中out(u)是用户u的好友集合,如果用户v喜欢物品i,则rvi=1,否则为0


2)当然,不同好友之间的熟悉度和兴趣相似度是不一样的,因此应该在推荐的时候把这个考虑在内:2.png


这里的wuv由两部分相似度构成,一部分是用户u和用户v的熟悉程度,另一部分是用户u和用户v的兴趣相似度。

其中,用户u和用户v的熟悉程度由如下公式度量,即他们之间的共同好友比例:

而用户u和用户v的兴趣相似度由如下公式度量,即他们喜欢的物品重合度:

3.png


从两方面改进基于邻域的社会化推荐算法


两处截断:


第一处截断:哪用户好友集合时只拿出和用户相似度最高的N个好友

第二处截断:查询用户行为做兴趣相似度时,只返回最近1个月的行为

重新设计数据库


给用户推荐好友


基于内容的匹配


常用内容属性包括:

用户的人口统计学属性(年龄、职业、性别等);

用户的兴趣(喜欢的物品和发布过的言论);

用户的位置信息(用户住址、邮编、IP等);


基于共同兴趣的好友推荐


利用UserCF的思想,如果两个用户喜欢相同的物品(比如同一条微博),就说明他们具有相似的兴趣;此外,也可以根据用户在社交网络中的评论提取用户的兴趣标签,来计算用户的兴趣相似度。


基于社交网络图的好友推荐


基于社交网络图的好友推荐

out(u)是在社交网络图中用户u指向的其他好友的集合

in(u)是在社交网络图中指向用户u的用户集合


通过用户u和用户v的出度和入度,定义W。根据相似度W进行推荐


计算相似度方法的解释在最后代码里

有下面几种方法计算相似度:

1.用户u,v的共同好友比例来计算相似度

5.png

def FriendSuggestion_out(u,G_out,G_in):
    suggestions = dict()
    G_out.setdefault(u,set())
    G_in.setdefault(u,set())
    friends = G_out[u]
#     i = 0
    for u_friend in G_out[u]:
#         i += 1
        for u_friend_friend in G_in[u_friend]:
            if u_friend_friend in friends:
                continue
            suggestions.setdefault(u_friend_friend,0)
            suggestions[u_friend_friend] += 1
    for i,j in suggestions.items():
        if i == u:
            continue
        if len(G_out[i]) == 0:
            suggestions[i] = 0
        else:
            suggestions[i] = j / math.sqrt(len(G_out[u]) * len(G_out[i])) 
#     return dict(sorted(suggestions.items(),key=itemgetter(1),reverse=True)[:k])
    return suggestions

2.关注u,v的用户的集合交集计算相似度

6.png

def FriendSuggestion_in(u,G_out,G_in):
    suggestions = dict()
    G_out.setdefault(u,set())
    G_in.setdefault(u,set())
    friends = G_out[u]
#     i = 0
    for u_friend in G_in[u]:
#         i += 1
        for u_friend_friend in G_out[u_friend]:
            if u_friend_friend in friends:
                continue
            suggestions.setdefault(u_friend_friend,0)
            suggestions[u_friend_friend] += 1
#         print(i)
#         suggestions[u_friend] = suggestions[u_friend_friend]
    for i,j in suggestions.items():
        if i == u:
            continue
        if len(G_in[i]) == 0:
            suggestions[i] = 0
        else:
            suggestions[i] = j / math.sqrt(len(G_in[u]) * len(G_in[i])) 
    return suggestions

3.u关注的用户中,有多大比例也关注用户v,同时施加惩罚in(v)来计算相似度

(考虑到某一名人,存在很多粉丝,导致每个人都与名人有很大相似度 例如有一亿粉丝的何老师~)

7.png

def FriendSuggestion_mix(u,G_out,G_in):
    suggestions = dict()
    G_out.setdefault(u,set())
    G_in.setdefault(u,set())
    friends = G_out[u]
    for u_friend in G_out[u]:
        for u_friend_friend in G_out[u_friend]:
            if u_friend_friend in friends:
                continue
            suggestions.setdefault(u_friend_friend,0)
            suggestions[u_friend_friend] += 1
#         suggestions[u_friend] = suggestions[u_friend_friend]
    for i,j in suggestions.items():
        if len(G_in[i]) == 0:
            suggestions[i] = 0
        else:
            suggestions[i] = j / math.sqrt(len(G_out[u]) * len(G_in[i])) 
    return suggestions


实现给用户推荐好友的完整过程代码


import os
import math
from operator import itemgetter
from sklearn.model_selection import train_test_split
import random
#获取文件列表 取前200个文件¶
edges = [name for name in os.listdir('twitter/')
         if name.endswith(".edges")]
#edges[:5]
train_G_out = dict()
test_G_out = dict()
train_G_in = dict()
test_G_in = dict()
#获取文件名的ID 以及.edges文件里的id 得到out in 两个字典
for file in edges[:200]:
    with open('twitter/' + file) as f:
        lines = f.readlines()
    for line in lines:
        a,b = line.split(" ")
        b = b.strip("\n")
        if random.random() < 0.8: #划分数据集
            train_G_out.setdefault(file[:-6],set())
            train_G_out.setdefault(a,set())
            train_G_out.setdefault(b,set())
            train_G_out[file[:-6]].add(a)
            train_G_out[file[:-6]].add(b)
            train_G_out[a].add(b)
            train_G_in.setdefault(file[:-6],set())
            train_G_in.setdefault(a,set())
            train_G_in.setdefault(b,set())
            train_G_in[a].add(file[:-6])
            train_G_in[b].add(a)
            train_G_in[b].add(file[:-6]) #str
        else:
            test_G_out.setdefault(file[:-6],set())
            test_G_out.setdefault(a,set())
            test_G_out.setdefault(b,set())
            test_G_out[file[:-6]].add(a)
            test_G_out[file[:-6]].add(b)
            test_G_out[a].add(b)
            test_G_in.setdefault(file[:-6],set())
            test_G_in.setdefault(a,set())
            test_G_in.setdefault(b,set())
            test_G_in[a].add(file[:-6])
            test_G_in[b].add(a)
            test_G_in[b].add(file[:-6]) #str
def FriendSuggestion_out(u,G_out,G_in):
    suggestions = dict()
    G_out.setdefault(u,set())
    G_in.setdefault(u,set())
    friends = G_out[u]
#     i = 0
    for u_friend in G_out[u]:  #遍历用户u关注的好友
#         i += 1
        for u_friend_friend in G_in[u_friend]: #u关注的好友中的粉丝列表
            if u_friend_friend in friends: #若粉丝是u关注的好友就跳过
                continue
            suggestions.setdefault(u_friend_friend,0) 
            suggestions[u_friend_friend] += 1 #对于u关注的好友的粉丝与u有一个交集 进行+1
    for i,j in suggestions.items():
        if i == u:  #去除本身
            suggestions[i] = 0
        elif len(G_out[i]) == 0:
            suggestions[i] = 0
        else:
            suggestions[i] = j / math.sqrt(len(G_out[u]) * len(G_out[i])) 
#     return dict(sorted(suggestions.items(),key=itemgetter(1),reverse=True)[:k])
    return suggestions
def FriendSuggestion_in(u,G_out,G_in):
    suggestions = dict()
    G_out.setdefault(u,set())
    G_in.setdefault(u,set())
    friends = G_out[u]
#     i = 0
    for u_friend in G_in[u]: #遍历关注用户u的粉丝
#         i += 1
        for u_friend_friend in G_out[u_friend]: #u的粉丝的关注列表好友
            if u_friend_friend in friends:
                continue
            suggestions.setdefault(u_friend_friend,0)
            suggestions[u_friend_friend] += 1  #uv的粉丝交集 +1
#         print(i)
#         suggestions[u_friend] = suggestions[u_friend_friend]
    for i,j in suggestions.items():
        if i == u:
            suggestions[i] = 0
        elif len(G_in[i]) == 0:
            suggestions[i] = 0
        else:
            suggestions[i] = j / math.sqrt(len(G_in[u]) * len(G_in[i])) 
    return suggestions
def FriendSuggestion_mix(u,G_out,G_in):
    suggestions = dict()
    G_out.setdefault(u,set())
    G_in.setdefault(u,set())
    friends = G_out[u]
    for u_friend in G_out[u]: #遍历u关注的好友列表
        for u_friend_friend in G_out[u_friend]: #遍历u好友的关注列表 即u关注的好友是u_friend_friend的粉丝 
            if u_friend_friend in friends:
                continue
            suggestions.setdefault(u_friend_friend,0)
            suggestions[u_friend_friend] += 1  #即u关注的好友有多大比例是用户v的粉丝 交集+1
#         suggestions[u_friend] = suggestions[u_friend_friend]
    for i,j in suggestions.items():
        if i == u:
            suggestions[i] = 0
        elif len(G_in[i]) == 0:
            suggestions[i] = 0
        else:
            suggestions[i] = j / math.sqrt(len(G_out[u]) * len(G_in[i])) 
    return suggestions
def recommend(u,G_out,G_in,k,choice):
    if choice == 'out':
        suggestions = FriendSuggestion_out(u,G_out,G_in)
    elif choice == 'in':
        suggestions = FriendSuggestion_in(u,G_out,G_in)
    else:
        suggestions = FriendSuggestion_mix(u,G_out,G_in)
    return dict(sorted(suggestions.items(),key=itemgetter(1),reverse=True)[:k])
def precision(k,choice):
    right = 0
    predict = 0
    for u in test_G_out.keys():
        x = recommend(u,train_G_out,train_G_in,k,choice)
        for i in x.keys():
            if i in test_G_out[u]:
                right += 1
        predict += k
    ans = right / (predict * 1.0)
    return ans * 100
#为用户‘100318079’推荐
print(recommend('100318079',train_G_out,train_G_in,5,'out'))
#验证测试集正确率
print("正确率:%.2f%%"%(precision(4,'mix')))
#{'217796457': 0.36794648440311994, 
#  '261753869': 0.3611730459561101, 
#  '92336981': 0.3611730459561101, 
#  '77618627': 0.35781322366606716, 
#  '540912889': 0.3517811819867572}
#正确率:19.80%
相关文章
|
17天前
|
机器学习/深度学习 PyTorch TensorFlow
卷积神经网络深度解析:从基础原理到实战应用的完整指南
蒋星熠Jaxonic,深度学习探索者。深耕TensorFlow与PyTorch,分享框架对比、性能优化与实战经验,助力技术进阶。
|
25天前
|
传感器 机器学习/深度学习 算法
【UASNs、AUV】无人机自主水下传感网络中遗传算法的路径规划问题研究(Matlab代码实现)
【UASNs、AUV】无人机自主水下传感网络中遗传算法的路径规划问题研究(Matlab代码实现)
|
1月前
|
机器学习/深度学习 算法 调度
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
192 0
|
18天前
|
监控 负载均衡 安全
WebSocket网络编程深度实践:从协议原理到生产级应用
蒋星熠Jaxonic,技术宇宙中的星际旅人,以代码为舟、算法为帆,探索实时通信的无限可能。本文深入解析WebSocket协议原理、工程实践与架构设计,涵盖握手机制、心跳保活、集群部署、安全防护等核心内容,结合代码示例与架构图,助你构建稳定高效的实时应用,在二进制星河中谱写极客诗篇。
WebSocket网络编程深度实践:从协议原理到生产级应用
|
19天前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
|
29天前
|
机器学习/深度学习 人工智能 算法
卷积神经网络深度解析:从基础原理到实战应用的完整指南
蒋星熠Jaxonic带你深入卷积神经网络(CNN)核心技术,从生物启发到数学原理,详解ResNet、注意力机制与模型优化,探索视觉智能的演进之路。
278 11
|
1月前
|
机器学习/深度学习 并行计算 算法
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
|
27天前
|
机器学习/深度学习 缓存 算法
2025年华为杯A题|通用神经网络处理器下的核内调度问题研究生数学建模|思路、代码、论文|持续更新中....
2025年华为杯A题|通用神经网络处理器下的核内调度问题研究生数学建模|思路、代码、论文|持续更新中....
268 1
|
28天前
|
算法 数据挖掘 区块链
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
|
1月前
|
传感器 数据采集 存储
【无线传感器】使用 MATLAB和 XBee连续监控温度传感器无线网络研究(Matlab代码实现)
【无线传感器】使用 MATLAB和 XBee连续监控温度传感器无线网络研究(Matlab代码实现)