어떻게 플라이 패와 Bengio 고전 신경망 모델 언어를 달성하기 위해?

그냥 등등 프라이머 NN4NLP 골드버그 특별 바, 스탠포드 cs224n의 학습 후, 시작 깊이 학습 및 자연 언어 처리 (NLP)을 얻기뿐만 아니라 무제한 플레이의 아이디어는, 그것의 시리즈를 쓰고 있지만,이 문제의 나머지 부분을 보자.
최근 NLP 필드 큰 사전 교육 모델 때문에 많은 연구가 ERNIE 2.0, 영어 임무 (16)의 총에하여 BERT 이상 모델과 XLNet을 이해하는 등 바이두 새로운 릴리스 지속적인 학습의 의미 프레임 워크와 같은 컴퓨팅 리소스 (많이 필요, SOTA 효과를 만들어 ), 이러한 프로젝트는 화상을 기본적으로 작은 작은 가구 목록을 새로 고치 코드를 해제, 그는 천진난 만하게 거물 기다리고 있도록 서류를 발급, 감당할 수없는입니다. 그러나 그것은 또한 요약 할 수있는 좋은 기회를 의미하고, 플러스 추가 푸시, 그들은 다시 생각을했다.

현대 NLP를 소개합니다이 시리즈는 나는 그들의 구현 및 설명을 모두 포함하여 가장 중요한 주제를 생각한다.

여기에 패들 (PaddlePaddle)를 비행 바이 오픈 소스 플랫폼을 깊이 학습을 사용,이 시점에, 몇 가지 이유가있다.

우선, 얼마 전에, 기술 미디어 친구, 미국 기업이 봉쇄 깊은 같은 주류 Tensorflow 및 Pytorch로, 프레임 워크를 학습 할 수 있는지 우리에게 이야기하고 대답은 결국 내가 할 수있는 어쩌면이다, 때문에 화웨이 이벤트 차단되었습니다, 구글은 심지어 특허를 적용 할 수 드롭 아웃. 그것은 한 권한으로 업데이 트 이러한 프레임 워크를 사용하지 않는 변경 후에는 그가 국내 바이두는 패들 비행을위한 프레임 워크를 찾을 생각할 수 있도록 우리가 할 수단이 없다 추정된다.

노 PaddleNLP은 내용이 매우 풍부 보였다 비행, 패들 NLP 비행의 느낌이 지원은 매우 좋은 관심의 가치가있다.

프로젝트 주소 :
https://github.com/PaddlePaddle/models/tree/develop/PaddleNLP

언어 모델

핵심 언어는 NLP의 발전에 큰 도움을 가져왔다 한 손으로 NLP (언어 모델), 당신은 어디서나 그것을 말할 수있는 현대 필드의 모델, 그것은 여러 분야의 핵심 부분이지만, 다른 한편으로는, 같은도 패배 샤오는 사실, 모델 언어는 양방향 언어 모델을 구하는 방법에 대한 혁신적인 생산적인 작업에 대한 예를 들어 NLP의 개발뿐만 아니라 정보를 제한합니다.

즉, 언어 모델이 무엇인지 결국?

언어 모델은 무엇입니까

그림 삽입 설명 여기
언어는 인기가 말하는 판단 문장, 단어를 말하기의 공식적인 지점의 확률을 계산 한 후,이 확률의 값이 얼마나 많은 종이 확률이 정상의 조각입니다 인간 표시되지 않는다 (심각한 얼굴)의 모델, 농담, 언어 모델은 사실이다 텍스트입니다.

얼굴이 문장 출시와 예를 들어, 단어의 경우, "오 모양을, 그가 유죄 지방을 볼 수있는 지점을 만들어,"사람들처럼, 다음 그래서 인간 음성의 확률이 작은 결정이 언어 모델이 아닌 것이 분명하다. 그리고 매우 일반적인 말 : "예, 감사는"언어 모델은 상대적으로 높은 확률 점수를 제공합니다.

수학적 방법은 같은 언어 모델 확률을 얻기 위해, 필요를 표현하기 :

그림 삽입 설명 여기
X 문장, X1, X2를 나타냅니다 ... 문장은 단어를 나타냅니다. 그것의 같은 확률을 계산하는 방법, 더 잔인한 방법은 매우, 매우 큰 신체를 가지고있다, 문장의 다양한있다, 우리는 다른 문장의 확률을 계산하는 숫자를 가지고 있지만이를 알고 조금 그것에 대해 생각 문장 조합은 무한하기 때문에 방법은 불가능합니다.

