実行環境
Python 3.8.8
macOS Catalina v10.15.4
インストール
今回はpython-Levenshtein
というライブラリを使用する
% conda install python-Levenshtein
目的
お茶、お〜いお茶、茶のように似ている単語を見つける。
今回はラーメン、うどん、中華麺、麺、カレー、ドラえもん
の中からラーメンと似ている物を探す。
前処理
まず日本語の場合漢字から全てひらがなにしなければならない。
>>> from pykakasi import kakasi
>>> word_list = ["ラーメン", "うどん", "中華麺", "麺", "カレー", "ドラえもん"]
>>> kks = kakasi()
>>> hira_word_list = []
>>> for word in word_list:
... result = kks.convert(word)
... new_word = ""
... for res in result:
... new_word += res['hira']
... hira_word_list += [new_word]
...
>>> hira_word_list
['らーめん', 'うどん', 'ちゅうかめん', 'めん', 'かれー', 'どらえもん']
ゲシュタルトパターンマッチング
標準ライブラリdifflib
を使って求められる。
>>> import difflib
>>> for hira_word in hira_word_list:
... similarity = difflib.SequenceMatcher(None, "らーめん", hira_word).ratio()
... print(f"{hira_word}の類似度 : {similarity}")
...
らーめんの類似度 : 1.0
うどんの類似度 : 0.2857142857142857
ちゅうかめんの類似度 : 0.4
めんの類似度 : 0.6666666666666666
かれーの類似度 : 0.2857142857142857
どらえもんの類似度 : 0.4444444444444444
中華麺よりドラえもんの方が類似度が高い。
レーベンシュタイン距離
>>> import Levenshtein
>>> # Levenshtein距離を標準化する
>>> def lev_dist(str1, str2):
... return 1 - (Levenshtein.distance(str1, str2) / max(len(str1), len(str2)))
...
>>> for hira_word in hira_word_list:
... similarity = lev_dist('らーめん', hira_word)
... print(f"{hira_word}の類似度 : {similarity}")
...
らーめんの類似度 : 1.0
うどんの類似度 : 0.25
ちゅうかめんの類似度 : 0.33333333333333337
めんの類似度 : 0.5
かれーの類似度 : 0.0
どらえもんの類似度 : 0.4
中華麺の類似度が0.3と低いのに対して、ドラえもんは0.4ある。
ジャロ・ウィンクラー距離
>>> for hira_word in hira_word_list:
... similarity = Levenshtein.jaro_winkler('らーめん', hira_word)
... print(f"{hira_word}の類似度 : {similarity}")
...
らーめんの類似度 : 1.0
うどんの類似度 : 0.5277777777777778
ちゅうかめんの類似度 : 0.611111111111111
めんの類似度 : 0.0
かれーの類似度 : 0.5277777777777778
どらえもんの類似度 : 0.6333333333333333
めんの類似度が0である一方、ドラえもんの類似度が0.633もある
ジャロ・ウィンクラー距離は位置はあまり関係しない。
結果、考察
中華麺よりドラえもんの方がラーメンに似ている。
ドラえもんより中華麺の方が類似度を高くするためにまず形態素解析で中華 + 麺
とした方がいいと思う
そもそもラーメンが麺に似ているのはたまたまで、ラーメンがスパゲティだったら麺に似ていない。