词义消岐简介

  词义消岐,英文名称为Word Sense Disambiguation,英语缩写为WSD,是自然语言处理(NLP)中一个非常有趣的基本任务。
  那么,什么是词义消岐呢?通常,在我们的自然语言中,不管是英语,还是中文,都有多义词存在。这些多义词的存在,会让人对句子的意思产生混淆,但人通过学习又是可以正确地区分出来的。
  以**“小米”**这个词为例,如果仅仅只是说“小米”这个词语,你并不知道它实际指的到底是小米科技公司还是谷物。但当我们把词语置于某个特定的语境中,我们能很好地区分出这个词语的意思。比如,

雷军是小米的创始人。

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

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

在这个句子中,“小米”指的是谷物、农作物。
  所谓词义消岐,指的是在特定的语境中,识别出某个歧义词的正确含义。
  那么,词义消岐有什么作用呢?词义消岐可以很好地服务于语言翻译和智能问答领域,当然,还有许多应用有待开发~

词义消岐实现

  在目前的词义消岐算法中,有不少原创算法,有些实现起来比较简单,有些想法较为复杂,但实现的效果普遍都不是很好。比较经典的词义消岐的算法为Lesk算法,该算法的想法很简单,通过对某个歧义词构建不同含义的语料及待判别句子中该词语与语料的重合程度来实现,具体的算法原理可参考网址:https://en.wikipedia.org/wiki/Lesk_algorithm .
  在下面的部分中,笔者将会介绍自己想的一种实现词义消岐的算法,仅仅是一个想法,仅供参考。
  我们以词语“火箭”为例,选取其中的两个义项(同一个词语的不同含义):NBA球队名 和 燃气推进装置 ,如下:

获取语料

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

import requests
from bs4 import BeautifulSoup
from 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 = 'https://baike.baidu.com/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 = 'https://baike.baidu.com/item/%E7%81%AB%E7%AE%AD/6308#viewPageContent'
WebScrape('火箭', url).run()

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

火箭技术的飞速发展,不仅可提供更加完善的各类导弹和推动相关科学的发展,还将使开发空间资源、建立空间产业、空间基地及星际航行等成为可能。
火箭技术是一项十分复杂的综合性技术,主要包括火箭推进技术、总体设计技术、火箭结构技术、控制和制导技术、计划管理技术、可靠性和质量控制技术、试验技术,对导弹来说还有弹头制导和控制、
1903年,俄国的К.E.齐奥尔科夫斯基提出了制造大型液体火箭的设想和设计原理。
火箭有很多种,原始的火箭是用引火物附在弓箭头上,然后射到敌人身上引起焚烧的一种箭矢。
“长征三号丙”火箭是在 “长征三号乙”火箭的基础上, 减少了两个助推器并取消了助推器上的尾翼。
火箭与导弹有什么区别
为了能够在未来大规模的将人类送入太空,不可能依赖传统的火箭和飞船。
火箭V2火箭
探测高层大气的物理特征(如气压、温度、湿度等)和现象的探空火箭。
可一次发射一发至数十发火箭弹。

实现算法

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

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

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

import os
import jieba
from 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 = 0
for 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))

输出结果如下:

['赛季', '初', '时候', '众望所归', '西部', '决赛', '球队']
火箭_燃气推进装置:
初, 频数为: 2, TF-IDF值为: 12.49585502688717
火箭_NBA球队名:
赛季, 频数为: 63, TF-IDF值为: 204.6194333469459
初, 频数为: 1, TF-IDF值为: 6.247927513443585
时候, 频数为: 1, TF-IDF值为: 8.055282435501189
西部, 频数为: 16, TF-IDF值为: 80.88451896801904
决赛, 频数为: 7, TF-IDF值为: 33.13348038429679
球队, 频数为: 40, TF-IDF值为: 158.712783770034经过词义消岐,火箭在该句子中的意思为 NBA球队名 .

测试

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

输入句子为:

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

输出结果为:

['三十多年', '前', '战士', '们', '戈壁滩', '白手起家', '建起', '我国', '发射', '基地']
火箭_燃气推进装置:
前, 频数为: 2, TF-IDF值为: 9.063440958888354
们, 频数为: 1, TF-IDF值为: 6.05528243550119
我国, 频数为: 3, TF-IDF值为: 22.410959804340102
发射, 频数为: 89, TF-IDF值为: 253.27878721862933
基地, 频数为: 7, TF-IDF值为: 42.38697704850833
火箭_NBA球队名:
前, 频数为: 3, TF-IDF值为: 13.59516143833253
们, 频数为: 1, TF-IDF值为: 6.05528243550119经过词义消岐,火箭在该句子中的意思为 燃气推进装置 .

输入句子为:

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

输出结果为:

