新手入坑LSTM-----如何一步一步进行文本训练

最近在学习一个课程,课程里一个项目就是看图说话,需要提起使用CNN提取图像特征,然后使用LSTM进行文本特征提取,然后将图像特征和文本特征进行合并,扔到网络里面进行训练,完成看图说话的训练,CNN很熟悉,LSTM第一次接触,记录下新手使用 LSTM 的过程。

一、RNN

下图是RNN模型的结构图
在这里插入图片描述

上图的RNN 的工作模式是这样的:

假如更定"the students opened their"四个单词,预测第5个单词出现的概率,先把"the"这个单词的one-hot即独热编码的向量,通过Embedding将稀疏的独热向量变成一个稠密的向量 e e e,通过下面的公式获得中间隐藏层的值:
h ( t ) = σ ( W h h t − 1 + W e e ( t ) + b 1 h^{(t)} = \sigma(W_hh^{t-1} + W_ee{(t)} + b_1 h(t)=σ(Whht1+Wee(t)+b1
那么 h ( 1 ) h^{(1)} h(1)的计算方式是:
h ( 1 ) = σ ( W h h 0 + W e e ( 1 ) + b 1 ) h^{(1)} = \sigma(W_hh^{0} + W_ee^{(1)} + b_1) h(1)=σ(Whh0+Wee(1)+b1)
h ( 0 ) h^{(0)} h(0)可以随机初始化,即 h ( 0 ) h^{(0)} h(0) W h W_h Wh相乘之后加上 e ( 1 ) e^{(1)} e(1) W e W_e We相乘的结果,得到了中间变量 h ( 1 ) h^{(1)} h(1),。

第二个单词"students"进来之后,重复和第一个单词的过程,只不过这里使用的中间变量是 h ( 1 ) h^{(1)} h(1),里面包含有第一个单词"the"的一些信息,这样可以生成中间变量 h ( 2 ) h^{(2)} h(2) h ( 2 ) h^{(2)} h(2)里面有第一个单词"the"和第二个单词"students"的信息,依次计算下去,一直到计算出来 h ( 4 ) h^{(4)} h(4) h ( 4 ) h^{(4)} h(4)是我们看过了"the students opened their"四个单词之后的结果,然后 h ( 4 ) h^{(4)} h(4)经过下面的公式获得概率分布;
y ( t ) = s o f t m a x ( U h ( t ) + b 2 ) y^{(t)} = softmax(Uh^{(t)} + b_2) y(t)=softmax(Uh(t)+b2)

如果 e ( t ) e^{(t)} e(t)转置的尺寸是(4, 1), h ( t − 1 ) h^{(t-1)} h(t1)转置的尺寸是(13, 11),那么 W e W_e We的尺寸是(13, 4), W h W_h Wh的尺寸是(13, 13),那么 h ( t ) h^{(t)} h(t)转置的尺寸是13x13x13x1+13x4x4x1=(13, 1).

下面图是RNN 的训练模式:
在这里插入图片描述

例如我们要训练一句话"the students opened their exams",首先我们拿出"the",进行one-hot编码,然后进行embedding,成为 e ( 1 ) e^{(1)} e(1), e ( 1 ) e^{(1)} e(1)经过下面的公式得到的隐藏层变量 h ( 1 ) h^{(1)} h(1)
h ( t ) = σ ( W h h t − 1 + W e e ( t ) + b 1 h^{(t)} = \sigma(W_hh^{t-1} + W_ee{(t)} + b_1 h(t)=σ(Whht1+Wee(t)+b1
然后经过下面的公式获得概率分布 y ( 1 ) y^{(1)} y(1)
y ( t ) = s o f t m a x ( U h ( t ) + b 2 ) y^{(t)} = softmax(Uh^{(t)} + b_2) y(t)=softmax(Uh(t)+b2)
y ( 1 ) y^{(1)} y(1)是预测下一个单词的概率分布,而下一个单词的真实值是"students“,这样根据预测值和真实值可以计算Loss函数 J ( 1 ) ( θ ) J^{(1)}(\theta) J(1)(θ),那么按照同意的方法可以计算,给定"the sutdent”预测"opened"的损失值 J ( 2 ) ( θ ) J^{(2)}(\theta) J(2)(θ), 给定"the sutdent opened”预测"their"的损失值 J ( 3 ) ( θ ) J^{(3)}(\theta) J(3)(θ), 给定"the sutdent opened their”预测"exams"的损失值 J ( 4 ) ( θ ) J^{(4)}(\theta) J(4)(θ), 然后
L o s s = J ( 1 ) ( θ ) + J ( 2 ) ( θ ) + J ( 3 ) ( θ ) + J ( 4 ) ( θ ) Loss = J^{(1)}(\theta) + J^{(2)}(\theta) +J^{(3)}(\theta) +J^{(4)}(\theta) Loss=J(1)(θ)+J(2)(θ)+J(3)(θ)+J(4)(θ)

RNN的优势是:1、能够处理任何长度的输入; 2、t时刻时能够使用t-1, t-2, t-3,…等时刻的信息;3、增加输入的长度,模型的大小不会变;4、每个时刻共享权重。

RNN的劣势:1、RNN很慢(上一步相乘的结果作为下一步相乘的输入);2、实际上,RNN使用更多的信息是离自己越近的时刻。

二、LSTM

1、什么是LSTM
传统的RNN一直在擦除和改写中间隐藏层变量 h ( t ) h^{(t)} h(t),可以给RNN不同的存储的地方来保持一个特别的状态,这种思路就是LSTM(long short-term memory),来解决梯度消失的问题。

下图是LSTM各种门的意义:
在这里插入图片描述
f ( t ) f^{(t)} f(t)是遗忘门,之前的状态中哪部分是被保留,哪部分是被遗忘的;
i ( t ) i^{(t)} i(t)是输入门,新的cell中哪部分被写入;
o ( t ) o^{(t)} o(t)是输出门,控制哪一部分输出成为下个隐藏层;
c ~ ( t ) \tilde{c}^{(t)} c~(t)是新的单元格内容
c ( t ) {c}^{(t)} c(t)是单元门,从上一个单元内容中擦除一些内容,把新的内容写入;
h ( t ) h^{(t)} h(t)是隐藏层
在这里插入图片描述
X t X_t Xt进入之后和 h t − 1 h_{t-1} ht1一起根据公式计算出 f t f_{t} ft i t i_{t} it o t o_{t} ot c ~ t \tilde{c}^t c~t,然后根据这四个门计算出 c t {c}^t ct h t h^t ht

lstm结构让RNN 能够保存更长久的信息,这种可以比较大程度上减弱梯度消失的问题,但是不能避免这个问题,但是LSTM在实际中依旧取得了很好的成绩。

三、实操训练LSTM

下面是一个基础款的lstm的训练流程

1、 准备训练数据文本库:
例如 Flickr8K数据集,8000 图像, 每幅图5个标题, 描述图像里面的事物和事件
在这里插入图片描述
2、 tokenizer (分词,文本向量化)
例如,lines是Flickr8K数据集中训练集的语料库,下面是keras中的tokenizer在这个语料库上训练的结果

tokenizer = Tokenizer()   #初始化
tokenizer.fit_on_texts(lines)  # 训练
test_line = " in street racer armor be examine the tire"
print (tokenizer.texts_to_sequences(line)[0])
 [4, 73, 711, 4558, 497, 2782, 5, 465]     

通过上面的方式," in street racer armor be examine the tire"就向量化为[4, 73, 711, 4558, 497, 2782, 5, 465],我们可以用一个小的例子,来看下是怎么向量化的
tokenizer = Tokenizer()

tokenizer.fit_on_texts(["I am am am the a student",
                       "being a student student student feeling good, "])
print (tokenizer.index_word)
print (tokenizer.word_index)
print (tokenizer.word_counts)

{1: 'student', 2: 'am', 3: 'a', 4: 'i', 5: 'the', 6: 'being', 7: 'feeling', 8: 'good'}
{'student': 1, 'am': 2, 'a': 3, 'i': 4, 'the': 5, 'being': 6, 'feeling': 7, 'good': 8}
OrderedDict([('i', 1), ('am', 3), ('the', 1), ('a', 2), ('student', 4), ('being', 1), ('feeling', 1), ('good', 1)])

word_counts: 字典,将单词(字符串)映射为它们在训练期间出现的次数。仅在调用fit_on_texts之后设置。
word_docs: 字典,将单词(字符串)映射为它们在训练期间所出现的文档或文本的数量。仅在调用fit_on_texts之后设置。
word_index: 字典,将单词(字符串)映射为它们的排名或者索引。仅在调用fit_on_texts之后设置。

3、 pad_sequences 填充序列使文本集中所有文本长度相同。
上面的步骤之后,将字符串进行量化,但是由于每句的长度不一样,因此需要做填充

# in_seq是已经向量化过的
in_seq = [2]
pad_sequences([in_seq], maxlen=10)[0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 2]

4、 embedding 进行嵌入化编码
one-hot编码表示太浪费内存了,需要讲稀疏的独热编码,变成稠密的向量,边稠密的原理是,独热编码的一个特点是向量与向量之间是独立同分布的,看不到向量与向量之间的关系,但是在自然语言中,词语与词语之间是有关系的,例如爸爸的爸爸是我的爷爷,那么爷爷和我之间的关联是很紧密的,但是在one-hot编码中,从编码的结果看,爷爷和我之间没有任何关系。

torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None,
max_norm=None, norm_type=2.0, scale_grad_by_freq=False,
sparse=False, _weight=None)

  • num_embeddings (python:int) – 词典的大小尺寸,比如总共出现5000个词,那就输入5000。此时index为(0-4999)
  • embedding_dim (python:int) – 嵌入向量的维度,即用多少维来表示一个符号。
  • padding_idx (python:int, optional) – 填充id,比如,输入长度为100,但是每次的句子长度并不一样,后面就需要用统一的数字填充,而这里就是指定这个数字,这样,网络在遇到填充id时,就不会计算其与其它符号的相关性。(初始化为0)
  • max_norm (python:float, optional) – 最大范数,如果嵌入向量的范数超过了这个界限,就要进行再归一化。
  • norm_type (python:float, optional) – 指定利用什么范数计算,并用于对比max_norm,默认为2范数。
  • scale_grad_by_freq (boolean, optional) – 根据单词在mini-batch中出现的频率,对梯度进行放缩。默认为False.
  • sparse (bool, optional) – 若为True,则与权重矩阵相关的梯度转变为稀疏张量。
a = torch.LongTensor([0])
embedding = torch.nn.Embedding(2, 5)
print(embedding(a))
Out[29]: tensor([[1.7931, 0.5004, 0.3444, 0.7140, 0.3001]]

5、 LSTM进行训练
class torch.nn.LSTM(*args, **kwargs)

  • input_size:x的特征维度
  • hidden_size:隐藏层的特征维度
  • num_layers:lstm隐层的层数,默认为1
  • bias:False则bih=0和bhh=0. 默认为True
  • batch_first:True则输入输出的数据格式为 (batch, seq, feature)
  • dropout:除最后一层,每一层的输出都进行dropout,默认为: 0
  • bidirectional:True则为双向lstm默认为False输入:input, (h0, c0)输出:output, (hn,cn)
  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值