1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 自然语言处理(NLP)之词义消歧(WSD)的简介与实现

自然语言处理(NLP)之词义消歧(WSD)的简介与实现

时间:2019-10-13 11:38:28

相关推荐

自然语言处理(NLP)之词义消歧(WSD)的简介与实现

词义消岐简介

词义消岐,英文名称为Word Sense Disambiguation,英语缩写为WSD,是自然语言处理(NLP)中一个非常有趣的基本任务。

那么,什么是词义消岐呢?通常,在我们的自然语言中,不管是英语,还是中文,都有多义词存在。这些多义词的存在,会让人对句子的意思产生混淆,但人通过学习又是可以正确地区分出来的。

以**“小米”**这个词为例,如果仅仅只是说“小米”这个词语,你并不知道它实际指的到底是小米科技公司还是谷物。但当我们把词语置于某个特定的语境中,我们能很好地区分出这个词语的意思。比如,

雷军是小米的创始人。

在这个句子中,我们知道这个“小米”指的是小米科技公司。比如

我今天早上喝了一碗小米粥。

在这个句子中,“小米”指的是谷物、农作物。

所谓词义消岐,指的是在特定的语境中,识别出某个歧义词的正确含义。

那么,词义消岐有什么作用呢?词义消岐可以很好地服务于语言翻译和智能问答领域,当然,还有许多应用有待开发~

词义消岐实现

比较经典的词义消岐的算法为Lesk算法,该算法的想法很简单,通过对某个歧义词构建不同含义的语料及待判别句子中该词语与语料的重合程度来实现

我们以词语“火箭”为例,选取其中的两个义项(同一个词语的不同含义):NBA球队名和燃气推进装置,如下:

获取语料

首先,我们利用爬虫爬取这两个义项的百度百科网页,以句子为单位,只要句子中出现该词语,则把这句话加入到这个义项的预料中。爬虫的完整Python代码如下:

import requestsfrom bs4 import BeautifulSoupfrom pyltp import SentenceSplitterclass WebScrape(object):def __init__(self, word, url):self.url = urlself.word = word# 爬取百度百科页面def web_parse(self):headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 \(KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}req = requests.get(url=self.url, headers=headers)# 解析网页,定位到main-content部分if req.status_code == 200:soup = BeautifulSoup(req.text.encode(req.encoding), 'lxml')return soupreturn None# 获取该词语的义项def get_gloss(self):soup = self.web_parse()if soup:lis = soup.find('ul', class_="polysemantList-wrapper cmn-clearfix")if lis:for li in lis('li'):if '<a' not in str(li):gloss = li.text.replace('▪', '')return glossreturn None# 获取该义项的语料,以句子为单位def get_content(self):# 发送HTTP请求result = []soup = self.web_parse()if soup:paras = soup.find('div', class_='main-content').text.split('\n')for para in paras:if self.word in para:sents = list(SentenceSplitter.split(para))for sent in sents:if self.word in sent:sent = sent.replace('\xa0', '').replace('\u3000', '')result.append(sent)result = list(set(result))return result# 将该义项的语料写入到txtdef write_2_file(self):gloss = self.get_gloss()result = self.get_content()print(gloss)print(result)if result and gloss:with open('./%s_%s.txt' % (self.word, gloss), 'w', encoding='utf-8') as f:f.writelines([_ + '\n' for _ in result])def run(self):self.write_2_file()# NBA球队名# url = '/item/%E4%BC%91%E6%96%AF%E6%95%A6%E7%81%AB%E7%AE%AD%E9%98%9F/370758?fromtitle=%E7%81%AB%E7%AE%AD&fromid=8794081#viewPageContent'# 燃气推进装置url = '/item/%E7%81%AB%E7%AE%AD/6308#viewPageContent'WebScrape('火箭', url).run()

运行结果:

利用这个爬虫,我们爬取了“火箭”这个词语的两个义项的语料,生成了火箭_燃气推进装置.txt文件和火箭_NBA球队名.txt文件,这两个文件分别含有275和190个句子。以火箭_燃气推进装置.txt文件为例,前10个句子如下:

火箭主要分类火箭美国大力神系列运载火箭大力神4火箭于1985年开始研制,在1986年挑战者号航天飞机失事之后,成为发射大型军用卫星的主要运载火箭,承担美国空军地球同步轨道卫星(预警、通信、中继、气象)和近地轨道侦察卫星的发射任务。其目标是在海南建成探空火箭探测和地面联合监测大气和电离层参数的综合探测系统。揭秘长三甲系列:“金牌火箭”是这样炼成的固体火箭的动力装置系统较为简单,它的主要部分就是固体火箭发动机,推进剂直接装在发动机的燃烧室壳体内。火箭按动力能源1965年起开始研制固体探空火箭“和平”2号和6号。作为新能源火箭的代表,核能火箭的优点是其发动机比冲比化学能火箭的高,而推进剂只有一种,简化了火箭结构,适合执行长时间任务或星际任务。中国在1958年以前曾发射过试验性火箭,1958年正式研制探空火箭,先后研制成T-7液体探空火箭和改进型 T-7A探空火箭。