조건부 확률과 화학식 체인 규칙 시퀀스 오른쪽 왼쪽에서 문장을 사용하여 더 계산이를 수식으로 변환 될 수있다 :

그림 삽입 설명 여기
앞의 모든 낱말들, 지금은 다음 단어 물론, 문제를 예측하는 방법에 따라 여전히 복잡 조금, 다음 RNN 모델을 계산하지만 지금은하자에 대한의 그래서 궁리를 기반으로, 더 큰 자사의 단기 중요성에서 단어를 추측 할 수 있습니다 마르코프 가정은 단지 N-1 단어의 전면에 의존하는 기간은,이 경우의 언어 모델은 N 그램 언어 모델이라고한다.

예를 들어, 다음 단어를 예측하기 이전 두 단어를 기준으로 3 그램 (트라이 그램) 언어 모델입니다 :

그림 삽입 설명 여기더 조심하고, 발견 할 것이다 그 때 더 가깝게 원래의 언어 모델 확률 방정식 N 증가의 n g.

n이 너무 큰 경우, 순서를 계산하는 것은 더 이상 단어 N-g 테이블이 너무 큰 것 계산에되기 때문에 물론, N, 더 나은 아니라 더 큰, 그것은 차원의 저주 (차원의 저주) 소위로 이어질 것입니다. 그래서 일반적으로는 3,4,5 부근에서 N의 크기를 취할 것입니다.

조기 구현 : 알고 계산

초기의 이해 계산 유사한 언어 모델의 확률은, 학교 어려운 정보 이론 클래스로 알려진, 교사 통신의 강력 암웨이 섀넌 고전적인 종이 수학적 이론, 그가 대학원 수준의 언어 모델의 유사한 계산을 사용하여 섹션을 준 한 종이 확률 방법은 텍스트를 생성합니다.

그림 삽입 설명 여기
하나는 바이그램 언어 모델 A의 당량을 갖는 빈도 테이블을 생성하는 2 그램 (바이그램)이다.

그림 삽입 설명 여기

이와 유사하게, 가장 중요한 작업은 N-g 주파수를 계산하기 위해 많은 양의 텍스트를 기반으로, 이러한 N 그램 언어 모델을 구축합니다.

이 과정 작업이 먼저 일부 영어 텍스트를 준비하는 것입니다, 그리고 다음 언어 모델의 확률로 나눈 N-g의 다음 하나 하나 수는 총 수의 추정치를 계산하는 데 필요한,이 방법은 카운트 기반 언어 모델이라고합니다.

NLP는 기존의 언어 모델에 내장하면 해당 같다, 물론, 같은 알고리즘을 부드럽게 같은 더 능력, 특정 교수 Jurafsky 책과 과정을 참조 할 수 있습니다.

그러나이 방법은 신경망 모델 언어가 여기에 실현하면서, 차원의 저주 앞서 언급하는 큰 문제가 될 것입니다 (신경망 언어 모델), 학습을 통해 배포 신경 네트워크를 사용하여 언어 모델을 구축하는 것입니다 (즉, 용어 벡터) 방법에 대한 말씀은이 문제를 해결합니다.

언어 모델을 수행 할 수 있습니다

그러나 언어 신경망 모델에 대해 이야기하기 전에, 우리는 언어 모델의 사용을 살펴.

앞서 언급 한대로 그건 사용이 무엇인지, 언어 모델은 모든 곳에서 현대의 핵심 NLP 중 하나라고 할 수 있습니다. 예를 들어, 초기 언어 모델의 부산물로 간주 단어 벡터; 동안 디코더도 호출 할 수있는 순서 (seq2seq) 모델, 조건부 언어 모델 (조건부 언어 모델)에 고전 순서, 주로 지금 사전 소방 훈련 모델, 작업은 언어 모델이다.

NLP의 실제 응용 프로그램에서, 나는 다음과 같은 세 가지로 요약 할 수 있다고 생각합니다 :

첫째, 정렬, 득점을 선고합니다. 먼저 텍스트의 큰 숫자에 대한 교육, 그리고 그들은 문장의 품질을 평가하기 위해 언어 모델을 얻을 수 있습니다. 결과 중 일부는 큰 정도 재주문 인덱스 증가, 기계 번역을 생성 할 때 언어 능력의 조합이 후보에 의해 생성 된 결과를 재정렬 모델 손실이된다 유용합니다.

