In their paper
"Deep Squared Euclidean Approximation to the Levenshtein Distance for DNA Storage", Guo et al. explore techniques for using a neural network to embed sequences in such a way that the squared Euclidean distance between embeddings approximates the Levenshtein distance between the original sequences. This implementation also takes techniques from
"Levenshtein Distance Embeddings with Poisson Regression for DNA Storage" by Wei et al. (2023).
This is valuable because there are excellent libraries for doing fast GPU accelerated searches for the K nearest neighbors of vectors, like
faiss. Algorithms like
HNSW allow us to do these searches in logarithmic time, where a brute force levenshtein distance based fuzzy search would need to run in exponential time.
This repo contains a PyTorch implementation of the core ideas from Guo's paper, adapted for ASCII sequences rather than DNA sequences. The implementation includes:
The trained model learns to embed ASCII strings such that the squared Euclidean distance between embeddings approximates the true Levenshtein distance between the strings.
The model uses a 5-layer CNN with average pooling followed by fully connected layers to produce fixed-size embeddings from variable-length ASCII sequences.
1import torch
2from models import EditDistanceModel
3
4# Load the model
5model = EditDistanceModel(embedding_dim=140)
6model.load_state_dict(torch.load('megashtein_trained_model.pth'))
7model.eval()
8
9# Embed strings
10def embed_string(text, max_length=80):
11 # Pad and convert to tensor
12 padded = (text + '\0' * max_length)[:max_length]
13 indices = [min(ord(c), 127) for c in padded]
14 tensor = torch.tensor(indices, dtype=torch.long).unsqueeze(0)
15
16 with torch.no_grad():
17 embedding = model(tensor)
18 return embedding
19
20# Example usage
21text1 = "hello world"
22text2 = "hello word"
23
24emb1 = embed_string(text1)
25emb2 = embed_string(text2)
26
27# Compute approximate edit distance
28approx_distance = torch.sum((emb1 - emb2) ** 2).item()
29print(f"Approximate edit distance: {approx_distance}")