File size: 1,230 Bytes
a828eeb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import json

PAD, BOS, EOS, UNK = 0, 1, 2, 3
SPECIALS = ["<pad>", "<bos>", "<eos>", "<unk>"]

class CharTokenizer:
    def __init__(self, vocab=None):
        self.vocab = vocab or {}
        self.inv = {i: c for c, i in self.vocab.items()}

    @classmethod
    def build(cls, texts, min_freq=20):
        from collections import Counter
        cnt = Counter()
        for t in texts:
            cnt.update(t)
        vocab = {s: i for i, s in enumerate(SPECIALS)}
        for ch, freq in sorted(cnt.items()):
            if freq >= min_freq:
                vocab[ch] = len(vocab)
        return cls(vocab)

    def encode(self, text, add_special=True):
        ids = [self.vocab.get(c, UNK) for c in text]
        return [BOS] + ids + [EOS] if add_special else ids

    def decode(self, ids):
        return "".join(self.inv.get(i, "") for i in ids
                       if i not in (PAD, BOS, EOS, UNK))

    def save(self, path):
        with open(path, "w", encoding="utf-8") as f:
            json.dump(self.vocab, f, ensure_ascii=False)

    @classmethod
    def load(cls, path):
        with open(path, encoding="utf-8") as f:
            return cls(json.load(f))

    def __len__(self):
        return len(self.vocab)