第二,用于文本生成。首先其训练方式是根据前面词,生成之后词。于是只要不断重复此过程(自回归)就能生成长文本了。比较有名的例子就包括最近的 GPT2,其标题就叫 “ Better Language Models and Their Implications.” 它生成的句子效果真的非常棒,可以自己体验一番 https://talktotransformer.com/.

그림 삽입 설명 여기
第三,作为预训练模型的预训练任务。最近很火的预训练模型,几乎都和语言模型脱不开关系。

比如说 ELMo 就是先训练双向 LSTM 语言模型,之后双向不同层向量拼接获得最后的 ELMo词向量,还有 BERT 里最主要的方法就是 Masked Language Model (遮掩语言模型)。

而最近的 XLNet 中最主要训练任务也叫做 Permutation language Model (排列语言模型),可见语言模型在其中的重要性重要性。

神经网络语言模型架构

接下来简单介绍一下这里要实现的网络结构,借鉴自 Bengio 的经典论文 A Neural Probabilistic Language Model 中的模型。

그림 삽입 설명 여기
这里我们训练 Tri-gram 语言模型,即用前面两个词预测当前词。

于是输入就是两个单词,然后查表取出对应词向量,之后将两个词向量拼接起来,过一个线性层,加入 tanh 激活函数,最后再过线性层输出分数,通过 softmax 将分数转换成对各个词预测的概率,一般取最大概率位置为预测词。

用公式表达整个过程就是:

그림 삽입 설명 여기
整个结构非常简单,接下来就来看看如何用 飞桨来实现这个结构吧,同时介绍以下 飞桨的基本思想,和一般训练流程。

项目地址:
https://github.com/PaddlePaddle/models/tree/develop/PaddleNLP/language_model

飞桨代码基本实现

这里拿一个小例子来解说,假设我们在一个叫做 PaddlePaddle 的世界,这个世界的人们只会说三句话,每句话三个词,我们需要建立一个 Tri-gram 语言模型,来通过一句话前两个词预测下一个词。

关于整个流程,主要分成准备,数据预处理,模型构建,训练,保存,预测几个阶段,这也是一般一个 NLP 任务的基础流程。

准备

首先,先导入需要的库。

import numpy as np 
import paddle 
import paddle.fluid as fluid

之后准备训练数据与词表,统计所有不同词,建立词表,然后按照顺序建立一个单词到 id 的映射表和配套的 id 到单词映射表。因为模型无法直接读这些词,所以需要单词与 id 之间的转换。

# 假设在这个叫做PaddlePaddle的世界里,人们只会说这三句话 
sentences = ["我 喜欢 Paddle", "Paddle 等于 飞桨", "我 会 Paddle"]  

vocab = set(' '.join(sentences).split(' ')) # 统计词表 
word2idx = {w: i for i, w in enumerate(word_list)} # 建立单词到id映射表 
idx2word = word_list # id到单词的映射表 
n_vocab = len(word2idx) # 词表大小

准备好数据后,设置模型参数和训练相关参数,因为任务很简单,所以参数都设很小。

# 参数设置 
# 语言模型参数 
n_step = 2 # 输入前面多少个词,tri-gram 所以取 3-1=2 个 
n_hidden = 2 # 隐层的单元个数 

# 训练参数 
n_epochs = 5000 # 训练 epoch 数 
word_dim = 2 # 词向量大小 
lr = 0.001 # 学习率 
use_cuda = False #用不用GPU

数据预处理

根据飞桨数据输入要求,需要准备数据读取器 (reader),之后通过它来读取数据,对输入数据进行一些前处理,最后作为 batch 输出。

def sent_reader(): 
    def reader(): 
        batch = [] 
        for sent in sentences: 
            words = sent.split(' ') 
            input_ids = [word2idx[word] for word in words[:-1]] # 将输入转为id 
            target_id = word2idx[words[-1]] # 目标转为id 
            input = np.eye(n_vocab)[input_ids] # 将输入id转换成one_hot表示 
            target = np.array([target_id])  
            batch.append((input, target)) 
        yield batch 
    return reader

构建模型

这里从飞桨中较底层 API 来进行构建,理解更透彻。先创建所需参数矩阵,之后按照前面的公式来一步步运算。

