提交 2113a409 编写于 作者: D dzhwinter

fix format

上级 c80ee118
...@@ -2,7 +2,15 @@ ...@@ -2,7 +2,15 @@
排序学习技术[1] 是构建排序模型的机器学习方法,在信息检索,自然语言处理,数据挖掘等机器学场景中具有重要作用。排序学习的主要目的是对给定一组文档,对任意查询请求给出反映相关性的文档排序。在本例子中,利用标注过的语料库训练两种经典排序模型RankNet[4]和LamdaRank[6],分别可以生成对应的排序模型,能够对任意查询请求,给出相关性文档排序。 排序学习技术[1] 是构建排序模型的机器学习方法,在信息检索,自然语言处理,数据挖掘等机器学场景中具有重要作用。排序学习的主要目的是对给定一组文档,对任意查询请求给出反映相关性的文档排序。在本例子中,利用标注过的语料库训练两种经典排序模型RankNet[4]和LamdaRank[6],分别可以生成对应的排序模型,能够对任意查询请求,给出相关性文档排序。
用户可以使用 `python ranknet.py` 或者 `python lambdaRank.py`命令就完成排序模型的训练和预测,程序会自动下载内置数据集,无需手动下载。 RankNet模型在命令行输入:
`python ranknet.py`
LambdaRank模型在命令行输入:
`python lambdaRank.py`
用户只需要使用以上命令就完成排序模型的训练和预测,程序会自动下载内置数据集,无需手动下载。
...@@ -62,7 +70,7 @@ for label, left_doc, right_doc in pairwise_train_dataset(): ...@@ -62,7 +70,7 @@ for label, left_doc, right_doc in pairwise_train_dataset():
## RankNet排序模型 ## RankNet排序模型
[RankNet](http://icml.cc/2015/wp-content/uploads/2015/06/icml_ranking.pdf)是一种经典的Pairwise的排序学习方法,是典型的前向神经网络排序模型。在文档集合S中的第i个文档记做`Ui`,它的文档特征向量记做`xi`,对于给定的一个文档对`<Ui, Uj>`,RankNet将输入的单个文档特征向量x映射到`f(x)`,得到`si=f(xi), sj=f(xj)`。将`Ui`相关性比Uj好的概率记做Pij,则 [RankNet](http://icml.cc/2015/wp-content/uploads/2015/06/icml_ranking.pdf)是一种经典的Pairwise的排序学习方法,是典型的前向神经网络排序模型。在文档集合S中的第i个文档记做$U_i$,它的文档特征向量记做$x_i$,对于给定的一个文档对$U_i, U_j$,RankNet将输入的单个文档特征向量x映射到$f(x)$,得到$s_i=f(x_i), s_j=f(x_j)$。将$U_i$相关性比Uj好的概率记做$P_{i,j}$,则
$$P_{i,j}=P(U_{i}>U_{j})=\frac{1}{1+e^{-\sigma (s_{i}-s_{j}))}}$$ $$P_{i,j}=P(U_{i}>U_{j})=\frac{1}{1+e^{-\sigma (s_{i}-s_{j}))}}$$
...@@ -70,7 +78,7 @@ $$P_{i,j}=P(U_{i}>U_{j})=\frac{1}{1+e^{-\sigma (s_{i}-s_{j}))}}$$ ...@@ -70,7 +78,7 @@ $$P_{i,j}=P(U_{i}>U_{j})=\frac{1}{1+e^{-\sigma (s_{i}-s_{j}))}}$$
$$C_{i,j}=-\bar{P_{i,j}}logP_{i,j}-(1-\bar{P_{i,j}})log(1-P_{i,j})$$ $$C_{i,j}=-\bar{P_{i,j}}logP_{i,j}-(1-\bar{P_{i,j}})log(1-P_{i,j})$$
其中代表真实概率的 其中$\bar{P_{i,j}}$代表真实概率,记做
$$\bar{P_{i,j}}=\frac{1}{2}(1+S_{i,j})$$ $$\bar{P_{i,j}}=\frac{1}{2}(1+S_{i,j})$$
...@@ -84,7 +92,7 @@ $$C=\frac{1}{2}(1-S_{i,j})\sigma (s_{i}-s{j})+log(1+e^{-\sigma (s_{i}-s_{j})})$$ ...@@ -84,7 +92,7 @@ $$C=\frac{1}{2}(1-S_{i,j})\sigma (s_{i}-s{j})+log(1+e^{-\sigma (s_{i}-s_{j})})$$
同时,得到文档Ui在排序优化过程的梯度信息为 同时,得到文档Ui在排序优化过程的梯度信息为
\lambda _{i,j}=\frac{\partial C}{\partial s_{i}} = \frac{1}{2}(1-S_{i,j})-\frac{1}{1+e^{\sigma (s_{i}-s_{j})}} $$\lambda _{i,j}=\frac{\partial C}{\partial s_{i}} = \frac{1}{2}(1-S_{i,j})-\frac{1}{1+e^{\sigma (s_{i}-s_{j})}}$$
表示的含义是本轮排序优化过程中上升或者下降量。 表示的含义是本轮排序优化过程中上升或者下降量。
...@@ -97,8 +105,8 @@ $$C=\frac{1}{2}(1-S_{i,j})\sigma (s_{i}-s{j})+log(1+e^{-\sigma (s_{i}-s_{j})})$$ ...@@ -97,8 +105,8 @@ $$C=\frac{1}{2}(1-S_{i,j})\sigma (s_{i}-s{j})+log(1+e^{-\sigma (s_{i}-s_{j})})$$
图3. RankNet网络结构示意图 图3. RankNet网络结构示意图
</p> </p>
- 全连接层(fully connected layer) : 指上一层中的每个节点都连接到下层网络。本例子中同样使用paddle.layer.fc实现,注意输入到RankCost层的全连接层输出为1x1的层结构 - 全连接层(fully connected layer) : 指上一层中的每个节点都连接到下层网络。本例子中同样使用paddle.layer.fc实现,注意输入到RankCost层的全连接层维度为1。
- RankCost层: RankCost层是排序网络RankNet的核心,度量docA相关性是否比docB好,给出预测值并和label比较。使用了交叉熵(cross enctropy)作为度量损失函数,使用梯度下降方法进行优化。细节可见[RankNet](http://icml.cc/2015/wp-content/uploads/2015/06/icml_ranking.pdf)[4] - RankCost层: RankCost层是排序网络RankNet的核心,度量docA相关性是否比docB好,给出预测值并和label比较。使用了交叉熵(cross enctropy)作为度量损失函数,使用梯度下降方法进行优化。细节可见[RankNet](http://icml.cc/2015/wp-content/uploads/2015/06/icml_ranking.pdf)[4]
由于Pairwise中的网络结构是左右对称,可定义一半网络结构,另一半共享网络参数。使用PaddlePaddle实现RankNet排序模型,定义网络结构的示例代码如下: 由于Pairwise中的网络结构是左右对称,可定义一半网络结构,另一半共享网络参数。使用PaddlePaddle实现RankNet排序模型,定义网络结构的示例代码如下:
...@@ -142,17 +150,21 @@ def ranknet(input_dim): ...@@ -142,17 +150,21 @@ def ranknet(input_dim):
return cost return cost
``` ```
上述结构中使用了和前述图表相同的模型结构,使用了两层隐藏层,分别使用了`hidden_size=10`的全连接层和`hidden_size=1`的全连接层。本例子中的input_dim指输入**单个文档**的特征dense_vector的维度,label取值为1,-1。每条输入样本为`<label>,<docA, docB>`的结构,以docA为例,输入`input_dim`的文档特征,依次变换成10维,1维特征,最终输入到RankCost层中,比较docA和docB在RankCost输出得到预测值。 上述结构中使用了和前述图表相同的模型结构,使用了两层隐藏层,分别使用了`hidden_size=10`的全连接层和`hidden_size=1`的全连接层。本例子中的input_dim指输入**单个文档**的特征的维度,label取值为1,-1。每条输入样本为`<label>,<docA, docB>`的结构,以docA为例,输入`input_dim`的文档特征,依次变换成10维,1维特征,最终输入到RankCost层中,比较docA和docB在RankCost输出得到预测值。
用户运行`python ranknet.py`将会将每个轮次的模型存下来,并在测试数据上测试效果。 用户运行只需要运行命令:
`python ranknet.py`
将会自动下载数据,训练RankNet模型,并将每个轮次的模型存下来,并在测试数据上测试效果。
## 用户自定义RankNet数据 ## 用户自定义RankNet数据
上面的代码使用了paddle内置的排序数据,如果希望使用自定义格式数据可以参考Paddle内置的`mq2007`数据集,编写一个生成器函数。例如输入数据为如下格式,只包含doc0-doc2三个文档。 上面的代码使用了paddle内置的排序数据,如果希望使用自定义格式数据可以参考Paddle内置的`mq2007`数据集,编写一个生成器函数。例如输入数据为如下格式,只包含doc0-doc2三个文档。
\<query_id\> \<relevance_score\> \<feature_vector\>的格式 \<query_id\> \<relevance_score\> \<feature_vector\>的格式(feature_vector采用libsvm数据格式)
``` ```
query_id : 1, relevance_score:1, feature_vector 0:0.1, 1:0.2, 2:0.4 #doc0 query_id : 1, relevance_score:1, feature_vector 0:0.1, 1:0.2, 2:0.4 #doc0
...@@ -195,8 +207,8 @@ def gen_pairwise_data(text_line_of_data): ...@@ -195,8 +207,8 @@ def gen_pairwise_data(text_line_of_data):
```python ```python
# Define the input data order # Define the input data order
feeding = {"label":0, feeding = {"label":0,
"left/data" :1, "left/data" :1,
"right/data":2} "right/data":2}
``` ```
...@@ -249,15 +261,17 @@ def lambdaRank(input_dim): ...@@ -249,15 +261,17 @@ def lambdaRank(input_dim):
return cost, output return cost, output
``` ```
上述结构中使用了和前述图表相同的模型结构,和RankNet相似,分别使用了`hidden_size=10`的全连接层和`hidden_size=1`的全连接层。本例子中的input_dim指输入**单个文档**的特征dense_vector的维度,label取值为1,-1。每条输入样本为label,\<docA, docB\>的结构,以docA为例,输入input_dim的文档特征,依次变换成10维,1维特征,最终输入到LambdaCost层中。需要注意这里的label和data格式为**dense_vector_sequence**,表示一列文档得分或者文档特征组成的**序列** 上述结构中使用了和前述图表相同的模型结构,和RankNet相似,分别使用了`hidden_size=10`的全连接层和`hidden_size=1`的全连接层。本例子中的input_dim指输入**单个文档**的特征的维度,label取值为1,-1。每条输入样本为label,\<docA, docB\>的结构,以docA为例,输入input_dim的文档特征,依次变换成10维,1维特征,最终输入到LambdaCost层中。需要注意这里的label和data格式为**dense_vector_sequence**,表示一列文档得分或者文档特征组成的**序列**
用户运行`python lambdaRank.py`将会把每个轮次的模型存下来,并在测试数据上测试效果。 用户运行只需要运行命令:
`python lambdaRank.py`
将会自动下载数据,训练LambdaRank模型,并将每个轮次的模型存下来,并在测试数据上测试效果。
## 自定义 LambdaRank数据 ## 自定义 LambdaRank数据
上面的代码使用了paddle内置的mq2007数据,如果希望使用自定义格式数据可以参考Paddle内置的`mq2007`数据集,编写一个生成器函数。例如输入数据为如下格式,只包含doc0-doc2三个文档。 上面的代码使用了paddle内置的mq2007数据,如果希望使用自定义格式数据可以参考Paddle内置的`mq2007`数据集,编写一个生成器函数。例如输入数据为如下格式,只包含doc0-doc2三个文档。
\<query_id\> \<relevance_score\> \<feature_vector\>的格式 \<query_id\> \<relevance_score\> \<feature_vector\>的格式
......
import os, sys import os, sys
import gzip import gzip
import sqlite3
import paddle.v2 as paddle import paddle.v2 as paddle
import numpy as np import numpy as np
import functools import functools
...@@ -39,7 +38,7 @@ def train_lambdaRank(num_passes): ...@@ -39,7 +38,7 @@ def train_lambdaRank(num_passes):
train_reader = paddle.batch( train_reader = paddle.batch(
paddle.reader.shuffle(fill_default_train, buf_size=100), batch_size=32) paddle.reader.shuffle(fill_default_train, buf_size=100), batch_size=32)
test_reader = paddle.batch( test_reader = paddle.batch(
paddle.reader.shuffle(fill_default_test, buf_size=100), batch_size=32) paddle.reader.buffered(fill_default_test, size=100), batch_size=32)
# mq2007 input_dim = 46, dense format # mq2007 input_dim = 46, dense format
input_dim = 46 input_dim = 46
......
...@@ -3,6 +3,13 @@ import unittest ...@@ -3,6 +3,13 @@ import unittest
def ndcg(score_list): def ndcg(score_list):
"""
measure the ndcg score of order list
https://en.wikipedia.org/wiki/Discounted_cumulative_gain
parameter:
score_list: np.array, shape=(sample_num,1)
"""
def dcg(score_list): def dcg(score_list):
n = len(score_list) n = len(score_list)
cost = .0 cost = .0
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册