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

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

一、RNN

下图是RNN模型的结构图

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

上图的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 )=σ(W h ​h t −1 +W e ​e (t )+b 1 ​
那么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 )=σ(W h ​h 0 +W e ​e (1 )+b 1 ​)
h ( 0 ) h^{(0)}h (0 )可以随机初始化,即h ( 0 ) h^{(0)}h (0 )与W h W_h W h ​相乘之后加上e ( 1 ) e^{(1)}e (1 )与W e W_e W e ​相乘的结果,得到了中间变量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 )=s o f t m a x (U h (t )+b 2 ​)

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

下面图是RNN 的训练模式:

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

例如我们要训练一句话”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 )=σ(W h ​h t −1 +W e ​e (t )+b 1 ​
然后经过下面的公式获得概率分布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 )=s o f t m a x (U h (t )+b 2 ​)
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)L o s s =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各种门的意义:

新手入坑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 )是隐藏层
新手入坑LSTM-----如何一步一步进行文本训练
X t X_t X t ​进入之后和h t − 1 h_{t-1}h t −1 ​一起根据公式计算出f t f_{t}f t ​,i t i_{t}i t ​,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

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

三、实操训练LSTM

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

1、 准备训练数据文本库:
例如 Flickr8K数据集,8000 图像, 每幅图5个标题, 描述图像里面的事物和事件

新手入坑LSTM-----如何一步一步进行文本训练
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 = [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)

Original: https://blog.csdn.net/weixin_45209433/article/details/120524169
Author: 仙女修炼史
Title: 新手入坑LSTM—–如何一步一步进行文本训练

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/531199/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球