Task02:文本预处理/语言模型/循环神经网络基础

1.文本预处理

文本是一类序列数据,一篇文章可以看作是字符或单词的序列,本节将介绍文本数据的常见预处理步骤,预处理通常包括四个步骤:

1.读入文本
2.分词
3.建立字典,将每个词映射到一个唯一的索引(index)
4.将文本从词的序列转换为索引的序列,方便输入模型
在这里插入图片描述
细节搬运自:
https://blog.csdn.net/lt326030434/article/details/85240591
1.文本获取
既然如今主流研究使用机器学习或者统计模型的技术,那么一个首要问题就是,如何获取大量的数据?无论是统计还是机器学习,其准确率都建立在样本的好坏上,样本空间是否足够大,样本分布是否足够均匀,这些都将影响算法的最终结果。
获取语料库,一个方法就是去网络上寻找一些第三方提供的语料库,出名的开放语料库比如wiki。但事实上,很多情况中所研究或开发的系统往往是应用于某种特定的领域,这些开放语料库经常无法满足我们的需求。这种时候就需要使用另一种方法,使用爬虫去主动的获取想要的信息。可以使用如pyspider、scrapy等python框架非常轻松地编写出自己需要的爬虫,从而让机器自动地去获取大量数据,从而继续我们的研究。
2.分词
中英文在分词上,由于语言的特殊性导致分词的思路也会不一样。大多数情况下,英文直接使用空格就可以进行分词,例如:
在这里插入图片描述
复杂一点的情况可以调用spaCy和NLTK。
但是在中文上,由于语法更为复杂,我们通常会使用jieba等第三方库进行分词的操作,例如:
在这里插入图片描述
还有些时候,可能我们需要处理某些垂直领域的文本,例如医疗、法律等领域,我们可能需要更垂直的词库。这时候,我们可以考虑第三方词库,例如清华大学开源词库或者其他人分享的开源词库等。这时候我们可能需要自己设计分词的算法。
3.文本清洗
由于大多数情况下,我们准备好的文本里都有很多无用的部分,例如爬取来的一些html代码,css标签等。或者我们去除不需要用的标点符号、停用词等,我们需要分步骤去清洗。下面是一些常用的清洗方法:

去除标点符号

s = ''.join(c for c in word if c not in string.punctuation)

英文转换为小写

s.lower()

数字归一化

s = '#number' if s.isdigit() else s

停用词库/低频词库
停用词库:我们可以直接在搜索引擎上搜索“停用词库”或“english stop words list”,能找到很多停用词库。例如:

stop_words = ["a","able","about","across","after","all","almost","also","am","among","an","and","any","are","as","at","be","because","been","but","by","can","cannot","could","dear","did","do","does","either","else","ever","every","for","from","get","got","had","has","have","he","her","hers","him","his","how","however","i","if","in","into","is","it","its","just","least","let","like","likely","may","me","might","most","must","my","neither","no","nor","not","of","off","often","on","only","or","other","our","own","rather","said","say","says","she","should","since","so","some","than","that","the","their","them","then","there","these","they","this","tis","to","too","twas","us","wants","was","we","were","what","when","where","which","while","who","whom","why","will","with","would","yet","you","your","ain't","aren't","can't","could've","couldn't","didn't","doesn't","don't","hasn't","he'd","he'll","he's","how'd","how'll","how's","i'd","i'll","i'm","i've","isn't","it's","might've","mightn't","must've","mustn't","shan't","she'd","she'll","she's","should've","shouldn't","that'll","that's","there's","they'd","they'll","they're","they've","wasn't","we'd","we'll","we're","weren't","what'd","what's","when'd","when'll","when's","where'd","where'll","where's","who'd","who'll","who's","why'd","why'll","why's","won't","would've","wouldn't","you'd","you'll","you're","you've"]

低频次库:我们可以使用Counter等库获取所有句子中所有词的词频,通过筛选词频获得低频词库。例如:

from collections import Counter
获取词典
word_dict = Counter(sentence_list)
 建立低频词库
low_frequency_words = []
low_frequency_words.append([k for (k,v) in  word_dict.items() if v <2])

获取停用词库和低频词库后,将词库中的词语删除

if s not in stop_words and s not in low_frequency_words:
    sentence += s

去除不必要的标签
这一块在实际工作中需要灵活的使用,例如使用re库对文本做正则删除、替换,利用json库去解析json数据,又或者使用规则对文本进行相应的处理。
4.标准化
通常我们需要用到词形还原(Lemmatization)和词干提取(Stemming)
首先来看一下两者的区别
Stemming:

from nltk.stem.porter import PorterStemmer
porter_stemmer = PorterStemmer()
porter_stemmer.stem('wolves')

打印结果: ‘wolv’