['对于', '马刺', '这样', '级别', '球队', '常规赛', '只有', '屈指可数', '几次', '交锋', '具有', '真正', '意义', '今天', '对', '一役', '其中', '之一']
火箭_燃气推进装置:
只有, 频数为: 1, TF-IDF值为: 7.470319934780034
具有, 频数为: 5, TF-IDF值为: 32.35159967390017
真正, 频数为: 2, TF-IDF值为: 14.940639869560068
意义, 频数为: 1, TF-IDF值为: 8.055282435501189
对, 频数为: 5, TF-IDF值为: 24.03677461028802
其中, 频数为: 3, TF-IDF值为: 21.16584730650357
之一, 频数为: 2, TF-IDF值为: 14.11056487100238
火箭_NBA球队名:
马刺, 频数为: 1, TF-IDF值为: 7.470319934780034
球队, 频数为: 40, TF-IDF值为: 158.712783770034
常规赛, 频数为: 14, TF-IDF值为: 73.4709851882102
只有, 频数为: 1, TF-IDF值为: 7.470319934780034
对, 频数为: 10, TF-IDF值为: 48.07354922057604
之一, 频数为: 1, TF-IDF值为: 7.05528243550119经过词义消岐,火箭在该句子中的意思为 NBA球队名 .

输入句子为:

姚明是火箭队的主要得分手之一。

输出结果为:

['姚明', '火箭队', '主要', '得分手', '之一']
火箭_燃气推进装置:
主要, 频数为: 9, TF-IDF值为: 51.60018906552445
之一, 频数为: 2, TF-IDF值为: 14.11056487100238
火箭_NBA球队名:
姚明, 频数为: 18, TF-IDF值为: 90.99508383902142
火箭队, 频数为: 133, TF-IDF值为: 284.1437533641371
之一, 频数为: 1, TF-IDF值为: 7.05528243550119经过词义消岐,火箭在该句子中的意思为 NBA球队名 .

输入的句子为:

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

输出结果为:

['从', '1992', '年', '开始', '研制', '长征二号', 'F', '型', '中国', '航天史', '技术', '最', '复杂', '、', '可靠性', '和', '安全性', '指标', '最高', '运载火箭']
火箭_燃气推进装置:
从, 频数为: 6, TF-IDF值为: 29.312144604353264
1992, 频数为: 1, TF-IDF值为: 6.733354340613827
年, 频数为: 43, TF-IDF值为: 107.52982410441274
开始, 频数为: 5, TF-IDF值为: 30.27641217750595
研制, 频数为: 25, TF-IDF值为: 110.28565614316162
长征二号, 频数为: 37, TF-IDF值为: 159.11461253349566
F, 频数为: 7, TF-IDF值为: 40.13348038429679
中国, 频数为: 45, TF-IDF值为: 153.51418105769093
技术, 频数为: 27, TF-IDF值为: 119.10850863461454
最, 频数为: 2, TF-IDF值为: 7.614709844115208
、, 频数为: 117, TF-IDF值为: 335.25857156467714
可靠性, 频数为: 5, TF-IDF值为: 30.27641217750595
和, 频数为: 76, TF-IDF值为: 191.22539545388003
安全性, 频数为: 2, TF-IDF值为: 14.940639869560068
运载火箭, 频数为: 95, TF-IDF值为: 256.28439093389505
火箭_NBA球队名:
从, 频数为: 5, TF-IDF值为: 24.42678717029439
1992, 频数为: 2, TF-IDF值为: 13.466708681227654
年, 频数为: 52, TF-IDF值为: 130.0360663588247
开始, 频数为: 2, TF-IDF值为: 12.11056487100238
中国, 频数为: 4, TF-IDF值为: 13.64570498290586
最, 频数为: 3, TF-IDF值为: 11.422064766172813
、, 频数为: 16, TF-IDF值为: 45.847326025938756
和, 频数为: 31, TF-IDF值为: 77.99983235618791
最高, 频数为: 8, TF-IDF值为: 59.76255947824027经过词义消岐,火箭在该句子中的意思为 燃气推进装置 .

输入句子为:

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

输出结果为:

['到', '目前为止', '已经', '休斯顿', '进行', '电视', '宣传', '并', '大街小巷', '竖起', '广告栏']
火箭_燃气推进装置:
到, 频数为: 11, TF-IDF值为: 39.19772273088667
已经, 频数为: 2, TF-IDF值为: 13.466708681227654
进行, 频数为: 14, TF-IDF值为: 68.39500407682429
并, 频数为: 11, TF-IDF值为: 49.17351928258037
火箭_NBA球队名:
到, 频数为: 6, TF-IDF值为: 21.38057603502909
已经, 频数为: 2, TF-IDF值为: 13.466708681227654
休斯顿, 频数为: 2, TF-IDF值为: 14.940639869560068
进行, 频数为: 2, TF-IDF值为: 9.770714868117755
并, 频数为: 5, TF-IDF值为: 22.351599673900168经过词义消岐,火箭在该句子中的意思为 燃气推进装置 .

总结

  对于笔者的这个算法,虽然有一定的效果,但是也不总是识别正确。比如,对于最后一个测试的句子,识别的结果就是错误的,其实“休斯顿”才是识别该词语义项的关键词,但很遗憾,在笔者的算法中,“休斯顿”的权重并不高。
  对于词义消岐算法,如果还是笔者的这个思路,那么有以下几方面需要改进:

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

  笔者的这篇文章仅作为词义消岐的简介以及简单实现,希望能对读者有所启发~

