前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >几百个作者有相同的名字?| 智源-AMiner大赛,从EDA到冠军baseline

几百个作者有相同的名字?| 智源-AMiner大赛,从EDA到冠军baseline

作者头像
大数据文摘
发布2019-11-14 00:00:45
8080
发布2019-11-14 00:00:45
举报
文章被收录于专栏:大数据文摘大数据文摘

大数据文摘出品

2019年10月,智源-AMiner 北京智源人工智能研究院和AMiner联合发布了一个大规模姓名排歧数据集OAG – WhoIsWho,这是目前为止发布的人工标注数据规模最大的姓名消歧数据集。

依托数据集,智源和AMiner联合发布了一项奖金为10万元的比赛。目前,比赛仍在进行中。我们邀请了一些参赛选手对数据集进行了一些有趣的探索,另外还邀请了AMiner官方和往届比赛获奖选手提供了两个baseline。EDA和baseline的代码和结果都可以到比赛页面的“Models”栏目查看。

相关链接:

https://biendata.com/competition/aminer2019/

本次比赛部分选手的EDA和baseline代码

在外文期刊数据库中,同一姓名简称代表多位作者的现象十分普遍,严重影响作者检索的精度,所以在此查看论文作者的重名、缩写名、别名等信息。发现在训练集中作者同名数量为221,平均每个同名作者们的论文数在1000左右。同样的在测试集中,同名作者数量为50,其所涉及的平均论文数量是917.96。

代码语言:javascript
复制
authors = [author for author in train_data]authors_num_person = [len(train_data[author].keys()) for author in train_data]print('训练集同名数量:', len(authors))print('消歧后实际作者数量:',  sum(authors_num_person))
# 以绘制训练集同名作者个体数量为例plt.figure(figsize=(40, 8), dpi=80)x = range(len(authors))
plt.bar(x, authors_num_person, width=0.5)plt.xticks(x, authors)plt.xticks(rotation=270)plt.xlabel('训练集同名作者')plt.ylabel('该名字同名作者数量(个)')for xl, yl in zip(x, authors_num_person):    plt.text(xl, yl+0.3, str(yl), ha='center', va='bottom', fontsize=10.5)
mean_person = int(np.mean(authors_num_person))plt.gca().hlines(mean_person,-1,225,linestyles='--',colors='red',label='平均值')plt.annotate(u"平均值:" + str(mean_person), xy = (225, mean_person), xytext = (225, mean_person+40),arrowprops=dict(facecolor='red',shrink=0.1,width=2))
代码语言:javascript
复制
训练集同名数量:221消歧后实际作者数量:22839涉及的论文总数(篇):205498

查看几条重名作者的信息后,我们可以发现,论文作者名字存在不一致的情况主要源于名字大小写问题、姓和名顺序不一致、名字带有下划线或横线、名字是否简写、以及名字是否分开写,例如:

代码语言:javascript
复制
paper id: zszavvJhpaper author name:  feifei chengpaper author name:  heng lipaper author name:  y w wangpaper author name:  martin skitmorepaper author name:  p j forsythebr

来源:赛道一,朱丽

同理,机构的表达也可能存在不一致的情况,因此需要对数据做相应的预处理统一表达之后,再具体查看某一作者的论文作者名中是否包含消歧作者名。实际情况中,一个作者可能有多个机构,一个机构有很多种表述方式,一些特殊姓氏可能都集中在一个国家(比如日本),同一个期刊可能同时存在简称和全称等等消歧情况,所以在此查看机构、协作作者、协作机构、常用关键词、发表的会议期刊是否有交集。发现有交集,所以在用基于规则的方式处理时需要注意。

