๐ ๋ชฉ์ฐจ
0. preprocessing
1. corpus ์์ง
2. Normalization
3. ๋ฌธ์ฅ๋จ์ tokenization
4. tokenization (ํ๊ตญ์ด, ์์ด, ์ค๊ตญ์ด)
5. parallel corpus ์ ๋ ฌ
6. subword tokenization (BPE Algorithm & UK, OOV)
7. Detokenization (๋ถ์ ํ ๋ณต์)
8. torchText ๋ผ์ด๋ธ๋ฌ๋ฆฌ
0. Preprocessing
0.1 corpus
corpus๋ ๋ง๋ญ์น๋ผ๊ณ ๋ ๋ถ๋ฆฌ๋ฉฐ ๋ณดํต ์ฌ๋ฌ๋จ์ด๋ค๋ก ์ด๋ฃจ์ด์ง ๋ฌธ์ฅ์ ์๋ฏธ.
train data๋ฅผ ์ํด ์ด๋ฐ ๋ค์์ ๋ฌธ์ฅ์ผ๋ก ๊ตฌ์ฑ๋ corpus๊ฐ ํ์ํ๋ค.
โ monolingual corpus: ํ ๊ฐ์ง ์ธ์ด๋ก ๊ตฌ์ฑ๋ corpus
โ bilingual corpus: ๋ ๊ฐ์ ์ธ์ด๋ก ๊ตฌ์ฑ๋ corpus
โ multilingual corpus: ๋ ๋ง์ ์์ ์ธ์ด๋ก ๊ตฌ์ฑ๋ corpus
โ parallel corpus: ์ธ์ด๊ฐ์ ์(ex.์๋ฌธ-ํ๊ธ)์ผ๋ก ๊ตฌ์ฑ๋ corpus
0.2 preprocessing ๊ณผ์ ๊ฐ์
โ corpus ์์ง
โก Normalize
โข ๋ฌธ์ฅ๋จ์ Tokenize
โฃ Tokenize
โค parallel corpus ์ ๋ ฌ
โฅ subword tokenize
1. Corpus ์์ง
corpus๋ฅผ ์์งํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋๋ฐ, ๋ฌด์์ ์น์ฌ์ดํธ์์ corpus ํฌ๋กค๋ง์ ํ๋ฉด ๋ฒ์ ๋ฌธ์ ๊ฐ ๋ ์ ์๋ค.
์ ์๊ถ์ ๋ฌผ๋ก , ๋ถํ์ํ ํธ๋ํฝ์ด ์น์๋ฒ์ ๊ฐ์ค๋๋ ๊ณผ์ ์์ ๋ฌธ์ ๋ฐ์๊ฐ๋ฅ
๋ฐ๋ผ์ ์ ์ ํ ์น์ฌ์ดํธ์์ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ or ์์ ์ ๋ชฉ์ ์ด ์๋ ๊ฒฝ์ฐ๋ก ์ ํ๋ ํฌ๋กค๋ง์ด ๊ถ์ฅ๋๋ค.
ํด๋น ์น์ฌ์ดํธ์ ํฌ๋กค๋ง ํ์ฉ์ฌ๋ถ๋ ์ฌ์ดํธ์ robots.txt๋ฅผ ๋ณด๋ฉด ๋๋ค.
ex) TED์ robot.txt ํ์ธ๋ฐฉ๋ฒ

