使用PaddleFluid和TensorFlow训练序列标注模型

专栏介绍:Paddle Fluid 是用来让用户像 PyTorch 和 Tensorflow Eager Execution 一样执行程序。在这些系统中,不再有模型这个概念,应用也不再包含一个用于描述 Operator 图或者一系列层的符号描述,而是像通用程序那样描述训练或者预测的过程。

本专栏将推出一系列技术文章,从框架的概念、使用上对比分析 TensorFlow 和 Paddle Fluid,为对 PaddlePaddle 感兴趣的同学提供一些指导。

上一篇我们通过 RNN 语言模型初识 PaddleFluid 和 TensorFlow 中的循环神经网络模型。了解了:

  • 在 PaddleFluid 和 TensorFlow 平台下如何组织序列输入数据;

  • 如何使用循环神经网络单元;

  • 使用中的注意事项。

可以看到 PaddleFluid 中的各种循环神经网络单元都直接支持非填充序列作为输入,用户在使用时无需对 mini-batch 中的不等长序列进行填充,无需关心填充位是否会对代价(loss)计算产生影响,从而需要在计算损失时对填充位置进行过滤这样的细节,对使用来说无疑是十分方便的。 

循环神经网络的是深度学习模型中最为重要的一部分,这一篇我们以序列标注任务为例将会构造一个更加复杂的循环神经网络模型用于命名实体识别任务。我们的关注点始终放在:在两个平台下:(1)如何组织序列数据;(2)如何使用序列处理单元(不限于循环神经网络)。

这一篇会看到: 

1. PaddleFluid Data Feeder vs. 使用 TensorFlow r1.4 之后 release 的 Dataset API 读取数据; 

2. 在 PaddleFluid 和 TensorFlow 中,使用条件随机场(Conditional Random Field,CRF)单元; 

3. 在 PaddleFluid 和 TensorFlow 中,通过数据并行方式使用多块 GPU 卡进行训练。

如何使用代码

本篇文章配套有完整可运行的代码, 请随时从 github [1] 上获取最新代码。代码包括以下几个文件:

在执行训练任务前,请首先在终端执行下面的命令进行训练数据下载以及预处理。

sh download.sh

在终端运行以下命令便可以使用默认结构和默认参数运行 PaddleFluid 训练序列标注模型。

python sequence_tagging_fluid.py

在终端运行以下命令便可以使用默认结构和默认参数运行 TensorFlow 训练序列标注模型。

python sequence_tagging_tensorflow.py

背景介绍

序列标注和命名实体识别

序列标注是自然语言处理任务中的重要基础任务之一。常见的分词,词性标注,语义角色标注,命名实体识别,甚至自动问答(QA)都可以通过序列标注模型来实现。这一篇我们将训练一个序列标注模型完成命名实体识别的任务。

我们先来看看,什么是序列标注问题呢?请看下面一幅图:

▲ 图1. 序列标注问题

序列标注任务是为一个一维的线性输入序列中的每个元素打上标签集合中的某个标签。在上面的例子中,序列标注就是为图像序列中的每个元素贴上一个描述它们形状的标签。而序列标注任务的难点在于:序列中 元素的标记和 它们在序列中的位置密切相关。 

那么, 什么是命名实体识别呢?命名实体识别(Named Entity Recognition,NER)又称作“专名识别”,是指识别文本中具有特定意义的实体,主要包括:人名、地名、机构名、专有名词等。

BIO 表示法 

序列标注任务一般都会采用 BIO 表示方式来定义序列标注的标签集,B 代表句子的开始,I 代表句子中间,O 代表句子结束。通过 B、I、O 三种标记将不同的语块赋予不同的标签,例如:对于一个标记为 A 的命名实体,将它所包含的第一个语块赋予标签 B-A,将它所包含的其它语块赋予标签 I-A,不属于任何命名实体的语块赋予标签 O。图 2 是用 BIO 表示标注序列中命名实体的具体示例。

▲ 图2. BIO标注方法示例

模型概览

图 3 是本篇模型的模型结构概览。 

▲ 图3. 序列标注模型结构概览

我们要训练的序列标注模型,接受:一个文本序列作为输入,另一个与输入文本序列等长的标记序列作为学习的目标。首先通过上一篇介绍过的 word embedding 层的取词作用得到词向量, 接着经过一个双向 LSTM 单元学习序列的特征表示,这个特别表示最终作为条件随机场 CRF 的输入完成最终的序列标注任务。 