实现算法

我们以句子为单位进行词义消岐,即输入一句话,识别出该句子中某个歧义词的含义。这儿使用的算法比较简单,是以TF-IDF为权重的频数判别。以句子

赛季初的时候,火箭是众望所归的西部决赛球队。

为例,对该句子分词后,去掉停用词(stopwords),然后分别统计除了“火箭”这个词以外的TF-IDF值,累加起来,比较在两个义项下这个值的大小即可。

实现这个算法的完整Python代码如下:

import osimport jiebafrom math import log2# 读取每个义项的语料def read_file(path):with open(path, 'r', encoding='utf-8') as f:lines = [_.strip() for _ in f.readlines()]return lines# 对示例句子分词sent = '赛季初的时候,火箭是众望所归的西部决赛球队。'wsd_word = '火箭'jieba.add_word(wsd_word)sent_words = list(jieba.cut(sent, cut_all=False))# 去掉停用词stopwords = [wsd_word, '我', '你', '它', '他', '她', '了', '是', '的', '啊', '谁', '什么', '都', \'很', '个', '之', '人', '在', '上', '下', '左', '右', '。', ',', '!', '?']sent_cut = []for word in sent_words:if word not in stopwords:sent_cut.append(word)print(sent_cut)# 计算其他词的TF-IDF以及频数wsd_dict = {}for file in os.listdir('.'):if wsd_word in file:wsd_dict[file.replace('.txt', '')] = read_file(file)# 统计每个词语在语料中出现的次数tf_dict = {}for meaning, sents in wsd_dict.items():tf_dict[meaning] = []for word in sent_cut:word_count = 0for sent in sents:example = list(jieba.cut(sent, cut_all=False))word_count += example.count(word)if word_count:tf_dict[meaning].append((word, word_count))idf_dict = {}for word in sent_cut:document_count = 0for meaning, sents in wsd_dict.items():for sent in sents:if word in sent:document_count += 1idf_dict[word] = document_count# 输出值total_document = 0for meaning, sents in wsd_dict.items():total_document += len(sents)# 计算tf_idf值mean_tf_idf = []for k, v in tf_dict.items():print(k + ':')tf_idf_sum = 0for item in v:word = item[0]tf = item[1]tf_idf = item[1] * log2(total_document / (1 + idf_dict[word]))tf_idf_sum += tf_idfprint('%s, 频数为: %s, TF-IDF值为: %s' % (word, tf, tf_idf))mean_tf_idf.append((k, tf_idf_sum))sort_array = sorted(mean_tf_idf, key=lambda x: x[1], reverse=True)true_meaning = sort_array[0][0].split('_')[1]print('\n经过词义消岐,%s在该句子中的意思为 %s .' % (wsd_word, true_meaning))

运行结果:

['赛季', '初', '时候', '众望所归', '西部', '决赛', '球队']火箭_NBA球队名:赛季, 频数为: 61, TF-IDF值为: 187.86335874071477初, 频数为: 1, TF-IDF值为: 5.861086905995394时候, 频数为: 1, TF-IDF值为: 7.861086905995394西部, 频数为: 19, TF-IDF值为: 89.13207618650854决赛, 频数为: 8, TF-IDF值为: 35.21324229886477球队, 频数为: 43, TF-IDF值为: 155.36585387972775火箭_燃气推进装置:初, 频数为: 3, TF-IDF值为: 17.58326071798618经过词义消岐,火箭在该句子中的意思为 NBA球队名 .

测试

接着,我们对上面的算法和程序进行更多的测试。

输入句子为:

三十多年前,战士们在戈壁滩白手起家,建起了我国的火箭发射基地。

输出结果为:

['三十多年', '前', '战士', '们', '戈壁滩', '白手起家', '建起', '我国', '发射', '基地']火箭_NBA球队名:前, 频数为: 3, TF-IDF值为: 10.617476433324095们, 频数为: 1, TF-IDF值为: 6.539158811108031火箭_燃气推进装置:前, 频数为: 9, TF-IDF值为: 31.852429299972282我国, 频数为: 5, TF-IDF值为: 31.38062202637119发射, 频数为: 110, TF-IDF值为: 257.1277444932219经过词义消岐,火箭在该句子中的意思为 燃气推进装置 .

输入句子为:

对于马刺这样级别的球队,常规赛只有屈指可数的几次交锋具有真正的意义,今天对火箭一役是其中之一。

输出结果为:

