フライパドル付Bengio古典的なニューラルネットワークモデルの言語を達成するためにどのように?

ただ、その上にプライマーNN4NLPゴールドバーグの特別なバー、スタンフォード大学のcs224nの学習と後に、開始深学習と自然言語処理(NLP)を取得するだけでなく、無限の遊びのアイデアは、それのシリーズを書くために、彼らは問題の残りをしましょう。
大型事前研修モデルなぜなら最近、NLPの分野、研究の多くは、このようなSOTA効果を作った英語の使命でERNIE 2.0、16の合計のBERTとXLNetを超えモデルを理解するためのBaiduの新しいリリースで継続的な学習の意味論的枠組みとして、コンピューティングリソース(の多くを必要と)は、そのようなプロジェクトが火傷で基本的に、小さな小さな世帯がリストを更新し、コードをリリース、彼は無邪気に大物を待っているように、書類を発行し、余裕がないのです。しかし、それはまた、総括する良い機会に加え、余分なプッシュを意味し、彼らは再びアイデアを果たしました。

このシリーズは、私が彼らの実装と説明の両方を含む最も重要なトピックを、考えて近代的なNLPをご紹介します。

ここでパドル(PaddlePaddle)を飛ぶことを学ぶBaiduのオープンソースプラットフォームの深さを使用することになり、この点について、いくつかの理由があります。

まず、ない長い前に、技術、メディアの友人は、アメリカの企業が遮断が深いな主流TensorflowとPytorchとして、フレームワークを学ぶかどうか、私たちに話をし、答えは、すべての後、私は、何ができるかもしれないです、理由Huawei社のイベントのブロックされました、特許を申請することができGoogleはさえドロップアウト。それは限り許可と更新にこれらのフレームワークを使用しないように変更した後、彼が、国内Baiduはパドルを飛ぶためのフレームワークを見つけるために考えることができますので、我々は、手段を持たないと推定されます。

パドルPaddleNLPは内容が非常に豊富に見え飛ぶために、飛んでパドルNLPの気持ちは、このサポートは注目に値する、非常に良いです。

プロジェクト住所:
https://github.com/PaddlePaddle/models/tree/develop/PaddleNLP

言語モデル

コア言語は、それがNLPの発展に大きな後押しをもたらした一方でNLP(言語モデル)、あなたは、どこでもそれを言うことができるの近代的な分野のモデルであり、それは多くの分野の重要な部分であるが、一方で、としても敗北しますシャオは、実際には、モデルの言語はまた、例えば、革新的な生成的なタスクだけでなく、双方向言語モデルを入手する方法についての情報に、NLPの開発を制限します。

その言語モデルが何であるかを最終的には?

言語モデルとは何ですか

ここに画像を挿入説明
言語は、(真面目な顔)のモデル、ジョーク、言語モデル、実際に人気話す判定文であるが、人間ではないですその単語を話すの正式なポイントの確率が計算され、この確率の値は、どのくらいの紙の確率は通常の一部であることを示していますテキスト。

言葉には、例えば、顔が文ロールアウトで:人のようではないことは明らかである「ああ見て、彼は有罪脂肪を見るためにポイントを作った」、そして人間の音声の確率は小さいと判断するために、言語モデルです。そして、非常に一般的なことわざ:「はい、ありがとうございましたが、」言語モデルは、比較的高い確率スコアを与えるでしょう。

表現する数学的な方法は、そのような言語モデル確率を取得する必要があります。

ここに画像を挿入説明
Xは、文、X1、X2を表し...文は単語を表しています。それのようにAの確率を計算する方法を、より多くの残忍な方法は非常に、非常に大規模コーパスを持つことである、文の様々ながある、そして我々は、異なる文の確率を計算するための番号を持っているが、このことを知っているために少しそれについて考えます文の組み合わせは無限大ですので、この方法は、可能ではありません。

条件付き確率式チェーン・ルールを使用してよりよい計算は、左から右の順に文章のためには、式に変換することができます。

ここに画像を挿入説明
前のすべての単語は、次の単語を予測する方法によると、当然のことながら、のための問題は今も複雑な少しは、その後、RNNモデルを計算するために使用することができますが、今のところのはとてもマルに基づいて大規模のその短期的な重要性から単語、のために仮定しましょうマルコフの仮定は、唯一のN-1ワードの前面に依存用語は、この場合、言語モデルは、N-gram言語モデルと呼ばれます。

例えば、次の単語を予測するために以前の二つの単語に基づいて、3グラム(トライグラム)言語モデルです。

ここに画像を挿入説明もっと慎重に、そして、より近い元の言語モデル確率方程式に、n個の増加の際にnグラムことがわかります。

nが大きすぎると、シーケンスを計算すると、長い単語nグラム・テーブルが大きすぎることになる計算になるのでもちろん、nは、良くない大きいです、それは寸法の呪い(次元の呪い)、いわゆるにつながります。だから、一般的には3,4,5の近くで、nの大きさになります。

初期の実装:知って数えます

最古の理解計算似た言語モデルの確率は、学校の最も困難な情報理論のクラスとして知られていた、教師のコミュニケーションの強力アムウェイシャノン古典的な論文A数学理論、彼は大学院レベルでの言語モデルの同様の計算を使用してセクション与えた紙いくつかのテキストを生成する確率方法。

ここに画像を挿入説明
一つは、バイグラム言語モデルAと同等のものを有する頻度テーブルを生成するために、2グラム(バイグラム)です。

ここに画像を挿入説明

同様に、N-gram言語モデルを構築するために、最も重要な仕事は、nグラム頻度をカウントするために大量のテキストに基づいています。

仕事は最初にいくつかの英語のテキストを用意して、その後、言語モデルの確率で割ったnグラムの数は、この方法はカウントベースの言語モデルと呼ばれ、合計数の推定値を計算するために必要な1つずつあるのコースがありました。

伝統的な言語モデルに建てられた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を達成するために使用することができ、活性化機能設定パラメータに直接達成することができます。

実際には、ここであなたはまた、そのようなソフトマックスフル重量W2ワードベクタテーブルだけでなく、直接出力部に接続埋め込む言及Bengio紙追加同様の残留接続する前に、接続層を共有する権利など、いくつかの小さなスキルを試すことができます。

ここで紹介するニューラルネットワークモデルでは、言語、およびパドルを飛ぶことにより、簡単な小さな例を達成するために、主にそれをしたいです。

まず、言語モデルのタスクは、NLPの分野で非常に重要である、最初に紹介したいと思います。

第二には、この論文Bengio言語ニューラルネットワークモデルは、このような実装言語として、非常に古典的な単語の後にリードを破って、再現を通じて、問題のニューラルネットワークを使用してモデルを提案するだけでなく、「次元の呪い」の言葉を解決することを提案する最初のベクトル、そこseq2seqおよび他のトピック。

第三には、簡単な例を挙げて、このようなフライパドルを達成するために、それはさておき、様々なモデルやデータの複雑さを置くことが可能である、浮上ピッチプログラムが構築された方法のより直感的な理解は、その後、浮上ピッチを説明するために、より複雑な手続きのための基礎を築きます。

:フライパドル複数の関連コンテンツの詳細については、テキストを読んだり、以下のリンクを参照するには、テキストの末尾をクリックしてください
https://github.com/PaddlePaddle/models/tree/develop/PaddleNLPを

公開された116元の記事 ウォンの賞賛1 ビュー4574

おすすめ

転載: blog.csdn.net/PaddleLover/article/details/103820363