diff --git a/ltr/README.md b/ltr/README.md index a8fa8195537a92af1fffcad9c3af15005cbb18ae..d4d80e3ef16083168a491d37a78a7da1cf289b51 100644 --- a/ltr/README.md +++ b/ltr/README.md @@ -1,4 +1,4 @@ -## 排序学习(LearningToRank) +# 排序学习(Learning To Rank) 排序学习技术\[[1](#参考文献1)\]是构建排序模型的机器学习方法,在信息检索、自然语言处理,数据挖掘等机器学场景中具有重要作用。排序学习的主要目的是对给定一组文档,对任意查询请求给出反映相关性的文档排序。在本例子中,利用标注过的语料库训练两种经典排序模型RankNet[[4](#参考文献4)\]和LamdaRank[[6](#参考文献6)\],分别可以生成对应的排序模型,能够对任意查询请求,给出相关性文档排序。 @@ -238,9 +238,9 @@ $$\lambda _{i,j}=\frac{\partial C}{\partial s_{i}}=-\frac{\sigma }{1+e^{\sigma ( ```python import paddle.v2 as paddle -def lambdaRank(input_dim): +def lambda_rank(input_dim): """ - lambdaRank is a ListWise Rank Model, input data and label must be sequence + lambda_rank is a ListWise Rank Model, input data and label must be sequence https://papers.nips.cc/paper/2971-learning-to-rank-with-nonsmooth-cost-functions.pdf parameters : input_dim, one document's dense feature vector dimension diff --git a/ltr/lambda_rank.py b/ltr/lambda_rank.py index 7a213791f300f45387c44c6af0ae8db7879b0d5e..123edc353cee9447a801b9300099df9d8fd64559 100644 --- a/ltr/lambda_rank.py +++ b/ltr/lambda_rank.py @@ -4,18 +4,16 @@ import paddle.v2 as paddle import numpy as np import functools -#lambdaRank is listwise learning to rank model - -def lambdaRank(input_dim): +def lambda_rank(input_dim): """ - lambdaRank is a ListWise Rank Model, input data and label must be sequence + lambda_rank is a Listwise rank model, the input data and label must be sequences. https://papers.nips.cc/paper/2971-learning-to-rank-with-nonsmooth-cost-functions.pdf parameters : input_dim, one document's dense feature vector dimension - dense_vector_sequence format - [[f, ...], [f, ...], ...], f is represent for an float or int number + format of the dense_vector_sequence: + [[f, ...], [f, ...], ...], f is a float or an int number """ label = paddle.layer.data("label", paddle.data_type.dense_vector_sequence(1)) @@ -48,7 +46,7 @@ def lambdaRank(input_dim): return cost, output -def train_lambdaRank(num_passes): +def train_lambda_rank(num_passes): # listwise input sequence fill_default_train = functools.partial( paddle.dataset.mq2007.train, format="listwise") @@ -60,7 +58,7 @@ def train_lambdaRank(num_passes): # mq2007 input_dim = 46, dense format input_dim = 46 - cost, output = lambdaRank(input_dim) + cost, output = lambda_rank(input_dim) parameters = paddle.parameters.create(cost) trainer = paddle.trainer.SGD( @@ -76,7 +74,7 @@ def train_lambdaRank(num_passes): if isinstance(event, paddle.event.EndPass): result = trainer.test(reader=test_reader, feeding=feeding) print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics) - with gzip.open("lambdaRank_params_%d.tar.gz" % (event.pass_id), + with gzip.open("lambda_rank_params_%d.tar.gz" % (event.pass_id), "w") as f: parameters.to_tar(f) @@ -88,17 +86,17 @@ def train_lambdaRank(num_passes): num_passes=num_passes) -def lambdaRank_infer(pass_id): +def lambda_rank_infer(pass_id): """ - lambdaRank model inference interface + lambda_rank model inference interface parameters: pass_id : inference model in pass_id """ print "Begin to Infer..." input_dim = 46 - output = lambdaRank(input_dim) + output = lambda_rank(input_dim) parameters = paddle.parameters.Parameters.from_tar( - gzip.open("lambdaRank_params_%d.tar.gz" % (pass_id - 1))) + gzip.open("lambda_rank_params_%d.tar.gz" % (pass_id - 1))) infer_query_id = None infer_data = [] @@ -119,6 +117,6 @@ def lambdaRank_infer(pass_id): if __name__ == '__main__': - paddle.init(use_gpu=False, trainer_count=4) - train_lambdaRank(2) - lambdaRank_infer(pass_id=1) + paddle.init(use_gpu=False, trainer_count=1) + train_lambda_rank(2) + lambda_rank_infer(pass_id=1) diff --git a/sequence_tagging_for_ner/README.md b/sequence_tagging_for_ner/README.md index e0c488c9aa5298d9d316d45f121c68dc41be73b2..fadfe4564a912641119d6864e36d2ba0874ff96e 100644 --- a/sequence_tagging_for_ner/README.md +++ b/sequence_tagging_for_ner/README.md @@ -1,24 +1,23 @@ # 命名实体识别 -## 背景说明 - 命名实体识别(Named Entity Recognition,NER)又称作“专名识别”,是指识别文本中具有特定意义的实体,主要包括人名、地名、机构名、专有名词等,是自然语言处理研究的一个基础问题。NER任务通常包括实体边界识别、确定实体类别两部分,可以将其作为序列标注问题解决。 -序列标注可以分为Sequence Classification、Segment Classification和Temporal Classification三类[[1](#参考文献)],我们这里限定序列标注为Segment Classification,即对输入序列中的每个元素在输出序列中给出对应的标签。对于NER任务,由于需要标识边界,一般采用[BIO方式](http://book.paddlepaddle.org/07.label_semantic_roles/)定义的标签集,如下是一个NER的标注结果示例: +序列标注可以分为Sequence Classification、Segment Classification和Temporal Classification三类[[1](#参考文献)],本例只考虑Segment Classification,即对输入序列中的每个元素在输出序列中给出对应的标签。对于NER任务,由于需要标识边界,一般采用[BIO方式](http://book.paddlepaddle.org/07.label_semantic_roles/)定义的标签集,如下是一个NER的标注结果示例: -
-
+
+
图1. BIO标注方法示例
+根据序列标注结果可以直接得到实体边界和实体类别。类似的,分词、词性标注、语块识别、[语义角色标注](http://book.paddlepaddle.org/07.label_semantic_roles/index.cn.html)等任务同样可通过序列标注来解决。 -根据序列标注结果可以直接得到实体边界和实体类别。类似的,分词、词性标注、语块识别、[语义角色标注](http://book.paddlepaddle.org/07.label_semantic_roles/index.cn.html)等任务同样可作为序列标注问题。 +由于序列标注问题的广泛性,产生了[CRF](http://book.paddlepaddle.org/07.label_semantic_roles/index.cn.html)等经典的序列模型,这些模型大多只能使用局部信息或需要人工设计特征。随着深度学习研究的发展,循环神经网络(Recurrent Neural Network,RNN等序列模型能够处理序列元素之间前后关联问题,能够从原始输入文本中学习特征表示,而更加适合序列标注任务,更多相关知识可参考PaddleBook中[语义角色标注](https://github.com/PaddlePaddle/book/blob/develop/07.label_semantic_roles/README.cn.md)一课。 -由于序列标注问题的广泛性,产生了[CRF](http://book.paddlepaddle.org/07.label_semantic_roles/index.cn.html)等经典的序列模型,这些模型多只能使用局部信息或需要人工设计特征。发展到深度学习阶段,各种网络结构能够实现复杂的特征抽取功能,循环神经网络(Recurrent Neural Network,RNN,更多相关知识见PaddleBook中[语义角色标注](http://book.paddlepaddle.org/07.label_semantic_roles/index.cn.html)一课)能够处理输入序列元素之间前后关联的问题而更适合序列数据。使用神经网络模型解决问题的思路通常是:前层网络学习输入的特征表示,网络的最后一层在特征基础上完成最终的任务;对于序列标注问题的通常做法是:使用基于RNN的网络结构学习特征,将学习到的特征接入CRF进行序列标注。这实际上是将传统CRF中的线性模型换成了非线性神经网络,沿用CRF的出发点是:CRF使用句子级别的似然概率,能够更好的解决标记偏置问题[[2](#参考文献)]。本示例中也将基于此思路建立模型,另外,虽然这里使用的是NER任务,但是所给出的模型也可以应用到其他序列标注任务中。 +使用神经网络模型解决问题的思路通常是:前层网络学习输入的特征表示,网络的最后一层在特征基础上完成最终的任务;对于序列标注问题,通常:使用基于RNN的网络结构学习特征,将学习到的特征接入CRF完成序列标注。实际上是将传统CRF中的线性模型换成了非线性神经网络。沿用CRF的出发点是:CRF使用句子级别的似然概率,能够更好的解决标记偏置问题[[2](#参考文献)]。本例也将基于此思路建立模型。虽然,这里以NER任务作为示例,但所给出的模型可以应用到其他各种序列标注任务中。 ## 模型说明 -在NER任务中,输入是"一句话",目标是识别句子中的实体边界及类别,我们参照论文\[[2](#参考文献)\]仅对原始句子进行了一些预处理工作:将每个词转换为小写,并将原词是否大写另作为一个特征,共同作为模型的输入。按照上文所述处理序列标注问题的思路,可以构造如下结构的模型(图2是模型结构示意图): +NER任务的输入是"一句话",目标是识别句子中的实体边界及类别,我们参照论文\[[2](#参考文献)\]仅对原始句子进行了一些预处理工作:将每个词转换为小写,并将原词是否大写另作为一个特征,共同作为模型的输入。按照上述处理序列标注问题的思路,可构造如下结构的模型(图2是模型结构示意图): 1. 构造输入 - 输入1是句子序列,采用one-hot方式表示 @@ -28,14 +27,14 @@ 4. CRF以步骤3中模型学习到的特征为输入,以标记序列为监督信号,实现序列标注。
-
-图2. NER模型网络结构 +
+图2. NER模型的网络结构图
## 数据说明 -在本示例中,我们将使用CoNLL 2003 NER任务中开放出的数据集。该任务(见[此页面](http://www.clips.uantwerpen.be/conll2003/ner/))只提供了标注工具的下载,原始Reuters数据由于版权原因需另外申请免费下载。在获取原始数据后可参照标注工具中README生成所需数据文件,完成后将包括如下三个数据文件: +在本例中,我们使用CoNLL 2003 NER任务中开放出的数据集。该任务(见[此页面](http://www.clips.uantwerpen.be/conll2003/ner/))只提供了标注工具的下载,原始Reuters数据由于版权原因需另外申请免费下载。在获取原始数据后可参照标注工具中README生成所需数据文件,完成后将包括如下三个数据文件: | 文件名 | 描述 | |---|---| @@ -73,7 +72,7 @@ # conll03.train和conll03.test函数可以获取处理之后的每条样本来供PaddlePaddle训练和测试. ``` -预处理完成之后一条训练样本包含3个部分,分别是:句子序列、首字母大写标记序列、标注序列。下表是一条训练样本的示例。 +预处理完成后,一条训练样本包含3个部分:句子序列、首字母大写标记序列、标注序列。下表是一条训练样本的示例。 | 句子序列 | 大写标记序列 | 标注序列 | |---|---|---| @@ -85,7 +84,7 @@ | baghdad | 1 | B-LOC | | . | 0 | O | -另外,使用本示例时数据相关的还有word词典、label词典和预训练的词向量三个文件:label词典已附在`data`目录中,对应于`data/target.txt`;word词典和预训练的词向量来源于[Stanford CS224d](http://cs224d.stanford.edu/)课程作业,请先在该示例所在目录下运行`data/download.sh`脚本进行下载,完成后会将这两个文件一并放入`data`目录下,分别对应`data/vocab.txt`和`data/wordVectors.txt`。 +另外,本例依赖的数据还包括:word词典、label词典和预训练的词向量三个文件。label词典已附在`data`目录中,对应于`data/target.txt`;word词典和预训练的词向量来源于[Stanford CS224d](http://cs224d.stanford.edu/)课程作业,请先在该示例所在目录下运行`data/download.sh`脚本进行下载,完成后会将这两个文件一并放入`data`目录下,分别对应`data/vocab.txt`和`data/wordVectors.txt`。 ## 使用说明 @@ -148,7 +147,7 @@ target_file = 'data/target.txt' # 标签对应的字典文件的路径 emb_file = 'data/wordVectors.txt' # 预训练的词向量参数的路径 ``` -而各接口的调用已在`ner.py`中预先提供 +各接口的调用已在`ner.py`中提供: ```python # 训练数据的生成器 @@ -162,11 +161,11 @@ ner_net_train(data_reader=train_data_reader, num_passes=1) ner_net_infer(data_reader=test_data_reader, model_file='params_pass_0.tar.gz') ``` -除适当调整`num_passes`和`model_file`两参数值外无需再做修改(也可根据需要自行调用各接口,如只使用预测功能)。完成修改后,运行本示例只需在`ner.py`所在路径下执行`python ner.py`即可。该示例程序会执行数据读取、模型训练和保存、模型读取及新样本预测等步骤。 +为运行序列标注模型除适当调整`num_passes`和`model_file`两参数值外,无需再做其它修改(也可根据需要自行调用各接口,如只使用预测功能)。完成修改后,运行本示例只需在`ner.py`所在路径下执行`python ner.py`即可。该示例程序会执行数据读取、模型训练和保存、模型读取及新样本预测等步骤。 ### 自定义数据和任务 -前文提到本示例中的模型可以应用到其他序列标注任务中,这里以词性标注任务为例,给出使用其他数据并应用到其他任务的方法。 +前文提到本例中的模型可以应用到其他序列标注任务中,这里以词性标注任务为例,给出使用其他数据,并应用到其他任务的操作方法。 假定有如下格式的原始数据: @@ -180,7 +179,7 @@ Baghdad NNP . . ``` -其中第一列为原始句子序列,第二列为词性标签序列,两列之间以空格分隔,句子之间以空行分隔。 +第一列为原始句子序列,第二列为词性标签序列,两列之间以“\t”分隔,句子之间以空行分隔。 为使用PaddlePaddle和本示例提供的模型,可参照`conll03.py`并根据需要自定义数据接口,如下: diff --git a/sequence_tagging_for_ner/image/ner_label_ins.png b/sequence_tagging_for_ner/images/ner_label_ins.png similarity index 100% rename from sequence_tagging_for_ner/image/ner_label_ins.png rename to sequence_tagging_for_ner/images/ner_label_ins.png diff --git a/sequence_tagging_for_ner/image/ner_network.png b/sequence_tagging_for_ner/images/ner_network.png similarity index 100% rename from sequence_tagging_for_ner/image/ner_network.png rename to sequence_tagging_for_ner/images/ner_network.png