文本预处理、语言模型与RNN基础-task2

这里对《ElitesAI·动手学深度学习PyTorch版》Task2的学习做个简短的总结。

Task2中总共分为3个部分:文本预处理语言模型RNN基础

主要学习了分词,n-gram,随机采样与相邻采样还有基础的RNN知识。

文本预处理

1. 关于re正则

推荐学习链接:https://blog.csdn.net/qq_41185868/article/details/96422320#3%E3%80%81%E6%A3%80%E7%B4%A2%E5%92%8C%E6%9B%BF%E6%8D%A2

lines = [re.sub('[^a-z]+', ' ', line.strip().lower()) for line in f]

# 上面这行代码的正则部分为
re.sub('[^a-z]+', ' ', str)
# re.sub()函数是用来字符串替换的函数
# '[^a-z]+' 注意这里的^是非的意思,就是说非a-z字符串
# 上面句子的含义是:将字符串str中的非小写字母开头的字符串以空格代替
2. 关于建立词典

这里是对Vocab类实现的理解,首先是这个类想干什么?

Vocab类想实现将词映射成一个索引,既然是索引那么相同的词就应该具有相同的索引,所以这里对于输入的文本还会进行一个去重的操作。

此外,Vocab还想方便的获取给定某个词对应的索引,以及给定一个索引获取这个索引所对应的词。除了上面说的两个功能,还有一个就是统计了每一个词的词频。

3. 常用的分词工具
  • Spacy
  • NLTK

语言模型

1. n-gram语言模型

假设序列 w 1 , w 2 , … , w T w_1, w_2, \ldots, w_T w1,w2,,wT中的每个词是依次生成的,我们有

KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ P(w_1, w_2, \l…

例如,一段含有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为语料库中文本的总数量。

此处需要再斟酌,按照书上所说, n ( w 1 ) n(w_1) n(w1)表示分词后的 w 1 w_1 w1出现的次数

类似的,给定 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作为第二个词的文本的数量。

2. 采样方式

随机采样:与mini_batch类似,对整个序列shuffle后,每次训练从训练集indices中选取batch_size个样本,组成1个batch进行训练。

相邻采样:其原理如下图所示,下图中batch_size为3,可见整个序列被拆分为3份,每次iteration取3份中相同位置的样本,然后组合为1个batch进行训练。
在这里插入图片描述

RNN基础

下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量 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对序列的下一个字符进行预测。
Image Name

1. 循环神经网络的构造

我们先看循环神经网络的具体构造。假设 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

2. 总结

在代码实现中, H 1 \boldsymbol{H}_1 H1 前面往往还会输入一个 H 0 \boldsymbol{H}_0 H0,一方面保证程序和公式的通用性,另一方面在遇到相邻采样时,可以利用到前面相邻样本的先验信息。

如果采取随机采样策略,训练每1个batch时,会将 H 0 \boldsymbol{H}_0 H0 初始化为0。

如果采取相邻采样策略,训练第i个batch时,有 H 0 i = H t i − 1 \boldsymbol{H}^i_0=\boldsymbol{H}^{i-1}_t H0i=Hti1 其中 t = n u m _ s t e p s t=num\_steps t=num_steps。其代码如下:

for X, Y in data_iter:
    if is_random_iter:  # 如使用随机采样,在每个小批量更新前初始化隐藏状态
        state = init_rnn_state(batch_size, num_hiddens, device)
    else:  # 否则需要使用detach函数从计算图分离隐藏状态
    	for s in state:
        	s.detach_() 

此处需要注意.detach_()的用法,在昨天的笔记中对.data()和.detach()进行了区分,.detach_()的功能和.detach()基本一致,唯一的区别在于.detach_()是一个in-place operation,即在代码中可以这样进行等效:

# 下方代码等效于for s in state: s.detach_() 
for i, s in enumerate(state):
    state[i] = s.detach()

在代码中,s是上一个batch训练完得到的 H t H_{t} Ht,存储着上一个batch的历史信息,且在计算图中是与上一个batch的计算变量相关联的, H t = ϕ ( X t W x h + H t − 1 W h h + b h ) {H}_t = \phi({X}_t {W}_{xh} + {H}_{t-1} {W}_{hh} + {b}_h) Ht=ϕ(XtWxh+Ht1Whh+bh),此处需要调用.detach_()改变计算图,将上个batch的 H t {H}_t Ht也就是这个batch的 H 0 H_0 H0搞成一个叶子结点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值