基于jaccard计算论文对的reference相似度的算法(2)

基本实现思路:每次输入两个论文的名字,然后通过查询node.list找到相应的id,或者直接输入论文id进行查询,然后在link.json中找到他引用的所有论文集合,然后计算jaccard相似度。模型中会遇到大量的查询两个论文引用的jaccard相似度,这样查询速度比较慢。由于样本数据量较大,后续使用时,每次读取所有的数据(一对一的引用关系),然后计算相似度速度比较慢,所以把数据集进行了整理,以每篇论文的id为key,以引用的论文的id列表为value进行保存,保存到link.json没有把所有的论文对的相似度计算完保存起来,是因为维度比较高,且数据比较稀疏。(注:对称且稀疏矩阵,可以采用压缩存储。)
算法:十分简单的杰卡德系数(Jaccard Index),也称Jaccard相似系数(Jaccard similarity coefficient),用于比较有限样本集之间的相似性与差异性。如集合间的相似性、字符串相似性、目标检测的相似性、文档查重等
Jaccard系数的计算方式为:交集个数和并集个数的比值
在这里插入图片描述
在这里插入图片描述

数据来源:计算所使用的数据来自已经给出的ACM数据集,其中的inlinks.list和outlinks.list的数据是两列论文id,都是前面的id所对应的论文引用后面的id所对应的论文。
有待改进的地方
1.所给数据集只是在一定范围内的引用关系,并不全面,不能较为准确的反应论文对引用的相似度,可以爬取所有的引用关系,然后再计算。
2.可以把所有的论文对引用相似度计算出来,自己尝试进行计算时,还是使用了大量的时间,若是直接带入模型,进行计算,会耗费大量的时间。至于占用空间比较大。可以采用矩阵的压缩存储。
3.在论文所引用的集合中,不同的论文所占有权重也应该是不同的。有的论文对相似度贡献比较大,有的比较小。可以加入惩罚因子。但是究竟是引用量高的被引论文对相似度的贡献更大,还是较少出现的偏僻的被引论文对相似度的贡献更大呢?

直接计算:

def node_id(name):
     fp=open("C:\\Users\\asus\\Desktop\\实训\\资料整理\\code+data\\ACM数据集\\nodes.list",'r')
     while(fp.readline()):
        id,node=fp.readline().rstrip().split("\t")
        if node==name:
            return id

#若是引用关系不在变化,需不需建立一个表直接把信息存起来
def jaccard2id(a,b):
    links1=set()
    links2=set()
    fp=open("C:\\Users\\asus\\Desktop\\实训\\资料整理\\code+data\\ACM数据集\\inlinks.list",'r')
    while(fp.readline()):
        links_from,links_to=fp.readline().rstrip().split("\t")
        if links_from==a:
            links1.add(links_to)
        if links_from==b:
            links2.add(links_to)
    
    if links1.intersection(links2)==None or links1.intersection_update(links2)==None:
        return 0
    else:
        common=len(links1.intersection(links2))
        all2=len(links1.intersection_update(links2))
        jaccard=common/(all2+1)  
        return jaccard

if __name__ == '__main__':
    name1=input("请输入第一篇论文的名字:")
    name2=input("请输入第二篇论文的名字:")
    id1=node_id(name1)
    id2=node_id(name2)
    samilarity=jaccard2id(id1,id2)
    print(samilarity)

保存到文件中:

import json

def essay_link():
    link=dict()
    fp=open("C:\\Users\\asus\\Desktop\\实训\\资料整理\\code+data\\ACM数据集\\inlinks.list",'r')
    while(fp.readline()):
        link_from,link_to=fp.readline().rstrip().split("\t")
        if link_from in link:
            link[link_from].append(link_to)#link['link_from']那么key就是link_from
        else:
            link[link_from]=[link_to]
    #value用list保存,用set()不能保存为json
    json_str = json.dumps(link, indent=4)
    with open('link.json', 'w') as json_file:
        json_file.write(json_str)
        
def jaccard(id1,id2):
    with open('link.json', 'r') as json_file:
        link=json.load(json_file)
    if id1 in link and id2 in link:
        links1=set(link[id1])
        links2=set(link[id2])
        if links1.intersection(links2)==None or links1.intersection_update(links2)==None:
            return 0
        else:
            # common=len(links1.intersection(links2))
            # all2=len(links1.intersection_update(links2))
            # jaccard=common/(all2+1)  #已经不为0了,感觉不加1平滑也可以了
            jaccard=len(links1.intersection(links2))/(len(links1.intersection_update(links2))+1)#借鉴推荐系统上惩罚热门的做法???
            return jaccard
    else:
        return -1
    

def name_query():
    name1=input("请输入第一篇论文的名字:")
    name2=input("请输入第二篇论文的名字:")
    fp=open("C:\\Users\\asus\\Desktop\\实训\\资料整理\\code+data\\ACM数据集\\nodes.list",'r')
    while(fp.readline()):
        id,node=fp.readline().rstrip().split("\t")
        if node==name1:
            id1=id
        if node==name2:
            id2=id
    return jaccard(id1,id2)

def id_query():
    id1=input("请输入第一篇论文的编号:")
    id2=input("请输入第二篇论文的编号:")
    return jaccard(id1,id2)
#计算所有论文对的jaccard相似度
def jall():
    fp=open("C:\\Users\\asus\\Desktop\\实训\\资料整理\\code+data\\ACM数据集\\nodes.list",'r')
    id=[]
    while(fp.readline()):
        iid,name=fp.readline().rstrip().split("\t")
        id.append(iid)
    #print(id)
    fp.close()
    f=open('jaccard.txt', 'w')      
    for i in range(len(id)):
        for j in range(i+1,len(id)):
            jac=jaccard(id[i], id[j])
 
    f.writelines([str(id[i])+'\t'+str(id[j])+'\t'+str(jac)+'\n'])
    f.close()
if __name__ == '__main__':
    #essay_link()
    #name_query()
    #print(id_query())
    jall()
    

运行结果:
下图为link.json里面的内容,很多仅有两三篇引用文献,所以大部分的引用关系不是特别全面。
在这里插入图片描述
下图是计算出的相似度,-1表示没有引用关系(没有引用其他文献和被其他文献引用),直接保存相似度还是比较稀疏和占用空间的。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值