下面是对各个子模块的进一步说明。

双向循环神经网络 

在循环神经网络模型中,t 时刻输出的隐藏层向量编码了到 t 时刻为止所有输入的信息,但由于循环神经网络单元计算的串行行:t 时刻循环神经网络但愿可以看到历史(t 时刻之前),却无法看到未来(t 时刻之后)。

一些自然语言处理任务总是能一次性拿到整个句子,这种情况下,在 t 时刻计算时,如果能够像获取历史信息一样得到未来的信息,对序列学习任务会有很大帮助,双向循环神经网络的出现正是为了解决这一问题。

它的思想简单且直接:使用两个循环神经网络单元( simple RNN,GRU 或者 LSTM 均可)分别以正向和反向顺序学习输入序列,再将两者的输出 向量进行横向拼接。这样的一个输出向量中就既包含了 t 时刻之前的信息,也包含了 t 时刻之后的信息。

条件随机场 

使用神经网络模型解决问题的思路通常都是:前层网络学习输入的特征表示,网络的最后一层在特征基础上完成最终任务。在序列 标注任务中,双向循环神经网络学习输入的特征表示,条件随机场(Conditional Random Filed, CRF)正是在特征的基础上完成序列标注的一种计算单元,处于整个网络的末端。

CRF 是一种概率化结构模型,可以看作是一个概率无向图模型(也叫作马尔科夫随机场),结点表示随机变量,边表示随机变量之间的概率依赖关系。简单来讲 CRF 学习条件概率:P(X|Y),其中 X=(x1,x2,...,xn) 是输入序列,Y=(y1,y2,...,yn) 是标记序列;解码过程是给定 X 序列求解令 P(Y|X) 最大的 Y 序列,即

条件随机场是的定义:设 G=(V,E) 是一个无向图, V 是结点的集合,E 是无向边的集合。V 中的每个结点对应一个随机变量 Yv,,其取值范围为可能的标记集合 {y},如果以随机变量 X 为条件,每个随机变量 Yv 都满足以下马尔科夫特性: 

其中,ω∼v 表示两个结点在图 G 中是邻近结点,那么,(X,Y) 是一个条件随机场

线性链条件随机场 

上面的定义并没有对 X 和 Y 的结构给出更多约束,理论上来讲只要标记序列表示了一定的条件独立性,G 的图结构可以是任意的。对序列标注任务,只需要考虑 X 和 Y 都是一个序列,于是可以形成一个如图 4 所示的简单链式结构图。在图中,输入序列 X 的元素之间并不存在图结构,因为我们只是将它作为条件,并不做任何条件独立假设。

▲ 图4. 输入序列和标记序列具有相同结构的线性链条件随机场

序列标注问题使用的是以上这种定义在线性链上的特殊条件随机场,称之为线性链条件随机场(Linear Chain Conditional Random Field)。下面,我们给出线性链条件随机场的数学定义: 

定义 2 :线性链条件随机场设 X=(x1,x2,...,xn),Y=(y1,y2,...,yn) 均为线性链表示的随机变量序列,若在给定随机变量序列 X 的条件下,随机变量序列 Y 的条件概率分布 P(Y|X) 满足马尔科夫性:

i=1,2,...,n(在i=1和n时只考虑单边)则称 P(Y|X) 为线性链条件随机场。X 表示输入序列,Y 表示与之对应的标记序列。

根据线性链条件随机场上的因子分解定理,在给定观测序列 X 时,一个特定标记序列 Y 的概率可以定义为:

其中:

是规范化因子。

上面的式子中 tj 是定义在边上的特征函数,依赖于当前和前一个位置,称为转移特征,表示对于观察序列 X 及其标注序列在 i 及 i−1 位置上标记的转移概率。sk 是定义在结点上的特征函数,称为状态特征,依赖于当前位置,表示对于观察序列 X 及其 i 位置的标记概率。λj 和 μk 分别是转移特征函数和状态特征函数对应的权值。

线性链条件随机场的优化目标 

实际上 ,t 和 s 可以用相同的数学形式表示,s 可以同样也写为以下形式:

假设有 K1 个转移特征,K2 个状态特征,定义特征函数

再对转移特征和状态特在各个位置 i 求和有:

于是条件概率 P(Y|X) 可以写为:

我们把 f 统称为特征函数,ω 是权值,是 CRF 模型要求解的参数

