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

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

获取社交网络数据途径


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

电子邮件

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

用户的位置数据: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%
相关文章
|
9天前
|
NoSQL Java Redis
Redis系列学习文章分享---第十八篇(Redis原理篇--网络模型,通讯协议,内存回收)
Redis系列学习文章分享---第十八篇(Redis原理篇--网络模型,通讯协议,内存回收)
20 0
|
9天前
|
存储 消息中间件 缓存
Redis系列学习文章分享---第十七篇(Redis原理篇--数据结构,网络模型)
Redis系列学习文章分享---第十七篇(Redis原理篇--数据结构,网络模型)
13 0
|
5天前
|
XML JSON 安全
Base64编码原理与在网络传输中的应用
Base64编码原理与在网络传输中的应用
|
5天前
|
机器学习/深度学习 编解码 数据可视化
图神经网络版本的Kolmogorov Arnold(KAN)代码实现和效果对比
目前我们看到有很多使用KAN替代MLP的实验,但是目前来说对于图神经网络来说还没有类似的实验,今天我们就来使用KAN创建一个图神经网络Graph Kolmogorov Arnold(GKAN),来测试下KAN是否可以在图神经网络方面有所作为。
26 0
|
9天前
程序技术好文:计算机网络(九)——STP原理
程序技术好文:计算机网络(九)——STP原理
12 1
|
10天前
|
安全 网络协议 算法
Android网络基础面试题之HTTPS的工作流程和原理
HTTPS简述 HTTPS基于TCP 443端口,通过CA证书确保服务器身份,使用DH算法协商对称密钥进行加密通信。流程包括TCP握手、证书验证(公钥解密,哈希对比)和数据加密传输(随机数加密,预主密钥,对称加密)。特点是安全但慢,易受特定攻击,且依赖可信的CA。每次请求可能复用Session ID以减少握手。
17 2
|
16天前
|
网络协议 网络架构 数据格式
网络原理,网络通信以及网络协议
网络原理,网络通信以及网络协议
12 1
|
17天前
|
机器学习/深度学习 算法 计算机视觉
没有公式,不要代码,让你理解 RCNN:目标检测中的区域卷积神经网络
没有公式,不要代码,让你理解 RCNN:目标检测中的区域卷积神经网络
43 0
没有公式,不要代码,让你理解 RCNN:目标检测中的区域卷积神经网络
|
20天前
|
机器学习/深度学习 搜索推荐 PyTorch
【机器学习】图神经网络:深度解析图神经网络的基本构成和原理以及关键技术
【机器学习】图神经网络:深度解析图神经网络的基本构成和原理以及关键技术
143 2
|
20天前
|
监控 网络协议 安全
Verilog代码在上网行为管理软件中的网络设备控制与协议分析
**Verilog摘要:** Verilog是硬件描述语言,用于数字电路设计和网络设备控制。它在上网行为管理软件中用于控制路由器、交换机等,例如通过简单模块控制端口状态。此外,Verilog还支持协议分析,如解析以太网帧提取MAC地址。监控数据可结合Verilog实现自动化提交,例如通过HTTP发送请求到服务器,实现实时监控和响应。这些示例展示了Verilog在网络安全和性能优化中的应用潜力。
81 1