词义消歧的研究通常需要语义词典的支持,因为词典描述了词语的义项区分。英语的词义消歧研究中使用的词典主要是ordNet,而中文使用的词典有HowNet,以及北京大学的“现代汉语语义词典”等。
除词典外,词义标注语料库标注了词的不同义项在真实文本中的使用状况,为开展有监督的词义消歧研究提供了数据支持。常见的英文词义标注语料库包括Semcor(普林斯顿大学标注)、DSO(新加坡国立大学标注)以及用于Senseval 评测的语料库等。在中文方面,哈尔滨工业大学和北京大学分别基于HowNet 和北大“现代汉语语义词典”标注了词义消歧语料库。

词义消歧的研究是自然语言处理的一项基础关键,根据所使用的资源类型不同,可以将词义消歧方法分为以三类:
1、基于词典的词义消歧

基于词典的词义消歧方法研究的早期代表工作是Lesk 于1986 的工作。给定某个待消解词及其上下文,该工作的思想是计算语义词典中各个词义的定义与上下文之间的覆盖度,选择覆盖度最大的作为待消解词在其上下文下的正确词义。但由于词典中词义的定义通常比较简洁,这使得与待消解词的上下文得到的覆盖度为0,造成消歧性能不高。
2、有监督词义消歧

有监督的消歧方法使用词义标注语料来建立消歧模型,研究的重点在于特征的表示。常见的上下文特征可以归纳为三个类型:(1)词汇特征通常指待消解词上下窗口内出现的词及其词性;
(2)句法特征利用待消解词在上下文中的句法关系特征,如动-宾关系、是否带主/宾语、主/宾语组块类型、主/宾语中心词等;
(3)语义特征在句法关系的基础上添加了语义类信息,如主/宾语中心词的语义类,甚至还可以是语义角色标注类信息。

最近随着深度学习在自然语言处理领域的应用,基于深度学习方法的词义消歧成为这一领域的一大热点。深度学习算法自动的提取分类需要的低层次或者高层次特征,避免了很多特征工程方面的工作量。
3、无监督和半监督词义消歧

虽然有监督的消歧方法能够取得较好的消歧性能,但需要大量的人工标注语料,费时费力。为了克服对大规模语料的需要,半监督或无监督方法仅需要少量或不需要人工标注语料。
例如Yarowsky(1995)仅需要使用少量的人工标注语料作为种子数据,Ng 等(2003)从词对齐的双语语料抽取种子数据。Resnik(1997)根据词的不同歧义往往也体现在句法搭配上的差异这一思想,通过计算“语义优选强度”和“选择关联度”在大规模语料中自动获取句法结构的语义优选,然后用之于词义消歧。
一般说来,虽然半监督或无监督方法不需要大量的人工标注数据,但依赖于一个大规模的未标注语料,以及在该语料上的句法分析结果。另一方面,待消解词的覆盖度可能会受影响。
例如,Resnik(1997)仅考察某部分特殊结构的句法,只能对动词、动词的主词/宾语、形容词修饰的名词等少数特定句去位置上的词进行消歧,而不能覆盖所有歧义词。