Lemmatization:

from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
lemmatizer.lemmatize('wolves')

打印结果: ‘wolf’

  • 在原理上,词干提取主要是采用“缩减”的方法,将词转换为词干,如将“cats”处理为“cat”,将“effective”处理为“effect”。而词形还原主要采用“转变”的方法,将词转变为其原形,如将“drove”处理为“drive”,将“driving”处理为“drive”。
  • 在复杂性上,词干提取方法相对简单,词形还原则需要返回词的原形,需要对词形进行分析,不仅要进行词缀的转化,还要进行词性识别,区分相同词形但原形不同的词的差别。词性标注的准确率也直接影响词形还原的准确率,因此,词形还原更为复杂。
  • 在结果上,词干提取和词形还原也有部分区别。词干提取的结果可能并不是完整的、具有意义的词,而只是词的一部分,如“revival”词干提取的结果为“reviv”,“ailiner”词干提取的结果为“airlin”。而经词形还原处理后获得的结果是具有一定意义的、完整的词,一般为词典中的有效词。
  • 在应用领域上,同样各有侧重。虽然二者均被应用于信息检索和文本处理中,但侧重不同。词干提取更多被应用于信息检索领域,如Solr、Lucene等,用于扩展检索,粒度较粗。词形还原更主要被应用于文本挖掘、自然语言处理,用于更细粒度、更为准确的文本分析和表达,所以我们要根据实际使用场景去选择我们的标准化方法。

5.特征提取
通常会采用TF-IDF、Word2Vec、CountVectorizer等方式实现对文本特征的提取。在这里只简单讲解一下几个方法的概念,之后会在其他文章中详细讲解几种方法的区别。

TF-IDF
词语由t表示,文档由d表示,语料库由D表示。词频TF(t,d)是词语t在文档d中出现的次数。文件频率DF(t,D)是包含词语的文档的个数。如果我们只使用词频来衡量重要性,很容易过度强调在文档中经常出现而并没有包含太多与文档有关的信息的词语,比如“a”,“the”以及“of”。如果一个词语经常出现在语料库中,它意味着它并没有携带特定的文档的特殊信息。

Word2Vec
Word2vec是一个Estimator,它采用一系列代表文档的词语来训练word2vecmodel。该模型将每个词语映射到一个固定大小的向量。word2vecmodel使用文档中每个词语的平均数来将文档转换为向量,然后这个向量可以作为预测的特征,来计算文档相似度计算等等。

Countvectorizer
Countvectorizer和Countvectorizermodel旨在通过计数来将一个文档转换为向量。当不存在先验字典时,Countvectorizer可作为Estimator来提取词汇,并生成一个Countvectorizermodel。该模型产生文档关于词语的稀疏表示,其表示可以传递给其他算法如LDA。

2.语言模型

对于语言模型的梳理如下图:
在这里插入图片描述
一段自然语言文本可以看作是一个离散时间序列,给定一个长度为 T T T的词的序列 w 1 , w 2 , … , w T w_1, w_2, \ldots, w_T w1,w2,,wT,语言模型的目标就是评估该序列是否合理,即计算该序列的概率:

P ( w 1 , w 2 , … , w T ) = ∏ t = 1 T P ( w t ∣ w 1 , … , w t − 1 ) = P ( w 1 ) P ( w 2 ∣ w 1 ) ⋯ P ( w T ∣ w 1 w 2 ⋯ w T − 1 ) P(w_1, w_2, \ldots, w_T)= \prod_{t=1}^T P(w_t \mid w_1, \ldots, w_{t-1})\\= P(w_1)P(w_2 \mid w_1) \cdots P(w_T \mid w_1w_2\cdots w_{T-1}) P(w1,w2,,wT)=t=1TP(wtw1,,wt1)=P(w1)P(w2w1)P(wTw1w2wT1)

本节我们介绍基于统计的语言模型,主要是 n n n元语法( n n n-gram)。在后续内容中,我们将会介绍基于神经网络的语言模型。
假设序列 w 1 , w 2 , … , w T w_1, w_2, \ldots, w_T w1,w2,,wT中的每个词是依次生成的,我们有

P ( w 1 , w 2 , … , w T ) P(w_1, w_2, \ldots, w_T) P(w1,w2,,wT)

例如,一段含有4个词的文本序列的概率

P ( w 1 , w 2 , w 3 , w 4 ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 1 , w 2 ) P ( w 4 ∣ w 1 , w 2 , w 3 ) . P(w_1, w_2, w_3, w_4) = P(w_1) P(w_2 \mid w_1) P(w_3 \mid w_1, w_2) P(w_4 \mid w_1, w_2, w_3). P(w1,w2,w3,w4)=P(w1)P(w2w1)P(w3w1,w2)P(w4w1,w2,w3).