1.1 monolingual corpus ์์ง
๊ฐ์ฅ ์ฝ๊ฒ ๊ตฌํ ์ ์๋ corpus(์ธํฐ๋ท์ ๊ทธ๋ฅ ๋๋ ค์๊ธฐ ๋๋ฌธ)์ด๊ธฐ์ ๋๋์ corpus๋ฅผ ์์ฝ๊ฒ ์ป์ ์ ์๋ค.
๋ค๋ง, ์ฌ๋ฐ๋ฅธ ๋๋ฉ์ธ์ corpus๋ฅผ ์์ง, ์ฌ์ฉ๊ฐ๋ฅํ ํํ๋ก ๊ฐ๊ณตํ๋ ๊ณผ์ ์ด ํ์ํ๋ค.
1.2 multilingual corpus ์์ง
์๋ ๊ธฐ๊ณ๋ฒ์ญ์ ์ํ parallel corpus๋ฅผ ๊ตฌํ๊ธฐ๋ monolingual corpus์ ๋นํด ์๋นํ ์ด๋ ต๊ณ
'he'์ 'she'์ ๊ฐ์ ๋๋ช ์ฌ๊ฐ ์ฌ๋์ด๋ฆ ๋ฑ์ ๊ณ ์ ๋ช ์ฌ๋ก ํํ๋ ๋๊ฐ ๋ง์ ์ด๋ฐ ๋ฒ์ญ์ ๋ํ ๋ฌธ์ ์ ๋ค์ ๋๋ฃจ ๊ณ ๋ คํด์ผํ๋ค.
2. Normalization
2.1 ์ ๊ฐ/๋ฐ๊ฐ ๋ฌธ์ ์ ๊ฑฐ
๋๋ถ๋ถ์ ์ผ๋ณธ/์ค๊ตญ์ด ๋ฌธ์์ ์ผ๋ถ ํ๊ตญ์ด๋ฌธ์์ ์ซ์, ์์, ๊ธฐํธ๊ฐ ์ ๊ฐ๋ฌธ์์ผ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํ๊ธฐ์ ์ด๋ฅผ ๋ฐ๊ฐ ๋ฌธ์๋ก ๋ณํํด์ฃผ๋ ์์ ์ด ํ์ํ๋ค.
2.2 ๋์๋ฌธ์ ํต์ผ
๋ค์ํ ํํ์ ์ผ์ํ๋ ํ๋์ ์๋ฏธ๋ฅผ ๊ฐ๋ ์ฌ๋ฌ ๋จ์ด๋ฅผ ํ๋์ ํํ๋ก ํต์ผํด ํฌ์์ฑ(sparsity)์ ์ค์ฌ์ค๋ค.
๋ค๋ง, ๋ฅ๋ฌ๋์ด ๋ฐ์ ํ๋ฉด์ ๋ค์ํ ๋จ์ด๋ค์ ๋น์ทํ ๊ฐ์ vector๋ก ๋จ์ด์๋ฒ ๋ฉ์ผ๋ก ๋์๋ฌธ์ ํด๊ฒฐ์ ํ์์ฑ์ด ์ค์ด๋ค์๋ค.
2.3 ์ ๊ท ํํ์์ ์ฌ์ฉํ Normalize
ํฌ๋กค๋ง์ผ๋ก ์ป์ ๋ค๋์ corpus์ ๊ฒฝ์ฐ, ํน์๋ฌธ์ ๋ฐ ๊ธฐํธ ๋ฑ์ ์ํ Noise๊ฐ ์กด์ฌํ๋ค.
๋ํ ์น์ฌ์ดํธ์ ์ฑ๊ฒฉ์ ๋ฐ๋ฅธ ์ผ์ ํจํด์ ๊ฐ๋ ๊ฒฝ์ฐ๋ ์๊ธฐ์
ํจ์จ์ ์ผ๋ก noise๋ฅผ ๊ฐ์ง, ์์ ์ผ ํ๋๋ฐ, ์ด๋ ์ธ๋ฑ์ค์ ์ฌ์ฉ์ด ํ์์ ์ด๋ค.
์๋๋ ์ ๊ท์์๊ฐํ์ฌ์ดํธ(https://regexper.com/)๋ฅผ ํ์ฉํด ๋ํ๋ธ ๊ฒ์ด๋ค.
[ ] ์ฌ์ฉ
2 or 3 or 4 or 5 or c or d or e์ ๊ฐ์ ์๋ฏธ๋ฅผ ๊ฐ๋๋ค.
๋ฉด ์๋์ ์ข์ธก๊ณผ ๊ฐ๋ค.
ex) [2345cde]
- ์ฌ์ฉ
์ฐ์๋ ์ซ์๋ ์ํ๋ฒณ ๋ฑ์ ํํํ ์ ์๋ค.
ex) [2-5c-e]
^ ์ฌ์ฉ
not์ ๊ธฐํธ ^์ ์ฌ์ฉํด ํํํ ์ ์๋ค.
ex) [2-5c-e]
( ) ์ฌ์ฉ
๊ดํธ๋ฅผ ์ด์ฉํด group ์์ฑํ ์ ์๋ค.
ex) (x)(yz)
? + * ์ฌ์ฉ
?: ์์ ์์ํ๋ ๋ถ๋ถ์ด ๋ํ๋์ง ์๊ฑฐ๋ ํ๋ฒ๋ง ๋ํ๋ ๋
+: ์์ ์์ํ๋ ๋ถ๋ถ์ด ํ๋ฒ ์ด์ ๋ํ๋ ๊ฒฝ์ฐ
*: ์์ ์์ํ๋ ๋ถ๋ถ์ด ๋ํ๋์ง ์๊ฑฐ๋ ์ฌ๋ฌ๋ฒ ๋ํ๋ ๊ฒฝ์ฐ
ex) x?
ex) x+
ex) x*
^์ $์ ์ฌ์ฉ
[ ] ๋ด์ ํฌํจ๋์ง ์์ ๋,
^ ์ ๋ผ์ธ์ ์์์ ์๋ฏธ
$ ์ ๋ผ์ธ์ ์ข ๋ฃ๋ฅผ ์๋ฏธ
ex) ^x$
์์ 1)
์๋์ ๊ฐ์ธ์ ๋ณด(์ ํ๋ฒํธ)๊ฐ ํฌํจ๋ corpus๋ฅผ dataset์ผ๋ก ์ฌ์ฉํ ๋, ๊ฐ์ธ์ ๋ณด๋ฅผ ์ ์ธํ๊ณ ์ฌ์ฉํ๊ณ ์ ํ๋ค๋ฉด?
๋จ, ํญ์ ๋ง์ง๋ง ์ค์ ์ ํ๋ฒํธ ์ ๋ณด๊ฐ ์๋ ๊ฒ์ ์๋๋ผ๋ฉด?
Hello Kim, I would like to introduce regular expression in this section
~~
Thank you!
Sincerely,
Kim: +82-10-1234-5678
๊ฐ์ธ์ ๋ณด์ ๊ท์น์ ๋จผ์ ํ์ ํด๋ณด์. ๊ตญ๊ฐ๋ฒํธ๋ ์ต๋ 3์๋ฆฌ์ด๊ณ ์์ +๊ฐ ๋ถ์ ์ ์์ผ๋ฉฐ ์ ํ๋ฒํธ ์ฌ์ด์ -๊ฐ ๋ค์ด๊ฐ ์๋ ์๋ค.
์ ํ๋ฒํธ๋ ๋น์นธ ์์ด ํํ๋๋ฉฐ ์ง์ญ๋ฒํธ๊ฐ ๋ค์ด๊ฐ ์ ์๊ณ ๋ง์ง๋ง์ ํญ์ 4์๋ฆฌ ์ซ์์ด๋ค ๋ฑ๋ฑ...
import re
regex = r"([\w]+\s*:?\s*)?\(?\+?([0-9]{1,3})?\-[0-9]{2,3}(\)|\-)?[0-9]{3,4}\-?[0-9]{4}"
x = "Name - Kim: +82-10-9425-4869"
re.sub(regex, "REMOVED", x)
์ถ๋ ฅ: Name - REMOVED
์์ 2) ์นํ์ ์ฌ์ฉ
์๋์ ์์ ์์ ์ํ๋ฒณ ์ฌ์ด์ ์๋ ์ซ์๋ฅผ ์ ๊ฑฐํด์ผํ๋ค๋ฉด?
๋ง์ฝ ๋จ์ํ [0-9]+ ๋ก ์ซ์๋ฅผ ์ฐพ์ ์์ค๋ค๋ฉด ์ซ์๋ง ์๊ฑฐ๋ ์ซ์๊ฐ ๊ฐ์ฅ์๋ฆฌ์ ์๋ ๊ฒฝ์ฐ๋ ์ฌ๋ผ์ง๊ฒ ๋๋ค.
x = '''abcdefg
12345
ab12
12ab
a1bc2d
a1
1a'''
๋ฐ๋ผ์ ๊ดํธ๋ก group์ ์์ฑํ๊ณ ๋ฐ๋ ๋ฌธ์์ด ๋ด์์ ์ญ์ฌ๋์(\)์ ํจ๊ป ์ซ์๋ฅผ ์ด์ฉํด ๋ง์น ๋ณ์๋ช ์ฒ๋ผ ๊ฐ๋ฆฌํฌ ์ ์๋ค.
regex = r'([a-z])[0-9]+([a-z])'
to = r'1\2\'
y = '\n'.join([re.sub(regex, to, x_i) for x_i in x.split('\n')])