`具体代码如下:

import os
from urllib import request
from lxml import etree
from urllib import parse
import jieba.posseg as pseg
import jieba.analyse as anse
import numpy as np

embedding_size =300
embedding_path = “D:\workspace\project\NLPcase\mutilSenmanticWord\data\wrod_vec_300.bin”
sim_limit = 0.8

def get_html(url):
‘’‘根据url,获取html页面’’’
return request.urlopen(url).read().decode(‘utf-8’).replace(’&nbsp’,’’)
def collect_mutilsens(word):
‘’‘根据单词,到百度百科上面去查询各种语义相关的句子’’’
url = “http://baike.baidu/item/%s?force=1”%parse.quote(word)#parser.quote 对含有特殊符号的URL进行编码,使其转换为合法的url字符串
html = get_html(url)
selector = etree.HTML(html)
sens = [ ‘’.join(i.split(’:’))for i in selector.xpath(’//li[@class=“list-dot list-dot-paddingleft”]/div/a/text()’)]
sens_link = [‘http://baike.baidu’ + i for i in selector.xpath(’//li[@class=“list-dot list-dot-paddingleft”]/div/a/@href’)]
sens_dict = {sens[i]:sens_link[i] for i in range(len(sens))}
return sens_dict

def extract_concept(desc):
‘’‘概念抽取’’’
desc_seg = [[i.word,i.flag] for i in pseg.cut(desc)]
concepts_candi = [i[0] for i in desc_seg if i[1] in [‘n’,‘b’,‘v’,‘d’]]
return concepts_candi[-1]

def entity_clusters(s):
‘’‘对具有联通边的实体进行聚类’’’
clusters = []
for i in range(len(s)):
cluster = s[i]
for j in range(len(s)):
if set(s[i]).intersection(set(s[j])) and set(s[i]).intersection(set(cluster)) and set(
s[j]).intersection(set(cluster)):
cluster += s[i]
cluster += s[j]
if set(cluster) not in clusters:
clusters.append(set(cluster))

return clusters

def similarity_cosine(vector1, vector2):
‘’‘计算问句与库中问句的相似度,对候选结果加以二次筛选’’’
cos1 = np.sum(vector1vector2)
cos21 = np.sqrt(sum(vector12))
cos22 = np.sqrt(sum(vector2
2))
similarity = cos1/float(cos21
cos22)
if str(similarity) == ‘nan’:
return 0.0
else:
return similarity

def get_wordvector(word):
‘’‘获取单个词的词向量’’’
return np.array(embdding_dict.get(word, [0]*embedding_size))

def load_embedding(embedding_path):
‘’‘加载词向量’’’
embedding_dict = {}
count = 0
for line in open(embedding_path):
line = line.strip().split(’ ‘)
if len(line) < 300:
continue
wd = line[0]
vector = np.array([float(i) for i in line[1:]])
embedding_dict[wd] = vector
count += 1
if count%10000 == 0:
print(count, ‘loaded’)
print(‘loaded %s word embedding, finished’%count)
return embedding_dict
embdding_dict = load_embedding(embedding_path)
def concept_cluster(concept_dict):
‘’‘词的义项聚类’’’
sens_list = []
cluster_sens_dict = {}
for sen1 in concept_dict:
sen1_list = [sen1]
for sen2 in concept_dict:
if sen1 == sen2:
continue
sim_score = similarity_cosine(get_wordvector(sen1),get_wordvector(sen2))
if sim_score>= sim_limit:
sen1_list.append(sen2)
sens_list.append(sen1_list)
sens_clusters = entity_clusters(sens_list)
for sens in sens_clusters:
symbol_sen = list(sens)[0]
cluster_sens_dict[symbol_sen] = concept_dict[symbol_sen]
return cluster_sens_dict

def extract_desc(link):
‘’‘获取该义项的描述信息,作为该义项的意义描述’’’
html = get_html(link)
selector = etree.HTML(html)
keywords = selector.xpath(’//meta[@name=“keywords”]/@content’)
desc = selector.xpath(’//meta[@name=“description”]/@content’)
return desc,keywords

def collect_concepts(wd):
‘’‘多义词主函数’’’
sens_dict = collect_mutilsens(wd)
if not sens_dict:
return {}
concepts_dict = {}
concept_dict = {}
for sen,link in sens_dict.items():
concept = extract_concept(sen)
if concept not in concept_dict:
concept_dict[concept] = [link]
else:
concept_dict[concept].append(link)
# 对抽取的概念进行聚合
cluster_concept_dict = concept_cluster(concept_dict)
for concept,links in cluster_concept_dict.items():
# 获取对应义项的连接页面内容,并进行处理
link = links[0]
desc, keywords = extract_desc(link)
context = ‘’.join(desc+[’ '+keywords])# 将两个内容进行合并,作为其描述
concepts_dict[concept] = context
return concepts_dict
#--------------------句子的语义级别表示----------------------

对义项的描述信息进行关键词提取,作为该义项的一个结构化表示

def extract_keywords(sent):
keywords = [i for i in anse.extract_tags(sent,topK=20,withWeight=False)]# 结巴的关键词提取
return keywords

基于word2vector,通过lookup table的方式找到句子的wordvector的表示

def rep_sentVector(sent):
word_list = extract_keywords(sent)
embedding = np.zeros(embedding_size)
sent_len = 0
for index, wd in enumerate(word_list):
if wd in embdding_dict:
embedding += embdding_dict.get(wd)# 通过求和的方式表示该句子
sent_len += 1
else:
continue
return embedding/sent_len

基于词语相似度,计算句子的相似度

def distance_words(sent1,sent2):
wds1 = extract_keywords(sent1)
wds2 = extract_keywords(sent2)
score_wds1 = []
score_wds2 = []
for word1 in wds1:
score = max([similarity_cosine(get_wordvector(word1),get_wordvector(word2)) for word2 in wds2])
score_wds1.append(score)
for word2 in wds2:
score = max([similarity_cosine(get_wordvector(word2),get_wordvector(word1)) for word1 in wds1])
score_wds2.append(score)
sim_score = max(sum(score_wds1)/len(wds1),sum(score_wds2)/len(wds2))
return sim_score

#-----------------------对该词进行消歧---------------
def detect_main(sent,word):
sent = sent.replace(word,’’)
# 多义词的获取
concept_dict = collect_concepts(word)
# 待消句子的表示
sent_vector = rep_sentVector(sent)
concept_scores_sent = {}
concept_scores_wds = {}
for concept, desc in concept_dict.items():
concept_vector = rep_sentVector(desc)
similarity_sent = similarity_cosine(sent_vector,concept_vector)
concept_scores_sent[concept] = similarity_sent
similarity_wds = distance_words(desc,sent)#另一种计算相似度的方法
concept_scores_wds[concept] = similarity_wds
concept_scores_sent = sorted(concept_scores_sent.items(),key=lambda asd:asd[1],reverse=True)
concept_scores_wds = sorted(concept_scores_wds.items(),key=lambda asd:asd[1],reverse=True)
return concept_scores_wds,concept_scores_sent
`

更多推荐

nlp词义消歧