语言模型的参数就是词的概率以及给定前几个词情况下的条件概率。设训练数据集为一个大型文本语料库,如维基百科的所有条目,词的概率可以通过该词在训练数据集中的相对词频来计算,例如, w 1 w_1 w1的概率可以计算为:

P ^ ( w 1 ) = n ( w 1 ) n \hat P(w_1) = \frac{n(w_1)}{n} P^(w1)=nn(w1)

其中 n ( w 1 ) n(w_1) n(w1)为语料库中以 w 1 w_1 w1作为第一个词的文本的数量, n n n为语料库中文本的总数量。

类似的,给定 w 1 w_1 w1情况下, w 2 w_2 w2的条件概率可以计算为:

P ^ ( w 2 ∣ w 1 ) = n ( w 1 , w 2 ) n ( w 1 ) \hat P(w_2 \mid w_1) = \frac{n(w_1, w_2)}{n(w_1)} P^(w2w1)=n(w1)n(w1,w2)

其中 n ( w 1 , w 2 ) n(w_1, w_2) n(w1,w2)为语料库中以 w 1 w_1 w1作为第一个词, w 2 w_2 w2作为第二个词的文本的数量。

n元语法

序列长度增加,计算和存储多个词共同出现的概率的复杂度会呈指数级增加。 n n n元语法通过马尔可夫假设简化模型,马尔科夫假设是指一个词的出现只与前面 n n n个词相关,即 n n n阶马尔可夫链(Markov chain of order n n n),如果 n = 1 n=1 n=1,那么有 P ( w 3 ∣ w 1 , w 2 ) = P ( w 3 ∣ w 2 ) P(w_3 \mid w_1, w_2) = P(w_3 \mid w_2) P(w3w1,w2)=P(w3w2)。基于 n − 1 n-1 n1阶马尔可夫链,我们可以将语言模型改写为

P ( w 1 , w 2 , … , w T ) = ∏ t = 1 T P ( w t ∣ w t − ( n − 1 ) , … , w t − 1 ) . P(w_1, w_2, \ldots, w_T) = \prod_{t=1}^T P(w_t \mid w_{t-(n-1)}, \ldots, w_{t-1}) . P(w1,w2,,wT)=t=1TP(wtwt(n1),,wt1).

以上也叫 n n n元语法( n n n-grams),它是基于 n − 1 n - 1 n1阶马尔可夫链的概率语言模型。例如,当 n = 2 n=2 n=2时,含有4个词的文本序列的概率就可以改写为:

P ( w 1 , w 2 , w 3 , w 4 ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 1 , w 2 ) P ( w 4 ∣ w 1 , w 2 , w 3 ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 2 ) P ( w 4 ∣ w 3 ) P(w_1, w_2, w_3, w_4) = P(w_1) P(w_2 \mid w_1) P(w_3 \mid w_1, w_2) P(w_4 \mid w_1, w_2, w_3)\\ = P(w_1) P(w_2 \mid w_1) P(w_3 \mid w_2) P(w_4 \mid w_3) P(w1,w2,w3,w4)=P(w1)P(w2w1)P(w3w1,w2)P(w4w1,w2,w3)=P(w1)P(w2w1)P(w3w2)P(w4w3)

n n n分别为1、2和3时,我们将其分别称作一元语法(unigram)、二元语法(bigram)和三元语法(trigram)。例如,长度为4的序列 w 1 , w 2 , w 3 , w 4 w_1, w_2, w_3, w_4 w1,w2,w3,w4在一元语法、二元语法和三元语法中的概率分别为

P ( w 1 , w 2 , w 3 , w 4 ) = P ( w 1 ) P ( w 2 ) P ( w 3 ) P ( w 4 ) , P ( w 1 , w 2 , w 3 , w 4 ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 2 ) P ( w 4 ∣ w 3 ) , P ( w 1 , w 2 , w 3 , w 4 ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 1 , w 2 ) P ( w 4 ∣ w 2 , w 3 ) . P(w_1, w_2, w_3, w_4) = P(w_1) P(w_2) P(w_3) P(w_4) ,\\ P(w_1, w_2, w_3, w_4) = P(w_1) P(w_2 \mid w_1) P(w_3 \mid w_2) P(w_4 \mid w_3) ,\\ P(w_1, w_2, w_3, w_4) = P(w_1) P(w_2 \mid w_1) P(w_3 \mid w_1, w_2) P(w_4 \mid w_2, w_3) . P(w1,w2,w3,w4)=P(w1)P(w2)P(w3)P(w4),P(w1,w2,w3,w4)=P(w1)P(w2w1)P(w3w2)P(w4w3),P(w1,w2,w3,w4)=P(w1)P(w2w1)P(w3w1,w2)P(w4w2,w3).