3. ๋ฌธ์ฅ๋จ์ tokenization
๋ค๋ง, ๋ณดํต ๋ค๋ฃจ๋ ค๋ ๋ฌธ์ ๋ค์ ์ ๋ ฅ๋จ์๊ฐ ์๋, ๋ฌธ์ฅ๋จ์์ธ ๊ฒฝ์ฐ๊ฐ ๋ง๊ณ
๋๋ถ๋ถ์ ๊ฒฝ์ฐ, ํ ๋ผ์ธ์ ํ ๋ฌธ์ฅ๋ง ์์ด์ผ ํ๋ค.
๋ฐ๋ผ์ ์ฌ๋ฌ ๋ฌธ์ฅ์ด ํ ๋ผ์ธ์ ์๊ฑฐ๋ ํ ๋ฌธ์ฅ์ด ์ฌ๋ฌ ๋ผ์ธ์ ๊ฑธ์ณ์๋ค๋ฉด, ์ด๋ฅผ ๋ถ์ (tokenize)ํด์ค์ผ ํ๋ค.
์ด๋ฅผ ์ํด ์ง์ ๋ถ์ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋ง๋ค๊ธฐ๋ณด๋ค๋ ๋๋ฆฌ ์๋ ค์ง NLP Toolkit, NLTK์์ ์ ๊ณตํ๋ sent_tokenize ์ด์ฉ์ด ์ฃผ๊ฐ ๋๋ค.
๋ฌผ๋ก , ์ถ๊ฐ์ ์ธ ์ ์ฒ๋ฆฌ ๋ฐ ํ์ฒ๋ฆฌ๊ฐ ํ์ํ ๊ฒฝ์ฐ๋ค๋ ์กด์ฌํ๋ค.
3.1 sentence tokenization ์์
import sys, fileinput, re from nltk.tokenize import sent_tokenize if __name__ == "__main__": for line in fileinput.input(): if line.strip() != "": line = re.sub(r'([a-z])\.([A-Z])', r'\1. \2', line.strip()) sentences = sent_tokenize(line.strip()) for s in sentences: if s != "": sys.stdout.write(s + "\n")โ
3.2 ๋ฌธ์ฅ ํฉ์น๊ธฐ ๋ฐ ๋ถ์ ์์
import sys, fileinput from nltk.tokenize import sent_tokenize if __name__ == "__main__": buf = [] for line in fileinput.input(): if line.strip() != "": buf += [line.strip()] sentences = sent_tokenize(" ".join(buf)) if len(sentences) > 1: buf = sentences[1:] sys.stdout.write(sentences[0] + '\n') sys.stdout.write(" ".join(buf) + "\n")โ
4. Tokenization
ํ๊ณ ์ ํ๋ ๋ฌธ์ , ์ธ์ด์ ๋ฐ๋ผ ํํ์ ๋ถ์, ๋จ์ํ ๋ถ์ ์ ํตํ ์ ๊ทํ๋ฅผ ์ํํ๋๋ฐ, ํนํ ๋์ด์ฐ๊ธฐ์ ๊ดํด ์ดํด๋ณด์.
ํ๊ตญ์ด์ ๊ฒฝ์ฐ, ํ์คํ ๊ณผ์ ์ด ์ถฉ๋ถํ์ง ์์ ๋์ด์ฐ๊ธฐ๊ฐ ์ง๋ฉ๋๋ก์ธ ๊ฒฝ์ฐ๊ฐ ์๋นํ ๋ง์ผ๋ฉฐ, ๋์ด์ฐ๊ธฐ๊ฐ ๋ฌธ์ฅํด์์ ํฐ ์ํฅ์ ์ฃผ์ง ์์ ์ด๋ฐ ํ์์ด ๋์ฑ ๋ ๊ฐ์ค๋๋ ๊ฒฝํฅ์ด ์กด์ฌํ๋ค. ๋ฐ๋ผ์ ํ๊ตญ์ด์ ๊ฒฝ์ฐ, ์ ๊ทํ๋ฅผ ํด์ค ๋, ํ์คํ๋ ๋์ด์ฐ๊ธฐ๋ฅผ ์ ์ฉํ๋ ๊ณผ์ ๋ ํ์ํ๋ฉฐ ๊ต์ฐฉ์ด๋ก์จ ์ ์ฌ๋ฅผ ์ด๊ทผ์์ ๋ถ๋ฆฌํด์ฃผ๋ ์ญํ ๋ ํ์ํ๊ธฐ์ ํฌ์์ฑ๋ฌธ์ ๋ฅผ ํด์ํ๊ธฐ๋ ํ๋ค.
์ด๋ฐ ํ๊ตญ์ด์ tokenization์ ์ํ ํ๋ก๊ทธ๋จ์ผ๋ก๋ C++๋ก ์ ์๋ Mecab, Python์ผ๋ก ์ ์๋ KoNLPy๊ฐ ์ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ค.
https://github.com/kh-kim/nlp_with_pytorch_examples/blob/master/chapter-04/tokenization.ipynb
์์ด์ ๊ฒฝ์ฐ, ๊ธฐ๋ณธ์ ์ผ๋ก ๋์ด์ฐ๊ธฐ๊ฐ ์๊ณ , ๊ธฐ๋ณธ์ ์ผ๋ก ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๊ท์น์ ๋งค์ฐ ์ ๋ฐ๋ฅด๊ณ ์๋ค.
์์ด์ ๊ฒฝ์ฐ, ๋ณดํต ์์ ์ธ๊ธํ๋ฏ ๊ธฐ๋ณธ์ ์ธ ๋์ด์ฐ๊ธฐ๊ฐ ์ ํต์ผ๋์ด ์๋ ํธ์ด๋ฏ๋ก ๋์ด์ฐ๊ธฐ ์์ฒด์๋ ํฐ ์ ๊ทํ ๋ฌธ์ ๊ฐ ์กด์ฌํ์ง ์๋๋ค.
๋ค๋ง ์ผํ(comma), ๋ง์นจํ(period), ์ธ์ฉ๋ถํธ(quotation) ๋ฑ์ ๋์ด์ฃผ์ด์ผ ํ๋ฏ๋ก Python์ผ๋ก ์ ์๋ NLTK๋ฅผ ์ด์ฉํ ์ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ค.
$ pip install nltk==3.2.5โ
์ผ๋ณธ์ด์ ์ค๊ตญ์ด์ ๊ฒฝ์ฐ, ๋ชจ๋ ๋ฌธ์ฅ์ด ๋์ด์ฐ๊ธฐ๊ฐ ์๋ ํํ๋ฅผ ํ๊ณ ์์ง๋ง, ์ ์ ํ ์ธ์ด๋ชจ๋ธ๊ตฌ์ฑ์ ์ํด ๋์ด์ฐ๊ธฐ๊ฐ ํ์ํ๋ค.
์ผ๋ณธ์ด์ ๊ฒฝ์ฐ, C++ base์ Mecab์, ์ค๊ตญ์ด์ ๊ฒฝ์ฐ Java base์ Stanford Parser, PKU Parser๋ฅผ ์ฌ์ฉํ๋ค.
5. ๋ณ๋ ฌ Corpus ์ ๋ ฌ
์๋ฅผ๋ค์ด ์์ด์ ๋ฌธ๊ณผ ํ๊ธ์ ๋ฌธ์ด ๋งตํ๋๋, ๋ฌธ์์ ๋ฌธ์๋จ์ ๋งตํ์ ๊ฒฝ์ฐ,
๋ฌธ์ฅ ๋ ๋ฌธ์ฅ์ ๊ดํ ์ ๋ ฌ์ ์ด๋ฃจ์ด์ ธ ์์ง ์์๊ธฐ์ ์ผ๋ถ ๋ถํ์ํ ๋ฌธ์ฅ๋ค์ ๊ฑธ๋ฌ๋ด์ผํ๋ค.
5.1 parallel corpus ์ ์๊ณผ์ ๊ฐ์
โ source์ target ์ธ์ด๊ฐ์ ๋จ์ด์ฌ์ ์ ์ค๋น,
์ค๋น๋ ๋จ์ด์ฌ์ ์ด ์์ผ๋ฉด โฅ์ผ๋ก ์ด๋, ์๋ค๋ฉด ์๋๊ณผ์ ์ ๋ฐ๋ฅธ๋ค.
โก ๊ฐ ์ธ์ด์ ๋ํ corpus๋ฅผ ์์ง ๋ฐ ์ ์
โข ๊ฐ ์ธ์ด์ ๋ํ word embedding vector๋ฅผ ๊ตฌํ๋ค.
โฃ MUSE๋ฅผ ํตํด ๋จ์ด๋ ๋ฒจ ๋ฒ์ญ๊ธฐ๋ฅผ ํ๋ จ
https://github.com/facebookresearch/MUSE
โค ํ๋ จ๋ ๋จ์ด๋ ๋ฒจ ๋ฒ์ญ๊ธฐ๋ฅผ ํตํด ๋ ์ธ์ด๊ฐ์ ๋จ์ด์ฌ์ ์ ์์ฑ
โฅ ๋ง๋ค์ด์ง ๋จ์ด์ฌ์ ์ ๋ฃ์ด Champollion์ ํตํด ๊ธฐ์กด์ ์์ง๋ multilingual corpus๋ฅผ ์ ๋ ฌ
https://github.com/LowResourceLanguages/champollion
โฆ ๊ฐ ์ธ์ด์ ๋ํด ๋จ์ด์ฌ์ ์ ์ ์ฉํ๊ธฐ ์ํด ์ ์ ํ tokenization์ ์ํ
โง ๊ฐ ์ธ์ด์ ๋ํด Normalization์ ์ํ
โจ Champollion์ ์ฌ์ฉํด parallel corpus๋ฅผ ์์ฑ
5.2 ๋จ์ด์ฌ์ ์์ฑ
facebook์ MUSE๋ parallel corpus๊ฐ ์๋ ์ํฉ์์ ์ฌ์ ์ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ๊ณผ ์ฝ๋๋ฅผ ์ ๊ณตํ๋ค.
MUSE๋ ๊ฐ monolingual corpus๋ฅผ ํตํด ๊ตฌ์ถ๋ ์ธ์ด๋ณ word embedding vector์ ๋ํด
๋ค๋ฅธ ์ธ์ด์ embedding vector์ mapping์์ผ ๋จ์ด ๊ฐ์ ๋ฒ์ญ์ ์ํํ ์ ์๋, unsupervised learning์ด๋ค.
<>๋ฅผ ๊ตฌ๋ถ๋ฌธ์(delimeter)๋ก ์ฌ์ฉํด ํ ๋ผ์ธ์ source๋จ์ด์ target๋จ์ด๋ฅผ ํํํ๋ค.
ex) MUSE๋ฅผ ํตํด unsupervised learning์ ์ฌ์ฉํด ๊ฒฐ๊ณผ๋ฌผ๋ก ์ป์ ์ํ ๋จ์ด ๋ฒ์ญ์ฌ์ ์ ์ผ๋ถ.
์๋นํ ์ ํํ ๋จ์ด๊ฐ ๋ฒ์ญ์ ๋ณผ ์ ์๋ค.
stories <> ์ด์ผ๊ธฐ stories <> ์์ค contact <> ์ฐ๋ฝ contact <> ์ฐ๋ฝ์ฒ contact <> ์ ์ด green <> ์ด๋ก์ green <> ๋นจ๊ฐ์ dark <> ์ด๋ dark <> ์ง
5.3 CTK๋ฅผ ํ์ฉํ ์ ๋ ฌ
์์ ๊ตฌ์ฑํ ์ฌ์ ์ CTK์ ์ ๋ ฅ์ผ๋ก ์ฌ์ฉ๋๋๋ฐ, CTK๋ ์ด ์ฌ์ ์ ๋ฐํ์ผ๋ก parallel์ ๋ฌธ์ฅ์ ๋ ฌ์ ์ํํ๋ค.
CTK๋ bilingual corpus์ ๋ฌธ์ฅ์ ๋ ฌ์ ์ํํ๋ ์คํ์์ค๋ก Perl์ ์ฌ์ฉํด ๊ตฌํ๋์๋ค.
๊ธฐ์กด ํน์ ์๋์ผ๋ก ๊ตฌ์ถ๋ ๋จ์ด์ฌ์ ์ ์ฐธ๊ณ ํด CTK๋ ๋ฌธ์ฅ์ ๋ ฌ์ ์ํํ๋๋ฐ, ์ฌ๋ฌ ๋ผ์ธ์ผ๋ก ๊ตฌ์ฑ๋ ์ธ์ด๋ณ ๋ฌธ์์ ๋ํด ๋ฌธ์ฅ ์ ๋ ฌํ ๊ฒฐ๊ณผ์ ์์ ๋ ์๋์ ๊ฐ๋ค.
omitted <=> 1 omitted <=> 2 omitted <=> 3 1 <=> 4 2 <=> 5 3 <=> 6 4,5 <=> 7 6 <=> 8 7 <=> 9 8 <=> 10 9 <=> omitted ํด์) target์ธ์ด์ 1,2,3๋ฒ์งธ ๋ฌธ์ฅ์ ์ง์ ์ฐพ์ง ๋ชปํด ๋ฒ๋ ค์ง ํด์) source์ธ์ด์ 1,2,3๋ฒ์งธ ๋ฌธ์ฅ์ target์ 4,5,6๋ฒ์งธ ๋ฌธ์ฅ๊ณผ mapping ํด์) source์ธ์ด์ 4,5๋ฒ์งธ ๋ ๋ฌธ์ฅ์ target์ 7๋ฒ ๋ฌธ์ฅ์ ๋์์ mapping
์์ ์์์ฒ๋ผ ์ด๋ค ๋ฌธ์ฅ๋ค์ ๋ฒ๋ ค์ง๊ธฐ๋ ํ๊ณ
์ผ๋์ผ(one-to-one)๋งตํ, ์ผ๋๋ค(one-to-many), ๋ค๋์ผ(many-to-one)๋งตํ์ด ์ด๋ค์ง๊ธฐ๋ ํ๋ค.
ex) CTK๋ฅผ ์ฝ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํด ํ์ด์ฌ์ผ๋ก ๊ฐ์ผ ์คํฌ๋ฆฝํธ ์์
์ด๋, CTK_ROOT์ CTK ์์น๋ฅผ ์ง์ ํด ์ฌ์ฉํ ์ ์๋ค.
import sys, argparse, os BIN = "NEED TO BE CHANGED" CMD = "%s -c %f -d %s %s %s %s" OMIT = "omitted" DIR_PATH = './tmp/' INTERMEDIATE_FN = DIR_PATH + "tmp.txt" def read_alignment(fn): aligns = [] f = open(fn, 'r') for line in f: if line.strip() != "": srcs, tgts = line.strip().split(' <=> ') if srcs == OMIT: srcs = [] else: srcs = list(map(int, srcs.split(','))) if tgts == OMIT: tgts = [] else: tgts = list(map(int, tgts.split(','))) aligns += [(srcs, tgts)] f.close() return aligns def get_aligned_corpus(src_fn, tgt_fn, aligns): f_src = open(src_fn, 'r') f_tgt = open(tgt_fn, 'r') for align in aligns: srcs, tgts = align src_buf, tgt_buf = [], [] for src in srcs: src_buf += [f_src.readline().strip()] for tgt in tgts: tgt_buf += [f_tgt.readline().strip()] if len(src_buf) > 0 and len(tgt_buf) > 0: sys.stdout.write("%s\t%s\n" % (" ".join(src_buf), " ".join(tgt_buf))) f_tgt.close() f_src.close() def parse_argument(): p = argparse.ArgumentParser() p.add_argument('--src', required = True) p.add_argument('--tgt', required = True) p.add_argument('--src_ref', default = None) p.add_argument('--tgt_ref', default = None) p.add_argument('--dict', required = True) p.add_argument('--ratio', type = float, default = 1.1966) config = p.parse_args() return config if __name__ == "__main__": assert BIN != "NEED TO BE CHANGED" if not os.path.exists(DIR_PATH): os.mkdir(DIR_PATH) config = parse_argument() if config.src_ref is None: config.src_ref = config.src if config.tgt_ref is None: config.tgt_ref = config.tgt cmd = CMD % (BIN, config.ratio, config.dict, config.src_ref, config.tgt_ref, INTERMEDIATE_FN) os.system(cmd) aligns = read_alignment(INTERMEDIATE_FN) get_aligned_corpus(config.src, config.tgt, aligns)
6. Subword Tokenization (with Byte Pair Encoding)
6.1 BPE (Byte Pair Algorithm)
BPE๋ฅผ ํตํ subword tokenization์ ํ์ฌ ๊ฐ์ฅ ํ์์ ์ธ ์ ์ฒ๋ฆฌ๋ฐฉ๋ฒ์ด๋ค.
ex) concentrate = con(together) + centr(=center) + ate(=make)
ex) ์ง์ค(้ไธญ) = ้(๋ชจ์ ์ง) + ไธญ(๊ฐ์ด๋ฐ ์ค)
[subword tokenization ์๊ณ ๋ฆฌ์ฆ]
- ๋จ์ด๋ ์๋ฏธ๋ฅผ ๊ฐ๋ ๋ ์์ subwords์ ์กฐํฉ์ผ๋ก ์ด๋ค์ง๋ค๋ ๊ฐ์ ํ์
- ์ ์ ํ subword๋ฅผ ๋ฐ๊ฒฌํด ํด๋น ๋จ์๋ก ์ชผ๊ฐ์ด
- ์ดํ ์๋ฅผ ์ค์ด๊ณ sparsity๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ค์ด๋ ๋ฐฉ๋ฒ.
- ํนํ UNK(Unknown) Token์ ๋ํด ํจ์จ์ ๋์ฒ์ด๋ค.
[UNK Token , OOV. &. BPE]
โ U.K[Unknown Token]: train corpus์ ์๋ ๋จ์ด
โ OOV[Out-of-Vocabulary] ๋ฌธ์ : U.K๋ก ์ธํด ๋ฌธ์ ๋ฅผ ํธ๋ ๊ฒ์ด ๊น๋ค๋ก์์ง๋ ํ์.
์์ฐ์ด์ฒ๋ฆฌ์์ ๋ฌธ์ฅ์ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ๋ ๋จ์ํ ๋จ์ด๋ค์ ์ํ์ค๋ก ๋ฐ๊ธฐ์
UNK Token์ ์์ฐ์ด์ฒ๋ฆฌ ๋ชจ๋ธ์ ํ๋ฅ ์ ๋ง๊ฐ๋จ๋ฆฌ๊ณ ์ ์ ํ embedding(encoding) ๋๋ ์์ฑ์ด ์ด๋ ค์์ง๋ ์ง๋ขฐ์ด๋ค.
ํนํ, ๋ฌธ์ฅ์์ฑ์ ๊ฒฝ์ฐ, ์ด์ ๋จ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ ๋จ์ด๋ฅผ ์์ธกํ๊ธฐ์ ๋์ฑ ์ด๋ ค์์ง๋ค.
subword ๋ถ๋ฆฌ๋ก OOV๋ฌธ์ ๋ฅผ ์ํํ๋๋ฐ, ๊ฐ์ฅ ๋ํ์ ์ธ subword ๋ถ๋ฆฌ์๊ณ ๋ฆฌ์ฆ์ด ๋ฐ๋ก BPE(Byte Pair Encoding)
์ด๋ค.
ํ์ง๋ง subword๋จ์์ tokenization์ ์งํํ๋ BPE ์๊ณ ๋ฆฌ์ฆ์ ๊ฒฝ์ฐ, ์ ์กฐ์ด๋ ์คํ(typo)๊ฐ์ UNK Token์ ๋ํด subword ๋จ์๋ ๋ฌธ์(character)๋จ์๋ก ์ชผ๊ฐ ๊ธฐ์กด train data์ token๋ค์ ์กฐํฉ์ผ๋ก ๋ง๋ค์ด๋ฒ๋ฆด ์ ์๋ค.
์ฆ, UNK ์์ฒด๋ฅผ ์์ฐ์ผ๋ก์จ ํจ์จ์ ์ผ๋ก UNK์ ๋์ฒํ์ฌ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์๋ค.
ex)
[์์ด NLTK]์ ์ํด ๋ถ์ ๋ ์๋ฌธ
Natural language processing is one of biggest streams in A.I
[์์ด BPE]๋ก subword๋ก ๋ถ์ ๋ ์๋ฌธ
_Natural _language _processing _is _one _of _biggest _stream s _in _A. I
7. Detokenization
์ ์ฒ๋ฆฌ๊ณผ์ ์์ tokenization์ ์ํํ์์ผ๋ฉด, ๋ค์ detokenization์ ์ํํด์ค์ผํ๋ค.
์ฆ, ์๋์ ๊ฐ์ ์ ์ฒ๋ฆฌ๊ณผ์ ์ ๋ฐ๋ฅธ๋ค.
โ ์ธ์ด๋ณ tokenizer๋ชจ๋(ex. NLTK)๋ก ๋ถ์ ์ํ
์ด๋, ์๋กญ๊ฒ ๋ถ์ ๋๋ ๊ณต๋ฐฑ๊ณผ์ ๊ตฌ๋ถ์ ์ํด ๊ธฐ์กด ๊ณต๋ฐฑ์ _ ๊ธฐํธ๋ฅผ ์ฝ์
โ subword๋จ์ tokenization(ex. BPE์๊ณ ๋ฆฌ์ฆ)์ ์ํ
์ด๋, ์ด์ ๊ณผ์ ๊น์ง์ ๊ณต๋ฐฑ๊ณผ subword๋จ์ ๋ถ์ ๋ก ์ธํ ๊ณต๋ฐฑ ๊ตฌ๋ถ์ ์ํด ํน์๋ฌธ์ _ ๊ธฐํธ๋ฅผ ์ฝ์
์ฆ, ๊ธฐ์กด ๊ณต๋ฐฑ์ ๊ฒฝ์ฐ _ _๋ฅผ ๋จ์ด ์์ ๊ฐ๊ฒ ๋๋ ๊ฒ.
โ Detokenize ์งํ
๋จผ์ ๊ณต๋ฐฑ์ ์ ๊ฑฐํ๋ค.
์ดํ (_๋ฅผ 2๊ฐ ๊ฐ๋)_ _ ๋ฌธ์์ด์ ๊ณต๋ฐฑ์ผ๋ก ์นํํ๋ค.
๋ง์ง๋ง์ผ๋ก _ ๋ฅผ ์ ๊ฑฐํ๋ค.
7.1 tokenization ํ์ฒ๋ฆฌ
Detokenization์ ์ฝ๊ฒํ๊ธฐ ์ํด tokenize ์ดํ ํน์๋ฌธ์๋ฅผ ๋ถ์ ๊ณผ์ ์์ ์๋กญ๊ฒ ์๊ธด ๊ณต๋ฐฑ ๋ค์์ ์ฝ์ ํด์ผํ๋ค.
์์ ) ๊ธฐ์กด ๊ณต๋ฐฑ๊ณผ ์ ์ฒ๋ฆฌ๋จ๊ณ์์ ์์ฑ๋ ๊ณต๋ฐฑ์ ์๋ก ๊ตฌ๋ถํ๊ธฐ ์ํ ํน์๋ฌธ์ _ ๋ฅผ ์ฝ์ ํ๋ ์ฝ๋
tokenizer.py
import sys STR = 'โ' if __name__ == "__main__": ref_fn = sys.argv[1] f = open(ref_fn, 'r') for ref in f: ref_tokens = ref.strip().split(' ') input_line = sys.stdin.readline().strip() if input_line != "": tokens = input_line.split(' ') idx = 0 buf = [] # We assume that stdin has more tokens than reference input. for ref_token in ref_tokens: tmp_buf = [] while idx < len(tokens): if tokens[idx].strip() == '': idx += 1 continue tmp_buf += [tokens[idx]] idx += 1 if ''.join(tmp_buf) == ref_token: break if len(tmp_buf) > 0: buf += [STR + tmp_buf[0].strip()] + tmp_buf[1:] sys.stdout.write(' '.join(buf) + '\n') else: sys.stdout.write('\n') f.close()โ
7.2 Detokenize ์์
์์ ์คํฌ๋ฆฝํธ(tokenizer.py)๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ๋ค.
์ฃผ๋ก ๋ค๋ฅธ ๋ถ์ ๋ชจ๋์ ์ํ ํ์ pipe๋ฅผ ์ฌ์ฉํด ๋ถ์ฌ์ ์ฌ์ฉํ๋ค.
$ cat [before filename] | python tokenizer.py | python post_tokenizer.py [before filename]โ
post_tokenizer.py
import sys if __name__ == "__main__": for line in sys.stdin: if line.strip() != "": if 'โโ' in line: line = line.strip().replace(' ', '').replace('โโ', ' ').replace('โ', '').strip() else: line = line.strip().replace(' ', '').replace('โ', ' ').strip() sys.stdout.write(line + '\n') else: sys.stdout.write('\n')โ
8. Torchtext ๋ผ์ด๋ธ๋ฌ๋ฆฌ
8.1 Torchtext ๋?
Torchtext ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์์ฐ์ด์ฒ๋ฆฌ๋ฅผ ์ํํ๋ data๋ฅผ ์ฝ๊ณ ์ ์ฒ๋ฆฌํ๋ ์ฝ๋๋ฅผ ๋ชจ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
(https://pytorch.org/text/stable/index.html)
Torchtext๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ๋ฉด ์ฝ๊ฒ textํ์ผ์ ์ฝ์ด๋ด ํ๋ จ์ ์ฌ์ฉํ ์ ์๋ค.
์์ธํ ์ค๋ช ์ ์๋ ๋งํฌ(https://wikidocs.net/60314)๋ฅผ ์ฐธ๊ณ
08-02 ํ ์นํ ์คํธ ํํ ๋ฆฌ์ผ(Torchtext tutorial) - ์์ด
ํ์ดํ ์น(PyTorch)์์๋ ํ ์คํธ์ ๋ํ ์ฌ๋ฌ ์ถ์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ์์ฐ์ด ์ฒ๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ ์นํ ์คํธ(Torchtext)๋ฅผ ์ ๊ณตํฉ๋๋ค. ์์ฐ์ด ์ฒ๋ฆฌ๋ฅผ ์ํด ํ ์นํ ์คํธ๊ฐ ๋ฐ๋โฆ
wikidocs.net