- 为什么要自然语言的分布式表示
- 为了让计算机能够理解文字(数字很好理解,因为计算机本身就可以直接将数字输入进去,并且每个数字的含义可以直接通过数字本身来表示,而文字计算机无法直接理解)
- 什么叫分布式表示
- 即将自然语言向量化,称为分布式表示
- 本笔记对应的视频链接:
1同义词词典
- 想让计算机理解自然语言,就必须要让他理解每一个单词的含义是什么。 最朴素的方法就是词典的方法,就像我们在学习汉字的时候会拥有一本词典,但遇到不会的不认识的单词的时候,我们去查这个词典里面给我们的解释。 那么在这样语言处理方面的话,就是同义词词典。
1.1同义词词典的构成
-
同义词词典的构成:
-
由于不同的单词可以表示相同或者相近的含义,因此在同义词词典中,我们将相同含义或者相近含义的单词归到一个组, 我们用一些标识符来标识每一个组,这样只要在同一个组内,他们都是表示相同或者相近的含义
-
比如下图中,这些单词都是可以表示汽车,他们是同义词
-
目前为止,我们只是把相同的词归到了同一个组,他们之间不具有层次关系,只是表示他们的含义相近或者相同
-
1.2单词网络
-
单词网络
-
在自然语言中,我们有上位词、下位词的概念,以及整体和部分的关系, 单词网络就是用来描述这种层次关系的
-
例如,下图中汽车只是机动车的一种,卡车也是一种机动车,所以机动车是汽车的上位词,即机动车代表着更加广泛的一个概念; 同理汽车也包含很多种,比如说小轿车SUV等等;这就构成了具有层次关系的单词网络,如下图所示
-
上图只是描述了机动车这一个简单概念, 因此他看起来像是一个树结构, 如果将所有的概念都放在一起构成一个单词网络,他将演化成一个图结构
-
基于这样的一个图结构,我们可以利用图的相关理论知识让计算机能够理解不同单词之间的联系以及相关程度(例如计算不同节点之间的路径长度)
-
1.3同义词词典之WordNet
- 使用
WordNet
需要使用nltk
包nltk
是一个自然语言处理工具包, 里面封装了一些方法,可以用来进行词性标注、句法分析等自然语言处理任务;- 详见:
nlp/word_net.py
1.3.1环境准备
-
创建一个虚拟环境,以便与其他的环境相分隔,不影响其他的项目
-
conda create -n nlp_1 pip python=3.8
-
安装nltk包
-
pip install nltk
1.3.2查看同义词
涉及的语句为:
from nltk.corpus import wordnet print(wordnet.synsets('car')) # 查看某个单词的同义词簇 print(wordnet.synset('car.n.01'))
-
初次运行
wordnet.synsets()
语句的时候,会报下图所示的错误。这是因为我们使用的是一个同义词词典,但是目前这个同义词词典还没有被下载到本地电脑。 -
因此按照错误提示,我们进入到命令行。执行错误提示中的代码,把这个同义词词典先下载下来。
-
然后执行
print(wordnet.synsets('car'))
语句就不会报错了;下图就是从同义词词典中返回的与car
这个单词相同或者相近的同义词组。- 返回的结果是一个列表,列表中包含五个元素
- 由于一个单词可能有多个含义,因此在返回的结果当中,每个元素都代表着一个含义所对应的那个组别。组别的名称称之为标题词;例如第一个元素表示car作为名词的第01个含义,这个组别的标题词为car.n.01;以此类推;
-
在自然语言处理这本书中,也给出了标题词的每个部分的含义:
-
在调用函数时,我们发现除了上面这个函数以外,还有一个函数名:
wordnet.synset()
;它们的区别如下图所示: -
因此,结合上面返回的标题词列表,我们就可以使用
wordnet.synset()
来查看具体的某一个标题词对应的单词的具体含义;这里可以使用封装好的definition
函数:-
car=wordnet.synset('car.n.01') # Synset 对象 print(car.definition())
-
-
查看某个同义词簇中包含的具体单词有哪些
-
print(car.lemma_names())
-
1.3.3查看单词网络
-
使用
Synset
对象的hypernym_paths()
方法来获取当前单词的上位词路径:-
print(car.hypernym_paths()[0])
-
这个函数
hypernym_paths()
返回一个列表,列表中的每个元素也是一个列表,表示一种上位词路径;由于单词网络是错综复杂的,因此这个函数的返回值有多个。 -
car.n.01
这个同义词簇的第一个上位词路径如下图所示(注意:路径是从最上位的单词出发,到当前词):
-
1.3.4计算单词之间的相似度
-
使用
Synset
对象的path_similarity()方法计算不同的同义词簇之间的相似度,该函数的参数如下:- 注意传入的是另一个同义词簇的
Synset
对象,而不是标题词字符串
- 注意传入的是另一个同义词簇的
-
分别计算car.n.01和dog.n.01、car.n.02的相似度:
-
dog=wordnet.synset('dog.n.01') print(car.path_similarity(dog)) car2=wordnet.synset('car.n.02') print('car.path_similarity(car2):',car.path_similarity(car2))
-
-
可以看到,car与dog的相似度很低,而与
car.n.02
的相似度较高,因为毕竟car.n.01
和car.n.02
都是可以通过wordnet.synsets('car')
查询到,说明他们的含义是相近的; -
书上简单介绍了这个相似度函数的计算原理,即两个同义词簇所在的上位词的路径,公共的部分越多,就越相似。
1.4 同义词词典的缺点
- 新词不断出现,语言的含义也会随着时间的变化而变化; 在使用同义词词典的过程当中,我们也知道在使用之前我们需要先把同义词词典下载到本地,这意味着我们需要事先构建好同义词词典,那么当新词或者词的含义发生变化时,我们需要人为的去维护这个同义词词典,这个维护成本是非常高的;
- 同义词词典只是单纯的将含义相同或者相近的单词分到一个组, 但是即使在同一个组,不同的单词可能用法不一样,在含义上可能也有细微的差别, 仅使用同义词词典,无法让计算机理解这些细微的差别。