['对于', '马刺', '这样', '级别', '球队', '常规赛', '只有', '屈指可数', '几次', '交锋', '具有', '真正', '意义', '今天', '对', '一役', '其中', '之一']火箭_NBA球队名:对于, 频数为: 1, TF-IDF值为: 7.2761244052742375球队, 频数为: 43, TF-IDF值为: 155.36585387972775常规赛, 频数为: 14, TF-IDF值为: 70.75224777512906只有, 频数为: 1, TF-IDF值为: 6.861086905995394对, 频数为: 12, TF-IDF值为: 47.450355724642506之一, 频数为: 1, TF-IDF值为: 6.539158811108031火箭_燃气推进装置:对于, 频数为: 1, TF-IDF值为: 7.2761244052742375这样, 频数为: 1, TF-IDF值为: 7.861086905995394只有, 频数为: 2, TF-IDF值为: 13.722173811990787具有, 频数为: 3, TF-IDF值为: 20.58326071798618真正, 频数为: 1, TF-IDF值为: 7.861086905995394意义, 频数为: 1, TF-IDF值为: 7.861086905995394对, 频数为: 13, TF-IDF值为: 51.40455203502938其中, 频数为: 5, TF-IDF值为: 31.38062202637119之一, 频数为: 3, TF-IDF值为: 19.617476433324093经过词义消岐,火箭在该句子中的意思为 NBA球队名 .

输入的句子为:

从1992年开始研制的长征二号F型火箭,是中国航天史上技术最复杂、可靠性和安全性指标最高的运载火箭。

输出结果为:

['从', '1992', '年', '开始', '研制', '长征二号', 'F', '型', '中国', '航天史', '技术', '最', '复杂', '、', '可靠性', '和', '安全性', '指标', '最高', '运载火箭']火箭_NBA球队名:从, 频数为: 6, TF-IDF值为: 23.441343573651111992, 频数为: 2, TF-IDF值为: 13.078317622216062年, 频数为: 64, TF-IDF值为: 150.61070501098862开始, 频数为: 2, TF-IDF值为: 9.078317622216062中国, 频数为: 11, TF-IDF值为: 39.74475331806989最, 频数为: 2, TF-IDF值为: 6.937538966433267、, 频数为: 25, TF-IDF值为: 62.15118686621173和, 频数为: 31, TF-IDF值为: 64.47154296659276最高, 频数为: 8, TF-IDF值为: 52.31327048886425火箭_燃气推进装置:从, 频数为: 24, TF-IDF值为: 93.765374294604441992, 频数为: 1, TF-IDF值为: 6.539158811108031年, 频数为: 44, TF-IDF值为: 103.54485969505468开始, 频数为: 17, TF-IDF值为: 77.16569978883652研制, 频数为: 24, TF-IDF值为: 102.6269857265817型, 频数为: 13, TF-IDF值为: 48.51345055765555中国, 频数为: 23, TF-IDF值为: 83.10266602869159技术, 频数为: 20, TF-IDF值为: 88.03310574716193最, 频数为: 3, TF-IDF值为: 10.4063084496499复杂, 频数为: 3, TF-IDF值为: 20.58326071798618、, 频数为: 149, TF-IDF值为: 370.4210737226219可靠性, 频数为: 2, TF-IDF值为: 14.552248810548475和, 频数为: 97, TF-IDF值为: 201.73353766966122最高, 频数为: 1, TF-IDF值为: 6.539158811108031运载火箭, 频数为: 111, TF-IDF值为: 257.7340185324972经过词义消岐,火箭在该句子中的意思为 燃气推进装置 .

输入句子为:

到目前为止火箭已经在休斯顿进行了电视宣传,并在大街小巷竖起广告栏。

输出结果为:

['到', '目前为止', '已经', '休斯顿', '进行', '电视', '宣传', '并', '大街小巷', '竖起', '广告栏']火箭_NBA球队名:到, 频数为: 3, TF-IDF值为: 10.012574849815142已经, 频数为: 1, TF-IDF值为: 7.2761244052742375休斯顿, 频数为: 9, TF-IDF值为: 51.220457140977736进行, 频数为: 2, TF-IDF值为: 8.321294375708604并, 频数为: 6, TF-IDF值为: 24.01863546520693火箭_燃气推进装置:到, 频数为: 17, TF-IDF值为: 56.73792414895247已经, 频数为: 1, TF-IDF值为: 7.2761244052742375进行, 频数为: 28, TF-IDF值为: 116.49812125992045并, 频数为: 18, TF-IDF值为: 72.0559063956208经过词义消岐,火箭在该句子中的意思为 燃气推进装置 .

总结:

这个算法,虽然有一定的效果,但是也不总是识别正确。比如,对于最后一个测试的句子,识别的结果就是错误的,其实“休斯顿”才是识别该词语义项的关键词,但很遗憾,在笔者的算法中,“休斯顿”的权重并不高。

对于词义消岐算法,如果还是用这个思路,那么有以下几方面需要改进:

语料大小及丰富程度;停用词的扩充;更好的算法。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。