本文作为笔者NLP入门系列文章第一篇,以后我们就要步入NLP时代。

  本文将会介绍NLP中常见的词袋模型(Bag of Words)以及如何利用词袋模型来计算句子间的相似度(余弦相似度,cosine similarity)。

  首先,让我们来看一下,什么是词袋模型。我们以下面两个简单句子为例:

sent1 = "I love sky, I love sea."
sent2 = "I like running, I love reading."

  通常,NLP无法一下子处理完整的段落或句子,因此,第一步往往是分句和分词。这里只有句子,因此我们只需要分词即可。对于英语句子,可以使用NLTK中的word_tokenize函数,对于中文句子,则可使用jieba模块。故第一步为分词,代码如下:

from nltk import word_tokenize
sents = [sent1, sent2]
texts = [[word for word in word_tokenize(sent)] for sent in sents]

输出的结果如下:

[['I', 'love', 'sky', ',', 'I', 'love', 'sea', '.'], ['I', 'like', 'running', ',', 'I', 'love', 'reading', '.']]

  分词完毕。下一步是构建语料库,即所有句子中出现的单词及标点。代码如下:

all_list = []
for text in texts:
all_list += text
corpus = set(all_list)
print(corpus)

输出如下:

{'love', 'running', 'reading', 'sky', '.', 'I', 'like', 'sea', ','}

  可以看到,语料库中一共是8个单词及标点。接下来,对语料库中的单词及标点建立数字映射,便于后续的句子的向量表示。代码如下:

corpus_dict = dict(zip(corpus, range(len(corpus))))
print(corpus_dict)

输出如下:

{'running': 1, 'reading': 2, 'love': 0, 'sky': 3, '.': 4, 'I': 5, 'like': 6, 'sea': 7, ',': 8}

  虽然单词及标点并没有按照它们出现的顺序来建立数字映射,不过这并不会影响句子的向量表示及后续的句子间的相似度。

  下一步,也就是词袋模型的关键一步,就是建立句子的向量表示。这个表示向量并不是简单地以单词或标点出现与否来选择0,1数字,而是把单词或标点的出现频数作为其对应的数字表示,结合刚才的语料库字典,句子的向量表示的代码如下:

# 建立句子的向量表示
def vector_rep(text, corpus_dict):
vec = []
for key in corpus_dict.keys():
if key in text:
vec.append((corpus_dict[key], text.count(key)))
else:
vec.append((corpus_dict[key], 0)) vec = sorted(vec, key= lambda x: x[0]) return vec vec1 = vector_rep(texts[0], corpus_dict)
vec2 = vector_rep(texts[1], corpus_dict)
print(vec1)
print(vec2)

输出如下:

[(0, 2), (1, 0), (2, 0), (3, 1), (4, 1), (5, 2), (6, 0), (7, 1), (8, 1)]
[(0, 1), (1, 1), (2, 1), (3, 0), (4, 1), (5, 2), (6, 1), (7, 0), (8, 1)]

让我们稍微逗留一会儿,来看看这个向量。在第一句中I出现了两次,在预料库字典中,I对应的数字为5,因此在第一句中5出现2次,在列表中的元组即为(5,2),代表单词I在第一句中出现了2次。以上的输出可能并不那么直观,真实的两个句子的代表向量应为:

[2, 0, 0, 1, 1, 2, 0, 1, 1]
[1, 1, 1, 0, 1, 2, 1, 0, 1]

  OK,词袋模型到此结束。接下来,我们会利用刚才得到的词袋模型,即两个句子的向量表示,来计算相似度。

  在NLP中,如果得到了两个句子的向量表示,那么,一般会选择用余弦相似度作为它们的相似度,而向量的余弦相似度即为两个向量的夹角的余弦值。其计算的Python代码如下:

from math import sqrt
def similarity_with_2_sents(vec1, vec2):
inner_product = 0
square_length_vec1 = 0
square_length_vec2 = 0
for tup1, tup2 in zip(vec1, vec2):
inner_product += tup1[1]*tup2[1]
square_length_vec1 += tup1[1]**2
square_length_vec2 += tup2[1]**2 return (inner_product/sqrt(square_length_vec1*square_length_vec2)) cosine_sim = similarity_with_2_sents(vec1, vec2)
print('两个句子的余弦相似度为: %.4f。'%cosine_sim)

