Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
外国人が日本語の検索機能をElasticsearchで作ってみた
Sunggyu 'KEI' Rhie
December 19, 2018
Technology
2
470
外国人が日本語の検索機能をElasticsearchで作ってみた
外国人だから日本語検索は難しいの?
実は日本語検索自体が大変なんじゃない?
じゃどう作っていくの?
をElasticsearchで解決してみました
Sunggyu 'KEI' Rhie
December 19, 2018
Tweet
Share
More Decks by Sunggyu 'KEI' Rhie
See All by Sunggyu 'KEI' Rhie
r4keisuke
4
1.4k
Other Decks in Technology
See All in Technology
futo23
1
300
sat
40
29k
you
0
280
zak3
1
190
iwashi86
54
24k
ayanadesu
0
380
optim
0
200
koukyo1994
3
440
sadayoshitada0919
0
280
yasuyukiyamasaki
1
160
ocise
1
1.8k
hanacchi
0
150
Featured
See All Featured
skipperchong
8
710
maggiecrowley
10
500
malarkey
193
8.6k
roundedbygravity
84
7.9k
frogandcode
128
20k
malarkey
119
16k
jrom
116
7.2k
andyhume
63
3.7k
roundedbygravity
242
21k
orderedlist
PRO
328
36k
smashingmag
283
47k
sachag
446
36k
Transcript
1 外国人が日本語の検索機能を Elasticsearchで実装してみました 李 晟圭
自己紹介 李 晟圭(イ・ソンギュ) 韓国出身 2016年からRetty在籍中 WEB/Search Team Engineering Manager 最近は事業成長に貢献(のつもり) しながら
技術的挑戦や組織作り・育成 などを主に
日本最大級の実名グルメサービス「Retty」 実名制 オススメの口コミ 友人との「つながり」 口コミ内容はポジティブな“おすすめ”で きるお店を投稿。 点数評価ではありません。 Rettyのサービス内で“友人”や“食の 嗜好が合う同士”がフォロー機能でつ ながっているSNS型です。
実名制口コミの信頼度が非常に高いグ ルメサービスです。 2011年6月にサービスを開始した実名グルメサービス「 Retty」は、 グルメに強いこだわりを持つ方々を中心に、 「オススメ」したいお店の情報を実名ベースでご 投稿いただく形で運営しています。 「自分にベストなお店が見つかる」グルメサービスとして、 20~40代の男女を中心に、 幅広い年代にご利用いただいていま す。
スマホ時代の実名グルメサービス「Retty」 月間利用者数4,000万人突破(2018年11月時点)
ユーザーさんのニーズに合わせた 良いお店を発見できることが 究極的な価値である グルメサービスには検索は必須
エリア ✕ ジャンル ✕ 目的 恵比寿 ✕ 焼き鳥 ✕ デート よくある検索
店名 鳥はな 焼き鳥屋佐藤 炭火焼き鳥江戸屋 よくある検索 ※全ての店名はこのスライドのために適当に作った架空の店名です。 実在する店舗の名前とかぶることがあってもそれは偶然なので、特定お店を取り上げてるつもりはございませんのでご容赦ください。
内容が膨らみすぎて店名にしぼりました ここでお詫び
Lサイズ靴下3足でなんと500円! 日本語では普通の表現
Lサイズ靴下3足でなんと500円! ひらがな、カタカナ、 漢字(よみがな、ふりがな)、 ローマ字、アラビア数字が 字空きなく書かれている 外国人からすると
Lサイズ靴下3足でなんと500円! でもこれでも意味がわかる
L サイズ 靴下 3 足 で なんと 500 円 !
脳内形態素解析発動 でもこれでも意味がわかる
単純に日本語に慣れてないから? 脳内形態素解析用辞書がまだまだだから? 結局外国人として難しいのは
「店名」なので 店主が好きなように決められる 日本語もその範囲を狭めて店名にすると
やきとん はなまる 鮨一 ラ・グランベリー・ルージュー The Farmer’s Cuisine ラーメン234 店名の例 ※全ての店名はこのスライドのために適当に作った架空の店名です。
実在する店舗の名前とかぶることがあってもそれは偶然なので、特定お店を取り上げてるつもりはございませんのでご容赦ください。
博多らぁめん屋ウマウマTONKOTSU〜豚骨〜246 沿い店 店名の例 ※全ての店名はこのスライドのために適当に作った架空の店名です。 実在する店舗の名前とかぶることがあってもそれは偶然なので、特定お店を取り上げてるつもりはございませんのでご容赦ください。
友達 店名の例
友達 店名の例 フレンド
外来語や固有名詞のなどは分かち書きや 固有名詞の漢字の読み方は 日本人もわからないことがよくある 結局外国人だからとかじゃない
脳内形態素解析に対応できる辞書はない 検索機能として作るには
ユーザさんは必ずしも 形態素解析や分かち書きのとおりに 検索するとは限らない 検索機能として作るには
ngramでいいのでは? 検索機能として作るには
適合率と再現率 つまり質か量か 検索機能として作るには
課題1:分かち書きできない固有名詞 課題2:想定できない読み仮名 課題3:一定レベルの質担保 課題4:ユーザーさんは店名を覚えていない 課題
なんでElasticsearchでやるの? は省略します! Elasticsearchで解決してみましょう
Analyzerは、新語・造語に強い mecab-ipadic-NEologdを使うので Kuromoji-NEologd with 自家製辞書 + ICU analysis を基本に Elasticsearchで解決してみましょう
Normalizeは ICU Normalizerに 任せるとして Elasticsearchで解決してみましょう
まずは「正式店名」 お店さんが公式とする店名 課題1:分かち書きできない固有名詞
やきとん はなまる 鮨一 ラ・グランベリー・ルージュー The Farmer’s Cuisine ラーメン123 正式名称の例
空白文字 記号(・、’〜など)で 区切ってみる 正式名称のTokenize
「やきとん」 「はなまる」 「鮨一」 「ラ」「グランベリー」「ルージュー」 「The」「Farmer」「s」「Cuisine」 「ラーメン」「123」 正式名称のTokenize
ラ・グランベリー・ルージュー →「ラ」「グランベリー」「ルージュー」 これでは「ラグランベリー」というクエリではヒットしな くなる 正式名称のTokenize
ラ・グランベリー・ルージュー →「ラ」「グランベリー」「ルージュー」 →「ラグランベリールージュー」 の2パターンを用意する 正式名称のTokenize
ラ・グランベリー・ルージュー →「ラ」「グランベリー」「ルージュー」 →「ラグランベリールージュー」 の2パターンを用意する 正式名称のTokenize 各Token毎の 完全一致と前方部分一致で検索できる
ラ・グランベリー・ルージュー →「ラ」「グランベリー」「ルージュー」 →「ラグランベリールージュー」 の2パターンを用意する 正式名称のTokenize なんか「ランベリー」とかのお店だったよね? →はい、これはngramで
正式名称のAnalyze ラ・グランベリー・ルージュー 全部つなげた前方一致用Analyzer TokenizeしたToken毎前方一致用Analyzer 部分一致用Analyzer の3種を用意する
全部つなげた前方一致Analyzerは Char Filter:記号削除 Tokenizer:edge ngram
課題2:想定できない読み仮名 次は読み仮名
やきとん はなまる 鮨一 ラ・グランベリー・ルージュー The Farmer’s Cuisine ラーメン123 友達 内房
正式名称の例
やきとん はなまる:やきとん はなまる 鮨一:すしいち ラ・グランベリー・ルージュー:ら ぐらんべりー るーじゅー The Farmer’s Cuisine:ふぁーまーず
くいじん ラーメン123:らーめん ひふみ 友達:ふろんど 内房:あんぱん 読み仮名の例 ※全ての店名はこのスライドのために適当に作った架空の店名です。 実在する店舗の名前とかぶることがあってもそれは偶然なので、 特定お店を取り上げてるつもりはございませんのでご容赦ください。
そんなのはない 読み仮名の解決策
データを確保し 正式名称と同じ形で Analyzerを配置する 課題2:想定できない読み仮名
できたと思ったら ラ・グランベリー・ルージューって 英語表記もあるらしい La Grandberry Rouge
課題追加:英語名称 La Grandberry Rouge ユーザさんは投げます、berry
課題1と2+αを解決するには Analyzerの数=Fieldの数 正式名称×3 読み仮名×3 英語名称×3 を用意して基本はできた
課題3:一定レベルの質担保 質とは クエリに対して 探している店舗が 表示されること
課題3:一定レベルの質担保 質と量はトレードオフ しかし表示されないお店があってはならない
課題3:一定レベルの質担保 より合致しそうなお店を ユーザーさんに早く届ければいい つまりスコアリングで表示順を上にする
課題3:一定レベルの質担保 1. 完全一致 2. 前方一致 3. Token毎前方一致 4. 部分一致
課題3:一定レベルの質担保 クエリによるスコアリングは 実際はたくさんの変数の中の一つである ユーザさんが求めるものに 近づけるための最低限の担保
課題4:ユーザさんは店名を覚えていない 「ユーザさんが求めるものに 近づけるための最低限の担保」 店名がはっきりわからないからこそ 検索がある
課題4:ユーザさんは店名を覚えていない 激辛ラーメン鳳の爪 激辛ラーメン凰の爪
課題4:ユーザさんは店名を覚えていない Fuzziness
Fuzziness レーベンシュタイン距離を用いて 文字数によって数文字ぐらいの 誤差は許す
Fuzziness 激辛ラーメン鳳の爪 激辛ラーメン凰の爪 どっちもヒットする!
Fuzziness 鳳の爪 凰の爪 1文字違うけど1/3なので
Fuzzinessは質を落とす あのね そのね このね どのね 1文字違うけど1/3なので
Fuzzinessは質を落とす 質への影響が激しいので 使うときには アプリケーションでの調整などで 制限的に使う
すべての課題がElasticsearchで解決! ここまでやって やっと「探してる店舗が表示されない」 という問い合わせが来なくなりました 一応成功
すべての課題がElasticsearchで解決! ここで余談
すべての課題がElasticsearchで解決! Rettyはグローバル展開してます 香港とタイ
タイのユーザさんに言われました まだまだだね
一緒にやってくれる方、ぜひ 助けてください
終わり ご清聴ありがとうございました