学习时,对于给定的输入序列和对应的标记序列的集合 D=[(X1,Y1),(X2,Y2),...,(XN,YN)] ,通过正则化的极大似然估计,可以得到如下优化目标:

这个优化目标,可以通过反向传播算法和整个神经网络一起更新求解。 

解码时,对于给定的输入序列 X,通过解码算法(通常有:维特比算法、Beam Search)求令出条件概率最大的输出序列

CRF小结

条件随机场是这一篇网络中一个相对复杂的计算单元。值得庆幸的是,在各个深度学习框架的帮助下,大多数情况下,我们只需要知道其原理便可以非常方便的使用,而不必过于关注 其内部的实现细节。

这里我们再对上面的内容进行一个简单的总结,方便大家使用 CRF 单元:

1. 在序列标注网络中, CRF 以循环神经网络单元输出向量作为输入,学习状态特征和转移特征。

2. 状态特征只与当然输入有关;转移特征是一个矩阵,刻画了标记两两之间互相转移的强度。

3. 假设循环神经网络单元输出向量维度为 h ,序列中含有 t 个词语,共有 d 个标记:

  • 循环神经网络输入矩阵的大小为:Out=t×h;

  • CRF 层以 Out 为输入学习转移特征:通过一个 全连接层将 Out 映射为一个 t×d 的矩阵,也就是转移特征; 

  • 状态特征是一个:(d+2)×d 维的矩阵,刻画了标记之前转移的强度。 这里的 +2 是需要学习序列开始 <s> 向句子首词转移和和句子末尾词向序列结束 <e> 转移这样两种特殊的状态转移;

  • CRF 本质上计算了一个 softmax:给定标记序列出现的概率。但困难之处在于 softmax 的归一化分母是所有可能标记序列,计算量很大。但由于引入了马尔科夫假设,这个归一化分母可以巧妙地通过一个动态规划算法求解。 

4. CRF 的学习准则是令 negative log likelihood 最大化。

数据集介绍

这一篇我们使用 Standford CS224d 课程中作业 2 [2] 的 NER 任务数据作为训练数据源。 进入 data 目录运行 data/download.sh 脚本下载数据并预处理训练数据。预处理包括:1. 为输入文本序列建立词典;2. 组织输入数据格式。 

运行结束将会在 data 目录下看到如下内容。

data
├── dev
├── dev_src.txt
├── dev_src.vocab
├── dev_trg.txt
├── dev_trg.vocab
├── download.sh
├── preprocess.py
├── train
├── train_src.txt
├── train_src.vocab
├── train_trg.txt
└── train_trg.vocab

其中需要重点关注的是 train_src.txt 、 train_trg.txt 、 train_src.vocab和train_trg.vocab 文件。它们分别是:输入文本序列;文本对应的标记序列;输入文本序列的词典以及标记序列词典。 train_src.txt 和 train_trg.txt 的一行是一条训练样本,他们严格一一对应。分别执行 head -n 1 train_src.txt 和 head -n 1 train_trg.t xt 会看到如下内容:

EU rejects German call to boycott British lamb .
B-ORG O B-MISC O O O B-MISC O O

程序结构

我们首先在此整体回顾一下使用 PaddleFluid 平台和 TensorFlow 运行神经网络模型的整体流程。

PaddleFluid

1. 调用 PaddleFluid API 描述神经网络模型。PaddleFluid 中 一个神经网络训练任务被称之为一段 Fluid Program 。 

2. 定义 Fluid Program 执行设备: place 。常见的有 fluid.CUDAPlace(0) 和fluid.CPUPlace() 。

place = fluid.CUDAPlace(0) if conf.use_gpu else fluid.CPUPlace()

注:PaddleFluid 支持混合设备运行,一些 运算(operator)没有特定设备实现,或者为了提高全局资源利用率,可以为他们指定不同的计算设备。

3. 创建 PaddleFluid 执行器(Executor),需要为执行器指定运行设备。

exe = fluid.Executor(place)

4. 让执行器执行 fluid.default_startup_program() ,初始化神经网络中的可学习参数,完成必要的初始化工作。 

5. 定义 DataFeeder,编写 data reader,只需要关注如何返回一条训练/测试数据。 

6. 进入训练的双层循环(外层在 epoch 上循环,内层在 mini-batch 上循环),直到训练结束。

TensorFlow 

