前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[L2]实战语言模型~数据batching

[L2]实战语言模型~数据batching

作者头像
触摸壹缕阳光
发布2020-05-28 19:07:36
6610
发布2020-05-28 19:07:36
举报

在一切变好之前,我们总要经历一些不开心的日子。

全文字数:2603字

阅读时间:10分钟

前言

由于在公众号上文本字数太长可能会影响阅读体验,因此过于长的文章,我会使用"[L1]"来进行分段。这个系列将主要借鉴《Tensorflow实战Google学习框架》这本书,主要介绍实现语言模型的一些前期准备,后期会出更详细的文章。

a

什么是 batching?

通常在优化目标函数的时候使用Mini-batch Gradient Descent算法,也就是Mini-batch梯度下降算法,这种梯度更新算法比Stochastic Gradient Descent(随机梯度下降算法,一个样本数据进行一次梯度更新)更加稳定,比Batch Gradient Descent(批量梯度下降法,一整个样本数据进行一个梯度更新)更新快。

虽然Mini-batch Gradient Descent稳定效率高,但是mini-batch给循环神经网络带来的很大的问题。因为在文本数据中,由于每个句子的长度不同,又无法像图像那样去调整到固定维度,而且在前期mini-batch的大小都是事先指定好了的,每一个批次的大小都是一样的。

这个时候就需要在对文本数据的batch操作的时候就需要采取一些特殊的处理了,目前有两种处理方案:

  1. 对于训练样本来说,每个句子通常是作为独立的数据来训练的,这个时候可以使用填充操作,就是将较短的句子补充到同一个batch中最长句子的相同长度,需要填充的地方使用"<pad>"进行标记;
  2. 对于训练样本来说,每个句子并非随意抽取的文本,而是在上下文之间有关联的内容,需要将前面句子的信息传递到后面的句子之中,为了实现这个目标,同行采用一个种batching的方法;

而我们的PTB的数据集就属于上下文之间有关联内容的数据,所以这里使用第二种的batching方法。

b

如何 batching

对于上下文之间有关联样本来说,最理想的当然就是把这些句子拼接起来,形成一个很长的一个句子,然后放在循环神经网络中进行训练,如下图所示:

▲将整个文档前后连接后的示意图

其中"A1A2A3","B1B2","C1C2C3C4"等分别代表一个句子。但是这种方式现实中并不能实现:

  1. 如果将整个文档都放入一个计算图中,循环神经网络将会被展开成一个很长很长(通常我们的训练样本很大)的前馈神经网络,这样会导致计算图变的异常的庞大,不方便调试和后期的维护,而且效率会变的很低;
  2. 序列过长会发生梯度爆炸的问题,不论是基本的RNN还是LSTM梯度都可能会发生梯度爆炸,虽然梯度爆炸的现象很明显而且能够通过梯度剪枝的方式进行处理,但是如果序列很长的话,误差曲线就会变的异常的陡峭,这个时候即使使用了梯度剪枝的方式,效果也不会变的太好;

不能使用整个序列作为样本,那么很自然就会想着把大的序列长度切割成固定长度的子序列。循环神经网络在处理完一个子序列后,它最终的隐藏状态将复制到下一个序列中作为初始值,这样在前向计算的时,效果等同于一次性顺序地读取了整个文档,而在反向传播的时候,梯度则只在每个子序列内部传播,如下图所示:

▲按长度3切分整个文档

需要注意:

  1. 每一个循环神经网络都是不同的神经网络,也就是权重参数并不相同;
  2. 每一个循环神经网络都有一个loss,但是并不合起来,因为梯度更新的时候,只在每个子序列内部进行更新,不会传递到相邻的子序列之中去;

上面只解决了上下文连续的问题,但是我们知道使用Mini-batch进行处理的好处是可以利用计算的并行能力,我们希望每一个计算可以对多个句子进行并行处理。

解决的方案:

  1. 将整个文档切分成batch_size个连续段落;
  2. 让每一个小的mini-batch负责batch_size个段落中的一小部分;

这个地方可能不太好理解,下面我用一个简单的numpy数组来说明batching:

代码语言:javascript
复制
import numpy as np

batch_num = 2

batch_size = 3
batch_step = 2

#(3,2*2)
array = np.arange(12).reshape(batch_size,batch_num * batch_step)
array2 = np.split(array,batch_num,axis = 1)

print(array)
print(array2)

▲通过numpy数组理清关系

我们继续来看对PTB数据进行batching的代码:

代码语言:javascript
复制
TRAIN_BATCH = 20
TRAIN_NUM_STEP = 35

#从文件中读取数据,并返回包含单词编号的数组
def read_data(file_path):
    with open(file_path,"r") as fin:
        #将整个文档读进一个长字符串.
        id_string = " ".join([line.strip() for line in fin.readlines()])
    #将读取的单词编号转换为整数
    id_list = [int(w) for w in id_string.split()]
    return id_list

def make_batches(id_list,batch_size,num_step):
    #计算总的batch的数量。每个batch包含的单词数量是batch_size * num_step
    num_batches = (len(id_list) - 1) // (batch_size * num_step)

    #将数据整理成一个维度为[batch_size,num_batches * num_step]的二维数组
    data = np.array(id_list[:num_batches * batch_size * num_step])
    data = np.reshape(data,[batch_size,num_batches * num_step])
    #沿着第二个维度将数据切分成num_batches个batch,存入一个数组
    data_batches = np.split(data,num_batches,axis = 1)

    #重复上述的操作,但是每个位置向右移动一位,这里得到的是RNN每一步输出所需要
    # 预测的下一个单词
    label = np.array(id_list[1:num_batches * batch_size * num_step + 1])
    label = np.reshape(label,[batch_size,num_batches * num_step])
    label_batches = np.split(label,num_batches,axis = 1)
    #返回一个长度为num_batcher的数组,其中每一项包括一个data矩阵和一个label矩阵。
    return list(zip(data_batches,label_batches))

batching的流程:

  1. 将整个数据存放到一个list中,也就是将整个文档变成一个句子;
  2. 设置batch_size也就是每一次并行处理的数量,设置num_step也就是步长,简单理解就是循环神经网络展开的长度;
  3. 计算遍历完整个句子(文档)需要的次数(这里需要的是整数)num_batches ,也可以认为这个句子(文档)可以分解成多少个(batch_size, num_step);
  4. 然后将句子分割成num_batches个(batch_size, num_step)。

我们需要构建的是循环神经网络的语言模型,模型输入和输出的基本单元都是单词,很明显是有监督的模型,所以不仅需要制作data还需要制作标签label。语言模型输入一个词预测输出下一个词的概率,所以在构建训练集的时候只需要将样本往后移动一个单词即可。当然不论是制作data还是label都需要使用batching。

继续用上面那个numpy数组的例子,使用batching制作label:

▲使用batching制作label

有了data和label,就可以构建训练样本了:

▲制作好的训练样本

通过numpy数组简单例子的类比可以很容易理解对文本数据的batching操作。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI机器学习与深度学习算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
NLP 服务
NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档