def nnlm(one_hots): 
    # 创建所需参数 
    # 词向量表 
    L = fluid.layers.create_parameter(shape=[n_vocab, word_dim], dtype='float32') 
    # 运算所需参数 
    W1 = fluid.layers.create_parameter(shape=[n_step*word_dim, n_hidden], dtype='float32') 
    b1 = fluid.layers.create_parameter(shape=[n_hidden], dtype='float32', is_bias=True) 
    W2 = fluid.layers.create_parameter(shape=[n_hidden, n_vocab], dtype='float32') 
    b2 = fluid.layers.create_parameter(shape=[n_vocab], dtype='float32', is_bias=True) 
    # 取出词向量 
    word_emb = fluid.layers.matmul(one_hots, L) 
    # 两个词向量拼接 
    input = fluid.layers.reshape(x=word_emb, shape=[-1, n_step*word_dim], inplace=True) 
    # 前向运算 
    input2hid = fluid.layers.tanh(fluid.layers.matmul(input, W1) + b1) # 输入到隐层 
    hid2out = fluid.layers.softmax(fluid.layers.matmul(input2hid, W2) + b2) # 隐层到输出 
    return hid2out

先根据输入的独热(one-hot)向量,取出对应的词向量,因为每个例子输入前两个词,因此每个例子可获得两个词向量,之后按照步骤,将它们拼接起来,然后与 W1 和 b1 进行运算,过 tanh 非线性,最后再拿结果与 W2 和 b2 进行运算,softmax 输出结果。

接下来构建损失函数,我们用常用的交叉熵(cross-entropy)损失函数,直接调 API。

def ce_loss(softmax, target): 
    cost = fluid.layers.cross_entropy(input=softmax, label=target) # 计算每个batch的损失 
    avg_cost = fluid.layers.mean(cost) # 平均 
    return avg_cost

开始训练

终于进入了训练环节,不过为了更好理解,先稍稍介绍一点 飞桨的设计思想。

飞桨同时为用户提供动态图和静态图两种计算图。动态图组网更加灵活、调试网络便捷,实现AI 想法更快速;静态图部署方便、运行速度快,应用落地更高效。

如果想了解飞桨动态图更多内容,可以参考GitHub项目地址:https://github.com/PaddlePaddle/models/tree/v1.5.1/dygraph

实际应用中,静态图更为常见,下面我们以静态图为例介绍一个完整的实现:

首先,需要先定义 Program,整个 Program 中包括了各种网络定义,操作等等,定义完之后,再创建一个 Executor 来运行 Program,用过类似框架的同学应该并不陌生。

因此先来看看这两行代码,fluid 中最重要的两个 Program,将它们取出来

startup_program = fluid.default_startup_program() # 默认启动程序 
main_program = fluid.default_main_program() # 默认主程序

default_startup_program 主要定义了输入输出,创建模型参数,还有可学习参数的初始化;而 default_main_program 则是定义了神经网络模型,前向反向,还有优化算法的更新。

之后将之前定义好的一些模块放入训练代码中。

train_reader = sent_reader() # 获取数据 reader 

# 定义输入和目标数据 
input = fluid.layers.data(name='input', shape=[-1, n_step, n_vocab], dtype='float32') 
target = fluid.layers.data(name='target', shape=[-1, 1], dtype='int64') 

# 输入到模型,获得 loss 
softmax = nnlm(input) 
loss = ce_loss(softmax, target)
之后还需要定义优化器(Optimizer),还有数据 Feeder 用于喂入数据。
# 配置优化器 
optimizer = fluid.optimizer.Adam(learning_rate=0.001) # 万金油的 Adam 
optimizer.minimize(loss) 

# 用于之后预测 
prediction = fluid.layers.argmax(softmax, axis=-1) 

# 定义 Executor 
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() # 指定运行位置 
exe = fluid.Executor(place) 

#定义数据 Feeder 
feeder = fluid.DataFeeder(feed_list=[input, target], place=place) # 每次喂入input和target
至此就完成了第一步的定义环节,然后就可以用定义的 Executor 来执行程序了。
# 参数初始化 
exe.run(startup_program) 

# 训练 
for epoch in range(n_epochs): 
    for data in train_reader(): 
        metrics = exe.run( 
            main_program, # 主程序 
            feed=feeder.feed(data), # 数据喂入 
            fetch_list=[loss]) # 要取出的数据 
        if epoch % 500 == 0: 
            print("Epoch {}, Cost {:.5f}".format(epoch, step, float(metrics[0][0])))

简单解释一下代码,训练时需要exe.run来执行每一步的训练,对于run需要传入主程序,还有输入 Feeder,和需要拿出来(fetch)的输出。
之后运行就能看到训练 log 了。

그림 삽입 설명 여기
能明显看到 loss 在不断下降,等训练完成,我们就获得一个训练好的模型。

保存模型

在预测前可以尝试先保存一个模型,可以便于之后使用,比如 load 出来做预测。

fluid.io.save_inference_model('./model', ['input'], [prediction], exe)

