Rabbit Slide Show

続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法

Description

* Event: https://foss4g.hokkaido.jp/2026 * Blog: https://www.clear-code.com/blog/2026/11/11/nominatim-penalty-tuning-for-cjk.html

Text

Page: 1

続・Nominatimが広島平和記念
資料館を見つけられない理由とそ
の解決方法
阿部 智晃
ClearCode Inc.
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 2

自己紹介
✓ 阿部 智晃
✓ GitHub: abetomo
✓ 株式会社クリアコード
✓ FOSSの開発・サポートを仕事にしている
✓ 全文検索エンジンの開発が主
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 3

FOSS4G 2026 Hiroshima
「広島平和記念資料館」が見つからない
✓ 原因: 検索最適化が裏目に出る
✓ 漢字は中国語の読み
✓ 解決: PGroonga(PostgreSQLの拡張機能)
で全文検索!
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 4

「北海道大学付属
図書館」も見つか
らない!

Page: 5

見つからない!を確認
北海道大学付属図書館 で検索
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 6

「本館」なら見つかる
北海道大学付属図書館本館 で検索
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 7

今回のお話
✓ PostgreSQLの拡張機能の追加なしでなんと
か見つけたい!
✓ 「検索最適化が裏目に出る」を改善
✓ Pythonのコードを50行くらいで実現
✓ データの再構築なしでOK
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 8

なぜ見つけられないか
「ペナルティ」がいい
感じに設定されないか
ら。
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 9

お知らせ
このあと「ペナルティ」についての説明をして
いきますが、わかりやすさ優先のため単純化
しています。
ご了承ください。
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 10

前提: 検索クエリーは分割される
クエリーも登録名も単語に分割して照合する
✓ Hokkaido University Library
✓ => Hokkaido | University | Library
✓ 分割した単語ごとに「ペナルティ」を計算
して組み合わせる
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 11

ペナルティ
単語どうしのくっつきやすさ。
✓ 「北海」と「道」: くっつきやすい => 0
✓ 「北海」と「阿部」: くっつきにくい => 0.5
値が小さいほど、より良い組み合わせと見なす
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 12

ペナルティがいい感じに設定されない
✓ 漢字(日本語・中国語)は1文字区切り
✓ 北|海|道|大|学|付|属|図|書|館
✓ 形態素解析はしない
✓ 意味を無視 => 「くっつきやすさ」が分からない
✓ クエリーが長いほどペナルティが高くなる
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 13

検索クエリーが長いとペナルティ高
| ごとにペナルティ0.3
✓ 長: 北|海|道|大|学|付|属|図|書|館
✓ 0.3 * 9 = 2.7
✓ 短: 北|海|道
✓ 0.3 * 2 = 0.6
✓ 短いクエリーは影響を受けにくい
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 14

ペナルティ高の補足
単語で分割ならペナルティは低くなるはず
例: 北海道|大学|付属|図書館
✓ 「北海道|大学」はくっつきやすい => 0
✓ 全部くっつきやすければ 0 + 0 + 0 = 0
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 15

なぜ高いと見つからないか
1. 名前と住所の分け方の候補をたくさん作る
2. ペナルティの小さい順に試す
3. 最小の候補 + 1.5 を超えたら打ち切り
正解の候補はあるのに、高すぎて使われない
候補の詳細はFOSS4G 2026 Hiroshimaの資料の巻末を参照
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 16

今回のアイディア
ペナルティを適切に設定するために日本語の
分割を改善して…は大変。
日本語(特に漢字)が連続するものはペナル
ティを低めにすると良いのでは?
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 17

今回のアイディア: 具体例
北|海|道|大|学|付|属|図|書|館
✓ Before: | ごとに0.3
✓ 0.3 * 9 = 2.7
✓ After: | の前後が日本語なら0.1
✓ 0.1 * 9 = 0.9
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 18

実装
追加したコードの一部
PENALTY_CJ_CHAR = 0.1
# ...略
def get_cj_partial_penalty(self, trange: TokenRange) -> float:
penalty = self.nodes[trange.start].partial.penalty
for pos in range(trange.start + 1, trange.end):
if self.is_cj_continuation(pos): # 日本語が続いていたら
penalty += PENALTY_CJ_CHAR # ペナルティは0.1
else: # そうでなかったら既存のペナルティの追加
node = self.nodes[pos]
penalty += node.partial.penalty + node.word_break_penalty
return penalty
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 19

デモ: ペナルティ改善なし
docker compose exec -e NOMINATIM_CJK_PENALTY=off nominatim \
nominatim search --query "広島平和記念資料館"
docker compose exec -e NOMINATIM_CJK_PENALTY=off nominatim \
nominatim search --query "北海道大学付属図書館"
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 20

デモ: ペナルティ改善あり
docker compose exec -e NOMINATIM_CJK_PENALTY=on nominatim \
nominatim search --query "広島平和記念資料館"
docker compose exec -e NOMINATIM_CJK_PENALTY=on nominatim \
nominatim search --query "北海道大学付属図書館"
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 21

副作用
見つからなくても良さそうなデータも見つか
る…。
私は真に驚くべき解説をここでしたいが、このスライドはそれを書くには狭すぎるの
で、ブログ記事で解説します。https://www.clear-code.com/blog/2026/11/11/
nominatim-penalty-tuning-for-cjk.html
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 22

効果がある範囲
✓ 日本語(J): 今回発表した通り
✓ 中国語(C): 未検証
✓ 同様に分割されるので効果はあると思われる
✓ 韓国語(K)には効果なし
✓ 1文字ずつ分割されないので前提が違う
✓ 先ほどの実装例がcjだったのはこのため
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 23

他のアプローチ
✓ ICUのBreakIteratorで分割できそう
✓ 広島|平和|記念|資料館
✓ ただしインポート全体に影響
✓ 全言語・全データで要検証
もっと良いアイディアがあれば教えてくださ
い!
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 24

まとめ
✓ ペナルティがいい感じに設定されていな
かった
✓ 日本語が連続するものはペナルティを低めにして改
善
✓ そもそも1文字ずつの分割がよくない
✓ ここから改善できるとより良い
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 25

関連リンク
✓ 本PoC(ペナルティ調整)
✓ https://github.com/abetomo/Nominatim
✓ penalty-tuning-for-cjkブランチ
✓ デモ環境
✓ https://github.com/abetomo/Nominatim-docker-
compose
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Page: 26

ありがとうございました
✓ Email: abe@clear-code.com
✓ GitHub: abetomo
✓ この発表の解説記事
✓ https://www.clear-code.com/blog/2026/11/11/
nominatim-penalty-tuning-for-cjk.html
続・Nominatimが広島平和記念資料館を見つけられない理由とその解決方法
Powered by Rabbit 4.0.1

Other slides