n n n较小时, n n n元语法往往并不准确。例如,在一元语法中,由三个词组成的句子“你走先”和“你先走”的概率是一样的。然而,当 n n n较大时, n n n元语法需要计算并存储大量的词频和多词相邻频率。
(1)n元模型的参数
在这里插入图片描述
(2)n的选择从(1)表中可以看出来,n越大,模型需要的参数越多,参数数量指数增长。而另一个方面,n越大,历史信息越多,模型就越准确。A. n越大时 - 提供了更多的语境信息,语境更具有区别性; - 参数个数多、计算代价大、训练语料需要多、参数估计不可靠;B. n较小时 - 语境信息少,不具区别性; - 但是,参数个数少、计算代价小、训练语料无需太多、参数估计可靠。n元模型等价于n-1阶马尔可夫过程,即n元模型把句子看出是马尔可夫过程的产物;为此,为了 将出现在不同位置的同一个词区分开,并且保证n元模型对于句子中前n-1个词也有意义,我们需要加入标记bos来标志句子开始;为了保证词组合的句子出现的概率和为1,需要在句末加入eos来标志句子结束。

语言模型性能评价

语言模型的评价目标:语言模型的计算的概率分布能够与真实的理想模型的概率分布可以相接近。
常用的几个指标:交叉熵,困惑度
我们通常使用困惑度(perplexity)来评价语言模型的好坏。回忆一下“softmax回归”一节中交叉熵损失函数的定义。困惑度是对交叉熵损失函数做指数运算后得到的值。特别地,

最佳情况下,模型总是把标签类别的概率预测为1,此时困惑度为1;
最坏情况下,模型总是把标签类别的概率预测为0,此时困惑度为正无穷;
基线情况下,模型总是预测所有类别的概率都相同,此时困惑度为类别个数。
显然,任何一个有效模型的困惑度必须小于类别个数。

3.循环神经网络基础

本节介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量 H H H,用 H t H_{t} Ht表示 H H H在时间步 t t t的值。 H t H_{t} Ht的计算基于 X t X_{t} Xt H t − 1 H_{t-1} Ht1,可以认为 H t H_{t} Ht记录了到当前字符为止的序列信息,利用 H t H_{t} Ht对序列的下一个字符进行预测。
在这里插入图片描述

循环神经网络的构造

我们先看循环神经网络的具体构造。假设 X t ∈ R n × d \boldsymbol{X}_t \in \mathbb{R}^{n \times d} XtRn×d是时间步 t t t的小批量输入, H t ∈ R n × h \boldsymbol{H}_t \in \mathbb{R}^{n \times h} HtRn×h是该时间步的隐藏变量,则:

H t = ϕ ( X t W x h + H t − 1 W h h + b h ) . \boldsymbol{H}_t = \phi(\boldsymbol{X}_t \boldsymbol{W}_{xh} + \boldsymbol{H}_{t-1} \boldsymbol{W}_{hh} + \boldsymbol{b}_h). Ht=ϕ(XtWxh+Ht1Whh+bh).

其中, W x h ∈ R d × h \boldsymbol{W}_{xh} \in \mathbb{R}^{d \times h} WxhRd×h W h h ∈ R h × h \boldsymbol{W}_{hh} \in \mathbb{R}^{h \times h} WhhRh×h b h ∈ R 1 × h \boldsymbol{b}_{h} \in \mathbb{R}^{1 \times h} bhR1×h ϕ \phi ϕ函数是非线性激活函数。由于引入了 H t − 1 W h h \boldsymbol{H}_{t-1} \boldsymbol{W}_{hh} Ht1Whh H t H_{t} Ht能够捕捉截至当前时间步的序列的历史信息,就像是神经网络当前时间步的状态或记忆一样。由于 H t H_{t} Ht的计算基于 H t − 1 H_{t-1} Ht1,上式的计算是循环的,使用循环计算的网络即循环神经网络(recurrent neural network)。

在时间步 t t t,输出层的输出为:

O t = H t W h q + b q . \boldsymbol{O}_t = \boldsymbol{H}_t \boldsymbol{W}_{hq} + \boldsymbol{b}_q. Ot=HtWhq+bq.

其中 W h q ∈ R h × q \boldsymbol{W}_{hq} \in \mathbb{R}^{h \times q} WhqRh×q b q ∈ R 1 × q \boldsymbol{b}_q \in \mathbb{R}^{1 \times q} bqR1×q
将循环神经网络在时序上展开如下图:
在这里插入图片描述发展到现在,循环神经网络产生了各种变体,如GRU,LSTM等。
包括循环神经网络训练用的的基于时间的反向传播算法(BPTT),以及训练时遇到的梯度爆炸与梯度消失问题,这些都是值得去研究学习的点。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值