输出结果如下:

两个句子的余弦相似度为: 0.7303。

  这样,我们就通过句子的词袋模型,得到了它们间的句子相似度。

  当然,在实际的NLP项目中,如果需要计算两个句子的相似度,我们只需调用gensim模块即可,它是NLP的利器,能够帮助我们处理很多NLP任务。下面为用gensim计算两个句子的相似度的代码:

sent1 = "I love sky, I love sea."
sent2 = "I like running, I love reading." from nltk import word_tokenize
sents = [sent1, sent2]
texts = [[word for word in word_tokenize(sent)] for sent in sents]
print(texts) from gensim import corpora
from gensim.similarities import Similarity # 语料库
dictionary = corpora.Dictionary(texts) # 利用doc2bow作为词袋模型
corpus = [dictionary.doc2bow(text) for text in texts]
similarity = Similarity('-Similarity-index', corpus, num_features=len(dictionary))
print(similarity)
# 获取句子的相似度
new_sensence = sent1
test_corpus_1 = dictionary.doc2bow(word_tokenize(new_sensence)) cosine_sim = similarity[test_corpus_1][1]
print("利用gensim计算得到两个句子的相似度: %.4f。"%cosine_sim)

输出结果如下:

[['I', 'love', 'sky', ',', 'I', 'love', 'sea', '.'], ['I', 'like', 'running', ',', 'I', 'love', 'reading', '.']]
Similarity index with 2 documents in 0 shards (stored under -Similarity-index)
利用gensim计算得到两个句子的相似度: 0.7303。

注意,如果在运行代码时出现以下warning:

gensim\utils.py:1209: UserWarning: detected Windows; aliasing chunkize to chunkize_serial
warnings.warn("detected Windows; aliasing chunkize to chunkize_serial") gensim\matutils.py:737: FutureWarning: Conversion of the second argument of issubdtype from `int` to `np.signedinteger` is deprecated. In future, it will be treated as `np.int32 == np.dtype(int).type`.
if np.issubdtype(vec.dtype, np.int):

如果想要去掉这些warning,则在导入gensim模块的代码前添加以下代码即可:

import warnings
warnings.filterwarnings(action='ignore',category=UserWarning,module='gensim')
warnings.filterwarnings(action='ignore',category=FutureWarning,module='gensim')

  本文到此结束,感谢阅读!如果不当之处,请速联系笔者,欢迎大家交流!祝您好运~

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