很简单,只需要传入保存的路径’./model’,预测需要 feed 的数据’input’,之后需要 fetch 出的预测结果 prediction,最后加上执行器 exe,就 OK 了。

非常快。

预测阶段

预测阶段其实和训练阶段类似,但因为主程序都保存下来了,所以只用先建立执行器 Executor,同时建立一个用于预测的作用域。

infer_exe = fluid.Executor(place) # 预测 Executor 
inference_scope = fluid.core.Scope() # 预测作用域

然后在预测作用域中 load 出模型,进行预测运算,大部分操作都和训练很类似了。唯一不同就是 load 模型这块,其实就是把之前保存下来的参数给 load 出来了,然后用于预测。

with fluid.scope_guard(inference_scope): 
    [inference_program, feed_target_names, 
     fetch_targets] = fluid.io.load_inference_model('./model', infer_exe) # 载入预训练模型 

    infer_reader = sent_reader() # 定义预测数据 reader 

    infer_data = next(infer_reader()) # 读出数据 
    infer_feat = np.array([data[0] for data in infer_data]).astype("float32") 

    assert feed_target_names[0] == 'input' 
    results = infer_exe.run(inference_program, 
                            feed={feed_target_names[0]: infer_feat}, 
                            fetch_list=fetch_targets) # 进行预测

结果如何?

for sent, idx in zip(sentences, results[0]):
    print("{} -> {}".format(' '.join(sent.split()[:2]), idx2word[idx]))
我 喜欢 -> Paddle
Paddle 等于 -> 飞桨
我 会 -> Paddle

模型完美地学习到了 PaddlePaddle 世界中仅有的几个 trigram 规则,当然因为该任务非常简单,所以模型一下就能学会。

更多尝试

在了解完以上这个小例子之后,就能在它基础上做很多修改了,感兴趣的同学不妨拿下面的几个思路作为练习。

더 많은 모델과 대용량 데이터 세트, 훈련을 함께 예를 들어, 종이 Bengio 스케일 모델, 대략 유사한 구조를 재현 해 봅니다 단지 크기 매개 변수를 수정할 수 있습니다.

깊은 API를 사용하여 네트워크 구조를 구축하기 위해 본원에 사용될 때 많은 플라이 패들 사용 API 용이이 있지만 또한 예를 들어, 직접적으로, 합을 곱한 매트릭스 중량을 만들 재 구축 이러한 API 호출 모델 그 여부 예를 들어, 워드 벡터 부분이 fluid.layers.embedding 단어 ID를 직접 얻을 수 있으며, 상기 연결 층은 당 전체로서 직접 직접 매우 편리 할 수 ​​fluid.layers.fc 활성화 기능 설정 파라미터를 달성하기 위해 사용될 수있다 .

사실, 여기에 당신은 또한 softmax를 전체 무게 W2 워드 벡터 테이블뿐만 아니라 직접 출력 부에 연결 퍼가기 언급 Bengio 종이 추가 유사한 잔류 연결하기 전에 연결 층을 공유 할 수있는 권리와 같은 일부 작은 기술을 시도 할 수 있습니다.

신경망 모델의 언어가 여기에 제시하고, 패들 비행하여 간단한 작은 예제를 달성하기 위해, 주로 그것이 싶지 :

첫째, 언어 모델 작업을 먼저 소개하고 싶은, NLP의 분야에서 매우 중요하다;

둘째, 본 논문 Bengio 언어 신경망 모델은 단어 후 리드를 치고 신경 네트워크를 사용하여 구현 언어 제안 된 모델뿐만 아니라 재생을 통해 문제 "차원의 저주"에 대한 단어를 해결하기 위해 제안하는 첫번째로, 아주 고전 벡터,이 seq2seq 및 다른 주제;

셋째, 간단한 예제를 통해 이러한 플라이 패를 달성하기 위해, 그 다음 옆으로 다양한 모델과 데이터의 복잡성, 비행 피치 프로그램 내장 방식의보다 직관적 인 이해를 넣어 비행 피치를 설명하는 더 복잡한 절차를위한 기반을 마련 할 수 있습니다.

더 플라이 패들 더 관련 콘텐츠에 대한 내용은 다음 링크를 텍스트를 읽거나 볼 수있는 텍스트의 끝을 클릭하십시오
https://github.com/PaddlePaddle/models/tree/develop/PaddleNLP

게시 된 116 개 원래 기사 · 원 찬양 한 · 전망 4574

추천

출처blog.csdn.net/PaddleLover/article/details/103820363