1. 调用 TensorFlow API 描述神经网络模型。 TensorFlow 中一个神经网络模型是一个 Computation Graph。

2. 创建 TensorFlow Session 用来执行计算图。

sess = tf.Session()

3. 调用 sess.run(tf.global_variables_initializer()) 初始化神经网络中的可学习参数

4. 编写返回每个 mini-batch 数据的数据读取脚本。

5. 进入训练的双层循环(外层在 epoch 上循环,内层在 mini-batch 上循环),直到训练结束。

如果不显示地指定使用何种设备进行训练,TensorFlow 会对机器硬件进行检测(是否有 GPU), 选择能够尽可能利用机器硬件资源的方式运行。 

构建网络

基于 PaddleFluid 和 TensorFlow 的序列标注网络分别定义在 sequence_tagging_fluid.py 和 sequence_tagging_tensorflow.py 的 NER_net 类中,详细信息请参考完整代码,这里对重要部分进行说明。 

加载训练数据 

PaddleFluid:编写Data Reader 

PaddleFluid 模型通过 fluid.layers.data 来接收输入数据。序列标注网络以图片以及图片对应的类别标签作为网络的输入:

self.source = fluid.layers.data(
    name="source", shape=[1], dtype="int64", lod_level=1)
self.target = fluid.layers.data(
    name="target", shape=[1], dtype="int64", lod_level=1)

定义 data layer 的核心是指定输入 Tensor 的形状( shape )和类型。

序列标注中,输入文本序列和标记序列都使用 one-hot 特征作为输入,一个词用一个和字典大小相同的向量表示,每一个位置对应了字典中的 一个词语。one-hot 向量仅有一个维度为 1, 其余全部为 0。在上面定义的 data layer 中 source 和 target 的形状都是 1,类型是 int64 。 

PaddleFluid 支持非填充的序列输入,这是通过 LoD Tensor 实现的。关于什么是 LoD Tensor请参考上一篇使用 PaddleFluid 和 TensorFlow 训练 RNN 语言模型中的介绍,这一篇不再赘述。有了 LoD Tensor 的概念后,在 PaddleFluid 中,通过 DataFeeder 模块来为网络中的 data layer 提供数据,调用方式如下面的代码所示:

train_reader = paddle.batch(
    paddle.reader.shuffle(
        data_reader(conf.train_src_file_name, conf.train_trg_file_name,
                    conf.src_vocab_file, conf.trg_vocab_file),
        buf_size=1024000),
    batch_size=conf.batch_size)

place = fluid.CUDAPlace(0) if conf.use_gpu else fluid.CPUPlace()
feeder = fluid.DataFeeder(feed_list=[net.source, net.target], place=place)

观察以上代码,需要用户完成的仅有:编写一个实现读取一条数据的 python 函数:data_reader 。 data_reader 的代码非常简单,我们再来看一下它的具体实现:

def data_reader(src_file_name, trg_file_name, src_vocab_file, trg_vocab_file):
    def __load_dict(dict_file_path):
        word_dict = {}
        with open(dict_file_path, "r") as fdict:
            for idx, line in enumerate(fdict):
                if idx < 2: continue
                word_dict[line.strip().split("\t")[0]] = idx - 2

        return word_dict

    def __reader():
        src_dict = __load_dict(src_vocab_file)
        trg_dict = __load_dict(trg_vocab_file)

        with open(src_file_name, "r") as fsrc, open(trg_file_name,
                                                    "r") as ftrg:
            for src, trg in izip(fsrc, ftrg):
                src_words = src.strip().split()
                trg_words = trg.strip().split()

                src_ids = [src_dict[w] for w in src_words]
                trg_ids = [trg_dict[w] for w in trg_words]
                yield src_ids, trg_ids

    return __reader

在上面的代码中: 

1. data_reader 是一个 python generator ,函数名字可以任意指定,无需固定。 

2. data_reader 打开输入序列文件和标记序列文件,每次从这两个文件读取一行,一行既是一条训练数据,返回一个 python list,这个 python list 既是序列中所有时间步。具体的数据组织方式如下表所示,其中 i 代表一个整数:

3. paddle.batch() 接口用来构造 mini-batch 输入,会调用 data_reader 将数据读入一个 pool 中,对 pool 中的数据进行 shuffle,然后依次返回每个 mini-batch 的数据。

TensorFlow:使用Dataset API

