2020.08.03
开始试验的第一天,首先从安装环境走起。由于实验指导书上要求的包没法直接使用pip
命令进行安装,下载速度慢,下到一半还老是断开连接,所以基本上都采用直接去PyPI上下载安装包进行手动安装。
首先新建了一个名为nlp
的Python虚拟环境:
1 | conda create -n nlp python=3.6 |
然后根据教程的要求安装jieba
、gensim
、torch
三个库,因为CUDA
和cuDNN
以前做图像的时候已经装过10.0版本的了,就将就用。全部安装完成后,虚拟环境下的包和版本信息如下:
1 | # packages in environment at S:\Anaconda3\envs\nlp: |
经过测试,三个包均可正常导入,其中输入命:
1 | torch.cuda.is_availabel() |
输出值为True
,说明GPU可正常调用。
NLP基本概念
语料库(Corpus)
所有的文本集合。
分词(Tokenization)
就是把一篇文章拆分成一个个的单词,如果是中文,则是把一篇文章拆分成一个个的词语。
停用词(StopWords)
某些NLP任务需要将一些常出现的“无意义”的词去掉,比如:统计一篇文章频率最高的100个词,可能会有大量的“is”、”a”、”the” 、“一个”、“与”这类词,它们就是StopWords。
归一化(Normalization)
将一系列的单词转化成某种统一的形式, 比如:将一句话的各个单词中,有大写、有小写,将之统一转成小写。再比如,一句话中,有些单词是缩写词,将之统一转换成全名。
词向量(Word Embedding)
词向量主要用于将自然语言中的词符号数学化,这样才能作为机器学习问题的输入。数学化表示词的方式很多,最简单的有独热(ont-hot) 编码。例如:现共有三个词语“篮球”、“足球”、“排球”,则分别用独热编码将它们表示为: [1,0,0],[0,1,0],[0,0,1]。 显然,独热编码有以下缺点:1.可能导致维数过大,对算法来说复杂度过高。2.两个词的相似程度无法表示。
词向量与独热编码不同,一般是以下形式:[0.2333,0.4324,0.6666,-0.9527,…],维数以50维和100 维比较常见。词向量解决了维度过大的问题,且两个词的相似度可以用欧几里得距离、余弦相似度等方法求得。word2vec 是最常见的词向量获取方法。
2020.08.05
正则表达式
re.match( pattern, string, flags=0)
re.match
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()
就返回none
。
re.search(pattern, string, flags=0)
re.search
扫描整个字符串并返回第一个成功的匹配。
re.sub(patterm, repl, string, count=0, flags=0)
re.sub
用于替换字符串中的匹配项。
re.compile(pattern[, flags])
compile
函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供match()
和search()
这两个函数使用。
模式 | 描述 | |
---|---|---|
^ |
匹配字符串的开头 | |
$ |
匹配字符串的末尾 | |
. |
匹配任意字符,除了换行符,当re.DOTALL 标记被指定时,则可以匹配包括换行符的任意字符 |
|
re{n} |
精确匹配n个前面表达式。例如,o{2} 不能匹配”Bob” 中的”o”, 但是能匹配”food” 中的两个o | |
re{n,} |
匹配n个前面表达式。例如,o{2,} 不能匹配”Bob”中 的”o”,但能匹配”fooood”中的所有o。 “o{1,}” 等价于”o+”。 “o{0,}” 则等价于”o*” | |
re{n,m} |
匹配n到m次由前面的正则表达式定义的片段,贪婪方式 | |
`a | b` | 匹配a或b |
\1...\9 |
匹配第n个分组的内容 |
2020.08.06
jieba的使用
分词
jieba.cut
方法接受三个输入参数:需要分词的字符串;cut_all
参数用来控制是否采用全模式;HMM
参数用来控制是否使用 HMM 模型 。jieba.cut_for_search
方法接受两个参数:需要分词的字符串;是否使用 HMM 模型。该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细。- 待分词的字符串可以是 unicode 或 UTF-8 字符串、GBK 字符串。注意:不建议直接输入 GBK 字符串,可能无法预料地错误解码成 UTF-8。
jieba.cut
以及jieba.cut_for_search
返回的结构都是一个可迭代的generator
,可以使用for
循环来获得分词后得到的每一个词语(unicode),或者用jieba.lcut
以及jieba.lcut_for_search
直接返回list
。jieba.Tokenizer(dictionary=DEFAULT_DICT)
新建自定义分词器,可用于同时使用不同词典。jieba.dt
为默认分词器,所有全局分词相关函数都是该分词器的映射。
全模式下会将所有可能的词语都进行分词,有时候他可以切出一些不太好切出的词,同时增大词汇量,但是他也会引入一些不太准确的分词。
精确模式下会尽可能的将句子精确切开,一般情况下采用这种模式即可。
搜索引擎模式是在精确模式的基础上,对长词再进行划分,提高分词的召回率,适合用于搜索引擎分词。
添加自定义词典
开发者可以指定自定义词典,以便包含 jieba 词库里没有的词。虽然 jieba 有新词识别能力,但是自行添加新词可以保证更高的分词正确率
jieba.load_userdict(file_name)
,file_name
为文件类对象或自定义词典的路径,词典格式和dict.txt
一样,一个词占一行,每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。file_name
若为路径或二进制方式打开的文件,则文件必须为 UTF-8 编码。词频省略时使用自动计算的能保证分出该词的词频。- 使用
add_word(word,freq=None,tag=None)
和del_word(word)
可在程序中动态修改词典。
非常见词需要进行添加自定义词典操作才能更好地分词,采用 add_word()
方法适合于需要添加的词不多的情况,如果词语较多建议采用 load_userdict()
。
关键词提取
关键词抽取就是从文本里面把跟这篇文档主题最相关的一些词抽取出来。这个可以追溯到文献检索初期,当时还不支持全文搜索的时候,关键词就可以作为搜索这篇论文的词语。因此,目前依然可以在论文中看到关键词这一项。jieba 分词系统中实现了两种关键词抽取算法,分别是基于 TF-IDF 的关键词抽取算法和基于 TextRank 的关键词抽取算法,两类算法均是无监督学习算法。
- 基于 TF-IDF 算法的关键词抽取
jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
sentence
为待提取的文本topK
为返回几个 TF-IDF 值最大的关键词,默认值为20
withWeight
为是否一并返回关键词权重值,默认值为False
allowPOS
仅包括指定词性的词,默认值为空,即不筛选。
- 基于 TextRank 算法的关键词抽取
jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=())
TF-IDF
在信息检索理论中,TF-IDF 是 Term Frequency - Inverse Document Frequency 的简写。TF-IDF 是一种数值统计,用于反映一个词对于语料中某篇文档的重要性。在信息检索和文本挖掘领域,它经常用于因子加权。TF-IDF 的主要思想就是:如果某个词在一篇文档中出现的频率高,也即 TF 高;并且在语料库中其他文档中很少出现,即 DF 的低,也即 IDF 高,则认为这个词具有很好的类别区分能力。TF-IDF在实际应用中主要是将二者相乘,也即TF IDF,TF为词频(Term Frequency),表示词 t 在文档 d 中出现的频率;IDF 为逆文档频率(Inverse Document Frequency),表示语料库中包含词 t 的文档的数目的倒数。
*TextRank
类似于 PageRank 的思想,将文本中的语法单元视作图中的节点,如果两个语法单元存在一定语法关系(例如共现),则这两个语法单元在图中就会有一条边相互连接,通过一定的迭代次数,最终不同的节点会有不同的权重,权重高的语法单元可以作为关键词。
Gensim 的使用
Gensim 是一款开源的第三方 Python 工具包,用于从原始的非结构化文本中,无监督地学习到文本隐层的主题向量表达。它支持包括 TF-IDF、LSA、LDA、和 word2vec 在内的多种主题模型算法,支持流式训练,并提供了诸如相似度计算、信息检索等一些常用任务的API 接口。
word2vec 词向量
word2vec 就是一种词嵌入,说的简单一点就是将一个词语表征为一个向量,当然这肯定不是一个随意给的一个向量,它是在一定的约束条件下得到。显然,首先作为一个向量,它可以被计算机“理解”,并用来进行各种数值运算;其次,两个向量之间的相似度表征了对应的两个词语的语义相似度。word2vec 非常的看重语言的逻辑性,也就是词语的前后关系。
计算词向量(word2vec)
利用 gensim.models.Word2Vec(sentences)
建立词向量模型,该构造函数执行了三个步骤:建立一个空的模型对象,遍历一次语料库建立词典,第二次遍历语料库建立神经网络模型可以通过分别执行 model=gensim.models.Word2Vec()
,model.build_vocab(sentences)
,model.train(sentences)
来实现。
训练时可以指定以下参数:
min_count
指定了需要训练词语的最小出现次数,默认为 5。size
指定了训练时词向量维度,默认为 100。worker
指定了完成训练过程的线程数,默认为 1 不使用多线程。model.wv.save_word2vec_format(‘word2vec_model.txt’,binary=False)
保存模型。gensim.models.KeyedVectors.load_word2vec_format('word2vec_model.txt',binary=False)
加载模型。
计算词语相似度
word2vec 是一个将单词转换成向量形式的工具。可以把对文本内容的处理简化为向量空间中的向量运算,计算出向量空间上的相似度,来表示文本语义上的相似度。
根据模型训练的结果,可以进行各种相似度的计算:
(1) 找出近义词中最相似的 topn
个词语:model.most_similar(positive=['word1','word2'], topn=10)
(2) 找出反义词中最相似的 topn
个词语:model.most_similar(negative=['word1','word2'], topn=10)
(3) 找出气质不合的词语:model.doesnt_match(['word1','word2','word3','word4'])
(4) 计算两个词语的相似度:model.similarity('word1','word2')
2020.08.11
实验一
实验题目及内容:
利用jieba对《网络新闻实体发现与情感识别》案例数据进行分词。
代码:
1 | # -*- coding:utf-8 -*- |
实验步骤:
这里以训练集为例,首先将训练集文件读取进来,训练集源文件为txt文档,文档中记录的每一行为一个样例,且一行为一个独立的json格式字符串。所以在读取文件的时候要一行行的进行读取,然后单独转换成json对象,最后拼接起来转换为DataFrame。
由于样例的‘title
’字段和‘content
’字段均为文本内容,我们将其拼接为‘text
’字段统一处理。然后对数据进行预处理,主要是使用正则表达式去除文本中的html标签,然后将字母归一化为小写,最后再将繁体字转化为简体。
数据预处理完成以后对DataFrame使用jieba进行逐行分词,这里使用的是精确模式,最后分词结果如下:
1 | newsId ... text |
注意:
这里使用的繁体转简体代码为第三方库,源码下载地址。
实验二
实验题目及内容:
利用Gensim训练《网络新闻实体发现与情感识别》案例数据的word2vec词向量。
代码:
1 | # -*- coding:utf-8 -*- |
实验步骤:
在实验一的基础上继续进行本实验,将分割好的词语列表放到gensim的Word2Vec
函数中进行训练,训练结束后再将模型保存。我们这里将词向量的维度设为了100,打开保存好的模型文件可以看到如下内容:
1 | 331479 100 |
整个词向量模型的大小为375MB,经过分词以后总共分割出了331479个不同的词语,然后每个词语后有100个数值,即为词向量的值。然后我们使用如下代码将保存好的模型读取进来,然后计算和智慧
最相似与最不相似的词语:
1 | model=gensim.models.KeyedVectors.load_word2vec_format('word2vec_model.txt',binary=False) |
输出结果如下,可以看到效果还算可以。
1 | [('数据分析', 0.6511616706848145), ('统计数据', 0.6379164457321167), ('历史数据', 0.6222556829452515), ('数据资料', 0.6182267665863037), ('信息', 0.6004210114479065)] |