Similar string search in Levenshtein-distance
Install
from source
git clone https://github.com/lovit/levenshtein_finder
cd levenshtein_finder
python setup.py install
from PyPI
pip install levenshtein_finder
Usage
Define Tokenizer
levenshtein_finder provides two basic tokenizers.
In [1]
from levenshtein_finder import CharacterTokenizer, BigramTokenizer
char_tokenizer = CharacterTokenizer()
bigram_tokenizer = BigramTokenizer()
char_tokenizer.tokenize("abc de") # ['a', 'b', 'c', ' ', 'd', 'e']
bigram_tokenizer.tokenize("abc de") # ['ab', 'bc', 'c ', ' d', 'de']
char_tokenizer.train("path/to/text") # or
char_tokenizer.train(["list", "of", "words"])
When you use word piece tokenizer in Huggingface's tokenizers, wrap the class instance with WordpieceTokenizersWrapper
In [2]
from tokenizers import BertWordPieceTokenizer
from levenshtein_finder import WordpieceTokenizersWrapper
tokenizer = WordpieceTokenizersWrapper(BertWordPieceTokenizer())
tokenizer.train("path/to/text")
tokenizer.tokenize("abc") # ["ab", "#c"]
tokenizer.encode("abc" # [53, 2]
tokenizer.decode(tokenizer.tokenize("abc")) # "abc"
Set tokenizer which Levenshtein Finder uses. Default is CharacterTokenizer
In [3]
from levenshtein_finder import LevenshteinFinder()
finder = LevenshteinFinder()
finder = LevenshteinFinder(BigramTokenizer())
finder = LevenshteinFinder(WordpieceTokenizersWrapper(BertWordPieceTokenizer()))
Indexing
In [4]
finder = LevenshteinFinder()
finder.indexing("path/to/text")
# when you use CharacterTokenizer or BigramTokenizer, you can index with list of words
finder.indexing(["list", "of", "words"])
Searching
Basic search. The form of similars is dict{term: distance}.
In [5]
finder.search("query")
If you want to check details in searching, set verbose=True
In [6]
finder.search("분식회계", verbose=True)
Out [6]
query : 분식회계
tokens : ['분', '식', '회', '계']
num data : 132864
num 1st candidates : 10137
num final candidates: 7
num similars : 4
elapsed time : 0.00542903 sec
[{'idx': 84243, 'data': '분식회계', 'distance': 0},
{'idx': 36211, 'data': '분식회', 'distance': 1},
{'idx': 113942, 'data': '분식회계설', 'distance': 1},
{'idx': 114122, 'data': '분석회계', 'distance': 1}]
For decomposing Korean to Jamo (NFKD)
To decompose Korean character to jamo components (감 -> [ㄱ, ㅏ, ㅁ]), use Normalizers.
In [7]
normalizer = Normalizers.create_normalizer(unicodedata=True)
tokenizer = CharacterTokenizer(normalizer=normalizer)
finder = LevenshteinFinder(tokenizer=tokenizer)
finder.indexing("text.txt")
finder.search("분식회계", verbose=True)
Out [7]
query : 분식회계
tokens : ['ᄇ', 'ᅮ', 'ᆫ', 'ᄉ', 'ᅵ', 'ᆨ', 'ᄒ', 'ᅬ', 'ᄀ', 'ᅨ']
num data : 132864
num 1st candidates : 125925
num final candidates: 4
num similars : 2
elapsed time : 0.0863643 sec
[{'idx': 84243, 'data': '분식회계', 'distance': 0},
{'idx': 114122, 'data': '분석회계', 'distance': 1}]
Demo
Searching similar words
LevenshteinFinder needs seconds.
In [8]
import json
with open("data/nouns_from_financial_news.json") as f:
words = list(json.load(f).keys())
finder = LevenshteinFinder()
finder.indexing(words)
finder.search("분식회계", verbose=True)
Out [8]
elapsed time : 0.00542903 sec
Brute-force distance computation needs 1.495 seconds
In [9]
import time
from levenshtein_finder import levenshtein
query = '분식회계'
begin_time = time.time()
distance = {word:levenshtein(word, query) for word in words}
search_time = time.time() - begin_time
print('search time = {} sec'.format('%.3f'%search_time))
similars = sorted(filter(lambda x:x[1] <= 1, distance.items()), key=lambda x:x[1])
elapsed_time = time.time() - begin_time
print('total elapsed time = {} sec'.format('%.3f'%elapsed_time))
print(similars)
Out [9]
search time = 1.480 sec
total elapsed time = 1.495 sec
[('분식회계', 0), ('분식회', 1), ('분식회계설', 1), ('분석회계', 1)]
Searching similar strings
Find similar sentence from NSMC corpus (20M).
In [10]
finder = LevenshteinFinder()
finder.indexing("~/Korpora/nsmc/corpus.txt")
finder.search("음악이 주가 된 최고의 음악영화", max_distance=1, verbose=True)
Out [10]
query : 음악이 주가 된 최고의 음악영화
tokens : ['음', '악', '이', ' ', '주', '가', ' ', '된', ' ', '최', '고', '의', ' ', '음', '악', '영', '화']
num data : 200002
num 1st candidates : 189663
num final candidates: 1
num similars : 1
elapsed time : 0.123322 sec
[{'idx': 6, 'data': '음악이 주가 된, 최고의 음악영화', 'distance': 1}]
Metadata
Release files for levenshtein-finder 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| levenshtein_finder-1.0.1.tar.gz | 7.1 kB | Without provenance | Details for levenshtein_finder-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| levenshtein_finder-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for levenshtein_finder-1.0.1-py3-none-any.whl |
Total release size: 17.7 kB
Release files / levenshtein_finder-1.0.1.tar.gz
| Download URL | levenshtein_finder-1.0.1.tar.gz |
|---|---|
| Size | 7.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
31539ac616f41f87d765501befa55ddf5390eadb0f4405397aba64c86d83dc1c
|
|
BLAKE2b-256 checksum How to use checksums |
b1a2a752dbf3eb467dd99402056508e680ab22f4256558bd21bdc32f40d41b84
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.7.9
|
Release files / levenshtein_finder-1.0.1-py3-none-any.whl
| Download URL | levenshtein_finder-1.0.1-py3-none-any.whl |
|---|---|
| Size | 10.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
be895db740fac66a185a8fbe79bd81a7be48caa0548aabfc0c0b81a60c8fafa6
|
|
BLAKE2b-256 checksum How to use checksums |
627d23cfd25ac805f4ea30adbabeb8c5cb518a7d29e44eb1275b52f306667314
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.7.9
|
Security for levenshtein-finder 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.