在之前的篇章中我们都使用 TensorFlow 的 placeholder 接入训练数据,这一篇我们使用一种新的方式 TensorFlow 在 r1.3 版本之后引入的 Dataset API 来读取数据。

参考 Google 官方给出的 Dataset API 中的类图 [3],使用 TensorFlow 的 Dataset API,首先引入两个抽象概念:

1. tf.data.Dataset 表示一系列元素,其中每个元素包含一个或多个 Tensor 对象。

2. tf.data.Iterator 提供了从数据集中取出元素的方法。 Iterator.get_next() 会在执行时生成Dataset 的下一个 /mini-batch 元素。

定义 Dataset 

目前 Dataset API 还提供了三种预定义好的定义 Dataset 的方式。这一篇中我们主要面向文本数据的处理,使用其中的 TextLineDataset 接口。 

tf.data.TextLineDataset:接口的输入是一个文件列表,输出是一个 TensorFlow dataset ,dataset 中的每一个元素就对应了文件中的一行。通过下面的调用传入输入序列文本路径和标记序列文本路径便可返回一个 Dataset 。

src_dataset = tf.data.TextLineDataset(src_file_name)
trg_dataset = tf.data.TextLineDataset(trg_file_name)

获取 Iterator 

需要说明的是,TensorFlow 中的循环神经网络要求一个 mini-batch 之内序列长度相等,使用 Dynamic RNN 时,batch 和 batch 之间序列长度可以不相等,因此对一个 mini-batch 之内的数据需要进行填充。 

Dataset API 提供了 padded_batch 帮助构造填充后的 mini-batch 数据。 

提示:使用 bucket 分桶,从桶内取 mini-batch 数据,填充至一个 batch 中的最长序列长度能够有效提高 dynamic rnn 的计算效率。 

下面的代码返回 Iterator ,使用先分桶,然后再取 mini-batch 数据填充至  batch 中最长序列长度的方式。完整代码请参考:iterator_helper_tf [4]。

def get_data_iterator(src_file_name,
                      trg_file_name,
                      src_vocab_file,
                      trg_vocab_file,
                      batch_size,
                      pad_token="</p>",
                      max_sequence_length=None,
                      unk_id=1,
                      num_parallel_calls=4,
                      num_buckets=5,
                      output_buffer_size=102400,
                      is_training=True):

    def __get_word_dict(vocab_file_path, unk_id):
        return tf.contrib.lookup.index_table_from_file(
            vocabulary_file=vocab_file_path,
            key_column_index=0,
            default_value=unk_id)

    src_dataset = tf.data.TextLineDataset(src_file_name)
    trg_dataset = tf.data.TextLineDataset(trg_file_name)

    dataset = tf.data.Dataset.zip((src_dataset, trg_dataset))
    if is_training:
        dataset = dataset.shuffle(
            buffer_size=output_buffer_size, reshuffle_each_iteration=True)

    src_trg_dataset = dataset.map(
        lambda src, trg: (tf.string_split([src]).values, \
                tf.string_split([trg]).values),
        num_parallel_calls=num_parallel_calls).prefetch(output_buffer_size)

    src_dict = __get_word_dict(src_vocab_file, unk_id)
    trg_dict = __get_word_dict(trg_vocab_file, unk_id)

    src_pad_id = tf.cast(src_dict.lookup(tf.constant(pad_token)), tf.int32)
    trg_pad_id = tf.cast(trg_dict.lookup(tf.constant(pad_token)), tf.int32)

    # convert word string to word index
    src_trg_dataset = src_trg_dataset.map(
        lambda src, trg: (
                tf.cast(src_dict.lookup(src), tf.int32),
                tf.cast(trg_dict.lookup(trg), tf.int32)),
        num_parallel_calls=num_parallel_calls).prefetch(output_buffer_size)

    # Add in sequence lengths.
    src_trg_dataset = src_trg_dataset.map(
        lambda src, trg: (src, trg, tf.size(src)),
        num_parallel_calls=num_parallel_calls).prefetch(output_buffer_size)

    def __batching_func(x):
        return x.padded_batch(
            batch_size,
            padded_shapes=(
                tf.TensorShape([None]),  # src
                tf.TensorShape([None]),  # trg
                tf.TensorShape([]),  #seq_len
            ),
            padding_values=(src_pad_id, trg_pad_id, 0, ))

    if num_buckets > 1:

        def __key_func(unused_1, unused_2, seq_len):
            if max_sequence_length:
                bucket_width = (
                    max_sequence_length + num_buckets - 1) // num_buckets
            else:
                bucket_width = 10

            bucket_id = seq_len // bucket_width,
            return tf.to_int64(tf.minimum(num_buckets, bucket_id))

        def __reduce_func(unused_key, windowed_data):
            return __batching_func(windowed_data)

        batched_dataset = src_trg_dataset.apply(
            tf.contrib.data.group_by_window(
                key_func=__key_func,
                reduce_func=__reduce_func,
                window_size=batch_size))

    else:
        batched_dataset = __batching_func(curwd_nxtwd_dataset)

    batched_iter = batched_dataset.make_initializable_iterator()
    src_ids, trg_ids, seq_len = batched_iter.get_next()

    return BatchedInput(
        initializer=batched_iter.initializer,
        source=src_ids,
        target=trg_ids,
        sequence_length=seq_len)