NLP入门(一)词袋模型及句子相似度的更多相关文章

  1. 文本向量化及词袋模型 - NLP学习(3-1)

    分词(Tokenization) - NLP学习(1) N-grams模型.停顿词(stopwords)和标准化处理 - NLP学习(2)   之前我们都了解了如何对文本进行处理:(1)如用NLTK文 ...

  2. R+NLP︱text2vec包——BOW词袋模型做监督式情感标注案例(二,情感标注)

    要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 在之前的开篇提到了text2vec ...

  3. NLP基础——词集模型(SOW)和词袋模型(BOW)

    (1)词集模型(Set Of Words): 单词构成的集合,集合自然每个元素都只有一个,也即词集中的每个单词都只有一个. (2)词袋模型(Bag Of Words): 如果一个单词在文档中出现不止一 ...

  4. 机器学习入门-文本数据-构造Tf-idf词袋模型(词频和逆文档频率) 1.TfidfVectorizer(构造tf-idf词袋模型)

    TF-idf模型:TF表示的是词频:即这个词在一篇文档中出现的频率 idf表示的是逆文档频率, 即log(文档的个数/1+出现该词的文档个数)  可以看出出现该词的文档个数越小,表示这个词越稀有,在这 ...

  5. 机器学习入门-文本数据-构造Ngram词袋模型 1.CountVectorizer(ngram_range) 构建Ngram词袋模型

    函数说明: 1 CountVectorizer(ngram_range=(2, 2)) 进行字符串的前后组合,构造出新的词袋标签 参数说明:ngram_range=(2, 2) 表示选用2个词进行前后 ...

  6. 机器学习入门-文本数据-构造词频词袋模型 1.re.sub(进行字符串的替换) 2.nltk.corpus.stopwords.words(获得停用词表) 3.nltk.WordPunctTokenizer(对字符串进行分词操作) 4.np.vectorize(对函数进行向量化) 5. CountVectorizer(构建词频的词袋模型)

    函数说明: 1. re.sub(r'[^a-zA-Z0-9\s]', repl='', sting=string)  用于进行字符串的替换,这里我们用来去除标点符号 参数说明:r'[^a-zA-Z0- ...

  7. 阿里天池 NLP 入门赛 TextCNN 方案代码详细注释和流程讲解

    thumbnail: https://image.zhangxiann.com/jung-ho-park-HbnqEhMBpPM-unsplash.jpg toc: true date: 2020/8 ...

  8. 文本离散表示(一):词袋模型(bag of words)

    一.文本表示 文本表示的意思是把字词处理成向量或矩阵,以便计算机能进行处理.文本表示是自然语言处理的开始环节. 文本表示按照细粒度划分,一般可分为字级别.词语级别和句子级别的文本表示.字级别(char ...

  9. 机器学习---文本特征提取之词袋模型(Machine Learning Text Feature Extraction Bag of Words)

    假设有一段文本:"I have a cat, his name is Huzihu. Huzihu is really cute and friendly. We are good frie ...

随机推荐

  1. python 导入模块出错 ImportError: No module named 'request'

    运行程序时报错 ImportError: No module named 'request' 1,第一种情况是真的没有安装requests这个模块,使用 sudo pip install reques ...

  2. 小白看过来runtinme

    RunTime 概述 RunTime消息机制 RunTime交换方法 RunTime消息转发 RunTime关联对象 RunTime实现字典与模型互转 1.RunTime 概述 我们在面试的时候,经常 ...

  3. 【渗透攻防】千变万化的WebShell

    前言WebShell就是以asp.php.jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门.本篇文章将带大家学习如何获取WebShell,如何隐藏WebShell,有 ...

  4. Java面试题精选,大型网站系统架构你不得不懂的10个问题

    作者:JavaGuide(公众号) 下面这些问题都是一线大厂的真实面试问题,不论是对你面试还是说拓宽知识面都很有帮助.之前发过一篇8 张图读懂大型网站技术架构 可以作为不太了解大型网站系统技术架构朋友 ...

  5. OAuth2简易实战(二)-模拟客户端调用

    1. OAuth2简易实战(二) 1.1. 目标 模拟客户端获取第三方授权,并调用第三方接口 1.2. 代码 1.2.1. 核心流程 逻辑就是从数据库读取用户信息,封装成UserDetails对象,该 ...

  6. CentOS随笔——关机命令

    关机重启命令 在linux领域内大多用在服务器上,很少遇到关机的操作.毕竟服务器上跑一个服务是永无止境的,除非特殊情况面,不得已才会关机. 正确的关机流程为:sync>shutdown>r ...

  7. 数字音频处理的瑞士军刀sox的音效算法以及用法

    SoX可以明确的写出需要的音频处理的效果,可以方便的重复使用,在目前的条件下是一个比较方便使用的项目.不过相信随着Audacity的发展,很有可能在未来可以逐渐替代SoX的功能. 对于SoX主要关心的 ...

  8. git gc和fsck的用法

    一.保证git良好的性能 在大的仓库中, git靠压缩历史信息来节约磁盘和内存空间. 压缩操作并不是自动进行的, 你需要手动执行 git gc: $ git gc 压缩操作比较耗时, 你运行git g ...

  9. Python - 使用Pylint检查分析代码

    1-简介 Home Page : https://www.pylint.org/ 检查语法错误,是否遵守编码风格标准.潜在的问题等: 支持自定义配置:例如显示或隐藏特定的警告,并且可以通过编写插件来添 ...

  10. elasticsearch 摘要

    看终于有人把Elasticsearch原理讲透了!, 后总结: 反向索引又叫倒排索引,是根据文章内容中的关键字建立索引. 搜索引擎原理就是建立反向索引 elasticsearch在Lucene的基础上 ...