代码语言:javascript
复制
# 查看机构、协作作者、协作机构、常用关键词、发表的会议期刊是否有交集for aid1 in author_data:    for aid2 in author_data:        if aid1 != aid2:            if set(org[aid1]).intersection(set(org[aid2])):                print('%s与%s机构重叠:' % (aid1, aid2), set(org[aid1]).intersection(set(org[aid2])))            if set(co_author[aid1]).intersection(set(co_author[aid2])):                print('%s与%s协作者重叠:' % (aid1, aid2), set(co_author[aid1]).intersection(set(co_author[aid2])))            if set(co_org[aid1]).intersection(set(co_org[aid2])):                print('%s与%s协作机构重叠:' % (aid1, aid2), set(co_org[aid1]).intersection(set(co_org[aid2])))            if set(keywords[aid1]).intersection(set(keywords[aid2])):                print('%s与%s关键词重叠:' % (aid1, aid2), set(keywords[aid1]).intersection(set(keywords[aid2])))            if set(venue[aid1]).intersection(set(venue[aid2])):                print('%s与%s会议期刊重叠:' % (aid1, aid2), set(venue[aid1]).intersection(set(venue[aid2])))br
代码语言:javascript
复制
bXCEdRdj与WSFIcbxu关键词重叠: {'chemical composition'}bXCEdRdj与WSFIcbxu会议期刊重叠: {'Journal of Agricultural and Food Chemistry'}bXCEdRdj与gUSOTB2u会议期刊重叠: {'Journal of home economics'}OaaWMLWs与5Bxjg2tr协作者重叠: {'Shoei Sato'}OaaWMLWs与5Bxjg2tr会议期刊重叠: {'APSIPA'}WSFIcbxu与bXCEdRdj关键词重叠: {'chemical composition'}WSFIcbxu与bXCEdRdj会议期刊重叠: {'Journal of Agricultural and Food Chemistry'}CsE5vsJA与JvJ9opoq协作者重叠: {'Hiroki Sakaji'}gUSOTB2u与bXCEdRdj会议期刊重叠: {'Journal of home economics'}5Bxjg2tr与OaaWMLWs协作者重叠: {'Shoei Sato'}5Bxjg2tr与OaaWMLWs会议期刊重叠: {'APSIPA'}JvJ9opoq与CsE5vsJA协作者重叠: {'Hiroki Sakaji'}br

一个作者的协作者、所发的会议期刊、关键词都有可能重叠,在使用相关规则需要谨慎。

来源:赛道一,桑运鑫

那么我们在使用规则处理时,就可以采用预处理机构的简写替换,以及使用正则表达式去除特殊的无意义标点符号或连接符号。例如:

代码语言:javascript
复制
#正则去标点def etl(content):    content = re.sub("[\s+\.\!\/,;$%^*(+\"\')]+|[+——()?【】“”!,。?、~@#¥%……&*()]+", " ", content)    content = re.sub(r" {2,}", " ", content)    return content
def get_org(co_authors, author_name):    for au in co_authors:        name = precessname(au['name'])        name = name.split('_')        if ('_'.join(name) == author_name or '_'.join(name[::-1]) == author_name) and 'org' in au:            return au['org']    return ''

来源:赛道一,朱丽

此外,一个作者,一段时间内应该是在一个单位工作的,我们可以根据作者的工作单位变动信息来为作者构建一个时间段映射到工作单位的表,在给出新论文时,用论文年份和作者工作单位进行辅助筛选。为此引入年份和工作单位,我们统计一下作者工作单位变化情况。发现共计262388份论文,其中无年份或者年份错误的占比很少,只有698份论文没有年份信息,所以绝大部分数据是有效的,可以利用这个特征。

代码语言:javascript
复制
# 统计论文的年份范围min_year = 3000max_year = 0pubs_no_year = 0for each in tqdm(author_pub.items()):    try:        year = int(each[1]['year'])    except:        pubs_no_year += 1        print("Paper {} has no year info".format(each[0]))        continue    if year<1500 or year>2100:        pubs_no_year +=1        print("Paper {} has wrong year info: {}".format(each[0], year))        continue    if year<min_year:        min_year = year    if year>max_year:        max_year = yearprint(min_year, max_year)print("共计{}份论文没有年份信息".format(pubs_no_year))

来源:赛道二,尹恒

关于同名作者数量分布,经探索发现数量大都在 [2,30] 之间, 也有部分名字重名极多在 [200,400] 之间。

代码语言:javascript
复制
import seaborn as snsimport matplotlib.pyplot as pltsns.distplot(same_author_num,30,hist_kws={"rwidth":0.0001,'edgecolor':'black', 'alpha':1.0})br
代码语言:javascript
复制
sns.distplot(same_author_num,300,             hist_kws=dict(cumulative=True),             kde_kws=dict(cumulative=True))br
代码语言:javascript
复制
sns.distplot(same_author_num,3000,             hist_kws=dict(cumulative=True),             kde_kws=dict(cumulative=True))plt.xlim(0,100)br
代码语言:javascript
复制
sns.distplot(thesis_percent,30,hist_kws={"rwidth":0.001,'edgecolor':'black', 'alpha':1.0})br
代码语言:javascript
复制
sns.distplot(thesis_percent,300,             hist_kws=dict(cumulative=True),             kde_kws=dict(cumulative=True))br
代码语言:javascript
复制
for name in train_author.keys()[15:20]:    f, ax = plt.subplots(figsize=(8, 6))    plt.plot([len(train_author[name][author])for author in train_author[name].keys()])br

同名作者的发文数量和时间段也有迹可循,大部分作者都有持续发表论文,越早发表第一篇论文的作者更有可能发表更多的论文,这可能和年龄有关。并且之后发表论文的速度越来越快。