构建网络结构及运行

构建网络结构及运行的过程对两个平台上都是常规流程。

1. 构建网络时调用相关的 API 接口,令一个 计算单元的输出成为下一个计算单元的输入建立起网络的连通性;具体请参考 sequence_tagging_fluid.py 和 sequence_tagging_tensorflow.py 中 NER_net 类的实现。

2. 运行训练以及解码具体请参考 sequence_tagging_fluid.py 和 sequence_tagging_tensorflow.py 中 train 函数的实现。

模型中核心模块:LSTM 单元在两个平台下的差异及注意事项请参考上一篇:使用 PaddleFluid 和 TensorFlow 训练 RNN 语言模型,这里不再赘述。

总结

这一篇继续在序列标注模型中了解 PaddleFluid 和 TensorFlow 在接受序列输入,序列处理策略上的不同。 

1. PaddleFluid 引入了 LoD Tensor 的概念,所有序列处理模块(包括所有循环神经网络单元,文本卷积)都支持非填充的序列输入,使用时无需对 mini-batch 数据进行填充,也就避免了对填充位的各种特殊处理,这一点非常方便。 

2. TensorFlow 中的 Dynamic RNN 支持 mini-batch 之间序列不等长,但仍要求一个 mini-batch 内的数据填充至一样长。 

3. PaddleFluid 中通过 Data Feeder 提供训练数据,只需要编写一个 python generator 实现从原始输入文件中读取一条训练样本, 框架会完成数据 shuffle 和组织 mini-batchd 工作。 

4. 这一篇使用了 TensorFlow r1.3 后 release 的 Dataset API,数据读取部分也是一个 computation graph,能够提高 I/O 效率,使用相对复杂一些。 

本篇代码中提供了通过数据并行策略在 PaddleFluid 平台下使用多块 GPU 卡进行训练,在 TensorFlow 中使用多卡相对复杂一些,这些主题会在下面继续讨论。

参考文献

[1]. 本文配套代码

https://github.com/JohnRabbbit/TF2Fluid/tree/master/05_sequence_tagging

[2].  Standford CS224d课程作业2

http://cs224d.stanford.edu/assignment2/index.html

[3]. Google官方Dataset API

https://developers.googleblog.com/2017/09/introducing-tensorflow-datasets.html

[4]. iterator_helper_tf

https://github.com/JohnRabbbit/TF2Fluid/blob/master/05_sequence_tagging/iterator_helper_tf.py

推荐、解读、讨论和报道人工智能前沿论文成果的学术平台。

入门PaddleFluidTensorFlow
1
相关数据
神经网络技术
Neural Network

(人工)神经网络是一种起源于 20 世纪 50 年代的监督式机器学习模型,那时候研究者构想了「感知器(perceptron)」的想法。这一领域的研究者通常被称为「联结主义者(Connectionist)」,因为这种模型模拟了人脑的功能。神经网络模型通常是通过反向传播算法应用梯度下降训练的。目前神经网络有两大主要类型,它们都是前馈神经网络:卷积神经网络(CNN)和循环神经网络(RNN),其中 RNN 又包含长短期记忆(LSTM)、门控循环单元(GRU)等等。深度学习是一种主要应用于神经网络帮助其取得更好结果的技术。尽管神经网络主要用于监督学习,但也有一些为无监督学习设计的变体,比如自动编码器和生成对抗网络(GAN)。

反向传播算法技术
Back-propagation