注意:本人现已开通微信公众号: Python爬虫与算法(微信号为:easy_web_scrape), 欢迎大家关注哦~~

NLP入门(九)词义消岐(WSD)的简介与实现相关推荐

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

    词义消岐简介 词义消岐,英文名称为Word Sense Disambiguation,英语缩写为WSD,是自然语言处理(NLP)中一个非常有趣的基本任务. 那么,什么是词义消岐呢?通常,在我们的自然语 ...

  2. NLP中词义消岐(WSD)的简介与实现

    文/jclian  图片来源于网络 词义消岐简介   词义消岐,英文名称为Word Sense Disambiguation,英语缩写为WSD,是自然语言处理(NLP)中一个非常有趣的基本任务.    ...

  3. cips2016+学习笔记︱NLP中的消岐方法总结(词典、有监督、半监督)

    歧义问题方面,笔者一直比较关注利用词向量解决歧义问题: 也许你寄希望于一个词向量能捕获所有的语义信息(例如run即是动车也是名词),但是什么样的词向量都不能很好地进行凸显. 这篇论文有一些利用词向量的 ...

  4. 【自然语言处理】汉语词义自动消岐系统

    一. 题目选择 [汉语词义自动消歧系统] 词义消岐,英文名称为 Word Sense Disambiguation,英语缩写为 WSD,其任务是根据歧义词语的语义环境确定其在该使用环境中的语义. 很多 ...

  5. 自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧

    自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧 NLP中进行词义消歧的一个非常方便且简单的方法就是训练词向量,通过词向量计算余弦值,来推断某个词在句子中的含义.python中的 ...

  6. NLP入门学习1——分词和词性标注

    NLP入门学习1--分词和词性标注 0.简介 1.概念和工具 1.1 词性标注 1.2 NLTK 1.3 jieba 1.4 LAC 2.代码实现 2.1 分词 2.1.1 使用nltk进行分词: 2 ...

  7. NLP 迷思之四:词义消歧(WSD)是NLP应用的瓶颈

    本文转载自http://blog.sciencenet.cn/blog-362400-526304.html 引用老友: 受教了.谢谢立委. 我同意"成语从来不是问题".成问题的应 ...

  8. 【NLP入门教程】七、词义消歧

    词义消歧(Word Sense Disambiguation, WSD)其目标是确定文本中词汇的正确含义.由于许多单词具有多种含义,词义消歧对于理解和分析文本具有关键作用. 1. 词义消歧的挑战 词义 ...

  9. NLP入门之综述阅读-自然语言处理发展及应用综述

    NLP入门-综述阅读-[自然语言处理发展及应用综述] 1 前言 2 自然语言处理的发展 3 自然语言处理的研究方法和内容 3.1 自然语言处理的研究方法 3.2 自然语言处理基础研究 3.2.1 词法 ...

最新文章

  1. NO.7 今天我们是实用派,看看业务选择和部署以及常用故障解决方案是怎么做的...
  2. 在html利用canvas蚂蚁,html5 利用canvas实现简单的人物走动
  3. Python之pandas:将dataframe数据写入到xls表格的多个sheet内(防止写入数据循环覆盖sheet表)
  4. HDOJ 2176 取石子游戏
  5. 教你正确把加减乘除运用在MySQL里面
  6. 排名如何得到快速提升?
  7. Pannellum:实例之通过按钮控制全景图
  8. 删除AdminServer logs下的log文件后开启AdminServer报错
  9. lmdb高效存储图片数据
  10. 如何升级iOS 16正式版?iOS 16正式版一键刷机教程
  11. 安装Hadoop3.2.1(很多坑)
  12. 【python】必备小知识——解决google chrome无法更新(错误代码为:7:0x80040902:60)
  13. POG个体成长模型:痛苦是成长的起点
  14. python学习的一些总结
  15. alios things开发板_AliOS Things这个操作系统怎么样?
  16. 音响的灵魂! 世界顶级扬声器品牌介绍
  17. 抖音商城店铺分享链接自动化
  18. 有利润表模板的BI软件有哪些?
  19. ecplise配置tomcat
  20. N1文件服务器,n1盒子搭建ftp服务器

热门文章

  1. 为什么决战平安京显示服务器连接失败,决战!平安京总是显示无法连接网络
  2. 一文看懂数据清洗:缺失值、异常值和重复值的处理
  3. Android开发——手把手写APP(四)——数独游戏编写(七)——总结
  4. 浅析 VSCode 代码高亮实现原理
  5. 射手座和什么星座最配
  6. 易云智能养殖监控系统,您身边的物联网智能管家
  7. 零售业的商品交叉价格弹性
  8. 安徽省计算机java二级,[2018年计算机二级考试《JAVA》章节练习题]安徽省计算机二级考试报名时间...
  9. 安卓APP发布上架的方法
  10. 使用 FasterTransformer 和 Triton 推理服务器部署 GPT-J 和 T5