我尝试在Elasticsearch中使用Learning-to-Rank!
此文是《集体 AdventCalendar 2019》的第21天文章。
首先
因为在最近的一天里,我被委托负责”我想在Elasticsearch上进行Learning-to-rank,所以请总结一下环境搭建的步骤和使用方法。拜托了!”所以这次我将介绍Elasticsearch与learning-to-rank的构建步骤和使用方法。
这次制作的是这个。
学习排序是指
在搜索引擎中,学习排序是一种利用机器学习和搜索数据来改善搜索结果排名顺序的方法。它也被称为顺序学习或排序学习。
这次,我们将使用 Elasticsearch 的 learning-to-rank 插件。我想通过使用 learning-to-rank 仓库中的示例,体验一下排序的改善。
环境建设
为了测试demo,我们需要事先进行以下环境搭建。
-
- Java の実行環境
-
- Python3 の実行環境
-
- Elasticsearch に learning-to-rank プラグインを導入
https://github.com/elastic/elasticsearch
https://github.com/o19s/elasticsearch-learning-to-rank
使用带有插件的 Elasticsearch 的构建,使用 Docker 镜像会更方便。
- https://hub.docker.com/_/elasticsearch
以下是Elasticsearch带有Learning-to-Rank Docker镜像的示例。
FROM elasticsearch:7.4.1
RUN bin/elasticsearch-plugin install -b http://es-learn-to-rank.labs.o19s.com/ltr-1.1.2-es7.4.1.zip
在环境构建完成后,将 Learning-to-Rank 存储库克隆并移动到演示目录下。
$ git clone https://github.com/o19s/elasticsearch-learning-to-rank.git
$ cd elasticsearch-learning-to-rank/demo
在进入demo文件夹后,按顺序执行脚本来体验Learning-to-Rank!
准备数据和库。
运行prepare.py,下载用于创建搜索数据和学习模型的库(Ranklib)。
$ python prepare.py
下载后, 会下载电影数据(tmdb.json)和排名学习库(RankLibPlus-0.1.0.jar)。请注意,由于tmdb.json文件较大,下载可能需要一些时间。
下载完成后,我们将准备Elasticsearch环境。
设置Elasticsearch环境
启动安装了Learning-to-Rank插件的Elasticsearch,并将数据输入其中。在Elasticsearch启动后,执行index_ml_tmdb.py脚本进行索引设置和数据插入。执行以下脚本将tmdb.json插入Elasticsearch中。
$ python index_ml_tmdb.py
完成设置索引和插入数据后,接下来需要设置用于学习的特征转换查询。执行以下脚本可设置用于学习的字段。(设置的字段可参考 demo/1.json 和 demo/2.json。在 demo 中,将标题和概述的搜索分数设置为特征。)
$ python load_features.py
當將數據準備好轉換為特徵欄位時,我們將開始建立模型。
将模型部署到Elasticsearch中
运行 train.py 脚本以创建模型,并将其部署到 Elasticsearch 中。
$ python train.py
在train.py文件中,将执行以下处理。
-
- 前処理
sample_judgements.txt をパースして、ranklib format に変換する。
モデル生成
Ranklib を実行して、モデル作成を行います。
モデルのデプロイ
Easticsearch にモデルを導入する。
数据预处理 (Data preprocessing)
在demo中,我们将使用sample_judgements.txt进行学习,以改善搜索结果的排名。sample_judgements.txt包含了针对搜索查询(qid)的搜索结果(#7555 Rambo,#1370 Rambo III,…),并为每个搜索查询和搜索结果的组合设置了评分(grade)。demo中包含以下三种查询。
# qid:1: rambo
# qid:2: rocky
# qid:3: bullwinkle
对于每个查询的搜索结果,请设置一个等级(数字越大越好)。
# grade (0-4) queryid docId title
4 qid:1 # 7555 Rambo
3 qid:1 # 1370 Rambo III
3 qid:1 # 1369 Rambo: First Blood Part II
3 qid:1 # 1368 First Blood
0 qid:1 # 136278 Blood
0 qid:1 # 102947 First Daughter
0 qid:1 # 13969 First Daughter
0 qid:1 # 61645 First Love
0 qid:1 # 14423 First Sunday
0 qid:1 # 54156 First Desires
4 qid:2 # 1366 Rocky
3 qid:2 # 1246 Rocky Balboa
3 qid:2 # 60375 Rocky VI
3 qid:2 # 1371 Rocky III
3 qid:2 # 1375 Rocky V
3 qid:2 # 1374 Rocky IV
0 qid:2 # 110123 Incredible Rocky Mountain Race
0 qid:2 # 17711 The Adventures of Rocky & Bullwinkle
0 qid:2 # 36685 The Rocky Horror Picture Show
4 qid:3 # 17711 The Adventures of Rocky & Bullwinkle
0 qid:3 # 1246 Rocky Balboa
0 qid:3 # 60375 Rocky VI
0 qid:3 # 1371 Rocky III
0 qid:3 # 1375 Rocky V
0 qid:3 # 1374 Rocky IV
将这个数据转换为 Ranklib 格式,将会得到以下数据。
4 qid:1 1:12.318474 2:10.573917 # 7555 rambo
3 qid:1 1:10.357875 2:11.950391 # 1370 rambo
3 qid:1 1:7.010513 2:11.220095 # 1369 rambo
3 qid:1 1:0.0 2:11.220095 # 1368 rambo
0 qid:1 1:0.0 2:0.0 # 136278 rambo
0 qid:1 1:0.0 2:0.0 # 102947 rambo
0 qid:1 1:0.0 2:0.0 # 13969 rambo
0 qid:1 1:0.0 2:0.0 # 61645 rambo
0 qid:1 1:0.0 2:0.0 # 14423 rambo
0 qid:1 1:0.0 2:0.0 # 54156 rambo
4 qid:2 1:10.686391 2:8.814846 # 1366 rocky
3 qid:2 1:8.985554 2:9.984511 # 1246 rocky
3 qid:2 1:8.985554 2:8.067703 # 60375 rocky
3 qid:2 1:8.985554 2:5.660549 # 1371 rocky
3 qid:2 1:8.985554 2:7.300772 # 1375 rocky
3 qid:2 1:8.985554 2:8.814846 # 1374 rocky
0 qid:2 1:6.815921 2:0.0 # 110123 rocky
0 qid:2 1:6.0816855 2:8.725066 # 17711 rocky
0 qid:2 1:6.0816855 2:5.9764795 # 36685 rocky
4 qid:3 1:7.6720834 2:12.722421 # 17711 bullwinkle
0 qid:3 1:0.0 2:0.0 # 1246 bullwinkle
0 qid:3 1:0.0 2:0.0 # 60375 bullwinkle
0 qid:3 1:0.0 2:0.0 # 1371 bullwinkle
0 qid:3 1:0.0 2:0.0 # 1375 bullwinkle
0 qid:3 1:0.0 2:0.0 # 1374 bullwinkle
我将使用这些数据来进行模型创建。
生成模型 mó
创建模型。在演示中,将生成以下模型。
-
- MART
-
- RankNet
-
- RankBoost
-
- AdaRank
-
- coord Ascent
-
- LambdaMART
-
- ListNET
-
- Random Forest
- Linear Regression
关于各个型号的详细信息,本次我们将省略不提。
模型上传
将模型上传到Elasticsearch。使用POST请求上传生成的模型。以下是示例。
POST _ltr/_featureset/movie_features/_createmodel
{
"model": {
"name": "test_9",
"model": {
"type": "model/ranklib",
"definition": "## Linear Regression\n## Lambda = 1.0E-10\n0:0.2943936467995844 1:0.2943936467995844 2:0.12167703031808977"
}
}
}
当您使用已上传的模型进行搜索时,请指定model.name。
搜索
让我们亲自搜索一下,体验一下通过Learning-to-Rank来改进搜索结果的效果!当运行search.py时,将获得以下搜索结果。
$ python search.py Rambo
{"query": {"multi_match": {"query": "Rambo", "fields": ["title", "overview"]}}, "rescore": {"query": {"rescore_query": {"sltr": {"params": {"keywords": "Rambo"}, "model": "test_6"}}}}}
Rambo
Rambo III
Rambo: First Blood Part II
First Blood
In the Line of Duty: The F.B.I. Murders
Son of Rambow
Spud
$
因为很难理解,所以我准备了一个比较有无Learning-to-Rank的结果。分别可以得到以下结果。
## search with learning-to-rank
1 Rambo
2 Rambo III
3 Rambo: First Blood Part II
4 First Blood
5 In the Line of Duty: The F.B.I. Murders
6 Son of Rambow
7 Spud
## search without learning-to-rank
1 Rambo
2 Rambo III
3 First Blood
4 Rambo: First Blood Part II
5 In the Line of Duty: The F.B.I. Murders
6 Son of Rambow
7 Spud
你的学习成果有所体现啊!
概括
这次我们介绍了在 Elasticsearch 中尝试 Learning-to-rank 的步骤,并成功将 Learning-to-rank 应用到搜索引擎中。为了方便大家试用,我们将本次使用的库整理到了仓库中,希望您能使用它。
另外,在本文中我们介绍了执行步骤,但如果有机会的话,我也希望能介绍更详细的内容,例如 Learning-to-rank 的各个逻辑以及本次使用的库的机制。