代码语言:javascript
复制
# 同名中各个作者发布论文区间count=0for name in train_author.keys()[15:20]:    f, ax = plt.subplots(figsize=(8, 6))    authors = train_author[name].keys()    for author in authors:        years=[]        for thesis in train_author[name][author]:            if 'year' in train_pub[thesis].keys():                years.append(train_pub[thesis]['year'])        plt.plot(np.sort(years))    plt.ylim(1990,2020)    if count==3:        print(name)    count+=1br

来源:赛道一,林志豪

无监督聚类DBSCAN(根据合作者和机构TFIDF进行相似度聚类)

代码语言:javascript
复制
for author in validate_data:
    # print(author)    coauther_orgs = []    papers = validate_data[author]    if len(papers) == 0:        res_dict[author] = []        continue    # print(len(papers))    paper_dict = {}    for paper in papers:        authors = paper['authors']        names = [precessname(paper_author['name']) for paper_author in authors]        orgs = [preprocessorg(paper_author['org']) for paper_author in authors if 'org' in paper_author]        abstract = paper["abstract"] if 'abstract' in paper else ''        coauther_orgs.append(etl(' '.join(names + orgs) + ' '+ abstract))    tfidf = TfidfVectorizer().fit_transform(coauther_orgs)

    clf = DBSCAN(metric='cosine')    s = clf.fit_predict(tfidf)    # 每个样本所属的簇    for label, paper in zip(clf.labels_, papers):        if str(label) not in paper_dict:            paper_dict[str(label)] = [paper['id']]        else:            paper_dict[str(label)].append(paper['id'])    res_dict[author] = list(paper_dict.values())
    tfidf = PCA(n_components=2, random_state=0).fit_transform(tfidf.toarray())

无监督聚类AffinityClustering(根据合作者和机构TFIDF进行相似度聚类)。

由于该算法运行效率问题,只对最后一名作者的聚类结果进行了可视化。

代码语言:javascript
复制
res_dict = {}t0 = time()for author in validate_data:    # print(author)    coauther_orgs = []    papers = validate_data[author]    if len(papers) == 0:        res_dict[author] = []        continue    # print(len(papers))    paper_dict = {}    for paper in papers:        authors = paper['authors']        names = [precessname(paper_author['name']) for paper_author in authors]        orgs = [preprocessorg(paper_author['org']) for paper_author in authors if 'org' in paper_author]        abstract = paper["abstract"] if 'abstract' in paper else ''        coauther_orgs.append(etl(' '.join(names + orgs) + ' '+ abstract))    tfidf = TfidfVectorizer().fit_transform(coauther_orgs)
    # affinity_clustering,参数可以调整,此处进攻参考,未提交测试    clf = cluster.AffinityPropagation(damping=.9, preference=-20)    s = clf.fit_predict(tfidf)    # 每个样本所属的簇    for label, paper in zip(clf.labels_, papers):        if str(label) not in paper_dict:            paper_dict[str(label)] = [paper['id']]        else:            paper_dict[str(label)].append(paper['id'])    res_dict[author] = list(paper_dict.values())
t1 = time()print('running time: %.2fs'% (t1 - t0))
# 降维tfidf = PCA(n_components=2, random_state=0).fit_transform(tfidf.toarray())

来源:赛道一,朱丽

最后,AMiner官方和往届比赛获奖选手分别为两个赛道提供了baseline代码供大家参考:

赛道一:

申发海,重庆邮电大学计算机硕士,研究方向涉及计算机视觉,机器学习,深度学习,曾获CCIR2019基于电子病历的数据查询类问答大赛第一名,2018开放学术数据挖掘大赛第二名,搜狐图文匹配算法大赛三等奖等。

相关链接:

https://biendata.com/models/category/3000/L_notebook/

赛道二:

陈波,中国人民大学信息学院计算机科学与技术系学术型研究生,主要研究方向为数据集成,知识图谱及社交网络相关研究。目前致力于学术网络中的实体消歧与跨语言知识图谱对齐等研究。

相关链接:

https://biendata.com/models/category/2998/L_notebook/

实习/全职编辑记者招聘ing

加入我们,亲身体验一家专业科技媒体采写的每个细节,在最有前景的行业,和一群遍布全球最优秀的人一起成长。坐标北京·清华东门,在大数据文摘主页对话页回复“招聘”了解详情。简历请直接发送至zz@bigdatadigest.cn

点「在看」的人都变好看了哦!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据文摘 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本次比赛部分选手的EDA和baseline代码
相关产品与服务
灰盒安全测试
腾讯知识图谱(Tencent Knowledge Graph,TKG)是一个集成图数据库、图计算引擎和图可视化分析的一站式平台。支持抽取和融合异构数据,支持千亿级节点关系的存储和计算,支持规则匹配、机器学习、图嵌入等图数据挖掘算法,拥有丰富的图数据渲染和展现的可视化方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档