反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法计算对网络中所有权重计算损失函数的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。 在神经网络上执行梯度下降法的主要算法。该算法会先按前向传播方式计算(并缓存)每个节点的输出值,然后再按反向传播遍历图的方式计算损失函数值相对于每个参数的偏导数。

条件独立性技术
Conditional independence

在概率论和统计学中,两事件R和B在给定的另一事件Y发生时条件独立,类似于统计独立性,就是指当事件Y发生时,R发生与否和B发生与否就条件概率分布而言是独立的。换句话讲,R和B在给定Y发生时条件独立,当且仅当已知Y发生时,知道R发生与否无助于知道B发生与否,同样知道B发生与否也无助于知道R发生与否。

条件概率分布技术
Conditional probability (distribution)

条件概率分布(Conditional Probability Distribution,或者条件分布,Conditional Distribution )是现代概率论中的概念。 已知两个相关的随机变量X 和Y,随机变量Y 在条件{X =x}下的条件概率分布是指当已知X 的取值为某个特定值x之时,Y 的概率分布。

条件随机场技术
Conditional random field

条件随机场(conditional random field,简称 CRF),是一种鉴别式机率模型,是随机场的一种,常用于标注或分析序列资料,如自然语言文字或是生物序列。 如同马尔可夫随机场,条件随机场为无向性之图模型,图中的顶点代表随机变量,顶点间的连线代表随机变量间的相依关系,在条件随机场当中,随机变量 Y 的分布为条件机率,给定的观察值则为随机变量 X。原则上,条件随机场的图模型布局是可以任意给定的,一般常用的布局是链接式的架构,链接式架构不论在训练(training)、推论(inference)、或是解码(decoding)上,都存在有效率的算法可供演算。 条件随机场跟隐马尔可夫模型常被一起提及,条件随机场对于输入和输出的机率分布,没有如隐马尔可夫模型那般强烈的假设存在。 线性链条件随机场应用于标注问题是由Lafferty等人与2001年提出的。

动态规划技术
Dynamic programming

动态规划(也称为动态优化),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划将复杂的问题分解成一系列相对简单的子问题,只解决一次子问题并存储它的解决方案(solution),下一次遇到同样的子问题时无需重新计算它的解决方案,而是简单地查找先前计算的解决方案,从而节省计算时间。动态规划适用于有最优子结构(Optimal Substructure)和重叠子问题(Overlapping Subproblems)性质的问题。

分桶技术
Bucketing

将一个特征(通常是连续特征)转换成多个二元特征(称为桶或箱),通常是根据值区间进行转换。例如,您可以将温度区间分割为离散分箱,而不是将温度表示成单个连续的浮点特征。假设温度数据可精确到小数点后一位,则可以将介于 0.0 到 15.0 度之间的所有温度都归入一个分箱,将介于 15.1 到 30.0 度之间的所有温度归入第二个分箱,并将介于 30.1 到 50.0 度之间的所有温度归入第三个分箱。

映射技术
Mapping

映射指的是具有某种特殊结构的函数,或泛指类函数思想的范畴论中的态射。 逻辑和图论中也有一些不太常规的用法。其数学定义为:两个非空集合A与B间存在着对应关系f,而且对于A中的每一个元素x,B中总有有唯一的一个元素y与它对应,就这种对应为从A到B的映射,记作f:A→B。其中,y称为元素x在映射f下的象,记作:y=f(x)。x称为y关于映射f的原象*。*集合A中所有元素的象的集合称为映射f的值域,记作f(A)。同样的,在机器学习中,映射就是输入与输出之间的对应关系。

语言模型技术
Language models

语言模型经常使用在许多自然语言处理方面的应用,如语音识别,机器翻译,词性标注,句法分析和资讯检索。由于字词与句子都是任意组合的长度,因此在训练过的语言模型中会出现未曾出现的字串(资料稀疏的问题),也使得在语料库中估算字串的机率变得很困难,这也是要使用近似的平滑n元语法(N-gram)模型之原因。

命名实体识别技术
Named entity recognition

命名实体识别(NER)是信息提取(Information Extraction)的一个子任务,主要涉及如何从文本中提取命名实体并将其分类至事先划定好的类别,如在招聘信息中提取具体招聘公司、岗位和工作地点的信息,并将其分别归纳至公司、岗位和地点的类别下。命名实体识别往往先将整句拆解为词语并对每个词语进行此行标注,根据习得的规则对词语进行判别。这项任务的关键在于对未知实体的识别。基于此,命名实体识别的主要思想在于根据现有实例的特征总结识别和分类规则。这些方法可以被分为有监督(supervised)、半监督(semi-supervised)和无监督(unsupervised)三类。有监督学习包括隐形马科夫模型(HMM)、决策树、最大熵模型(ME)、支持向量机(SVM)和条件随机场(CRF)。这些方法主要是读取注释语料库,记忆实例并进行学习,根据这些例子的特征生成针对某一种实例的识别规则。

元学习技术
Meta learning

元学习是机器学习的一个子领域,是将自动学习算法应用于机器学习实验的元数据上。现在的 AI 系统可以通过大量时间和经验从头学习一项复杂技能。但是,我们如果想使智能体掌握多种技能、适应多种环境,则不应该从头开始在每一个环境中训练每一项技能,而是需要智能体通过对以往经验的再利用来学习如何学习多项新任务,因此我们不应该独立地训练每一个新任务。这种学习如何学习的方法,又叫元学习(meta-learning),是通往可持续学习多项新任务的多面智能体的必经之路。

自然语言处理技术
Natural language processing

自然语言处理(英语:natural language processing,缩写作 NLP)是人工智能和语言学领域的分支学科。此领域探讨如何处理及运用自然语言;自然语言认知则是指让电脑“懂”人类的语言。自然语言生成系统把计算机数据转化为自然语言。自然语言理解系统把自然语言转化为计算机程序更易于处理的形式。

规范化技术
Normalization

规范化:将属性数据按比例缩放,使之落入一个小的特定区间,如-1.0 到1.0 或0.0 到1.0。 通过将属性数据按比例缩放,使之落入一个小的特定区间,如0.0到1.0,对属性规范化。对于距离度量分类算法,如涉及神经网络或诸如最临近分类和聚类的分类算法,规范化特别有用。如果使用神经网络后向传播算法进行分类挖掘,对于训练样本属性输入值规范化将有助于加快学习阶段的速度。对于基于距离的方法,规范化可以帮助防止具有较大初始值域的属性与具有较小初始值域的属相相比,权重过大。有许多数据规范化的方法,包括最小-最大规范化、z-score规范化和按小数定标规范化。

词性标注技术
part of speech (tagging)

词性标注是指为分词结果中的每个单词标注一个正确的词性的程序,也即确定每个词是名词、动词、形容词或其他词性的过程。

参数技术
parameter

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

维特比算法技术
Viterbi algorithm

维特比算法(英语:Viterbi algorithm)是一种动态规划算法。它用于寻找最有可能产生观测事件序列的维特比路径——隐含状态序列,特别是在马尔可夫信息源上下文和隐马尔可夫模型中。 术语“维特比路径”和“维特比算法”也被用于寻找观察结果最有可能解释相关的动态规划算法。例如在统计句法分析中动态规划算法可以被用于发现最可能的上下文无关的派生(解析)的字符串,有时被称为“维特比分析”。

深度学习技术
Deep learning

深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。 深度学习是机器学习中一种基于对数据进行表征学习的算法,至今已有数种深度学习框架,如卷积神经网络和深度置信网络和递归神经网络等已被应用在计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域并获取了极好的效果。

张量技术
Tensor

张量是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数,这些线性关系的基本例子有内积、外积、线性映射以及笛卡儿积。其坐标在 维空间内,有 个分量的一种量,其中每个分量都是坐标的函数,而在坐标变换时,这些分量也依照某些规则作线性变换。称为该张量的秩或阶(与矩阵的秩和阶均无关系)。 在数学里,张量是一种几何实体,或者说广义上的“数量”。张量概念包括标量、矢量和线性算子。张量可以用坐标系统来表达,记作标量的数组,但它是定义为“不依赖于参照系的选择的”。张量在物理和工程学中很重要。例如在扩散张量成像中,表达器官对于水的在各个方向的微分透性的张量可以用来产生大脑的扫描图。工程上最重要的例子可能就是应力张量和应变张量了,它们都是二阶张量,对于一般线性材料他们之间的关系由一个四阶弹性张量来决定。

TensorFlow技术
TensorFlow

TensorFlow是一个开源软件库,用于各种感知和语言理解任务的机器学习。目前被50个团队用于研究和生产许多Google商业产品,如语音识别、Gmail、Google 相册和搜索,其中许多产品曾使用过其前任软件DistBelief。

推荐文章