[๐ค ๊ฐ์ข 6.8] Unigram ํ ํฐํ
Unigram ์๊ณ ๋ฆฌ์ฆ์ AlBERT, T5, mBART, Big Bird ๋ฐ XLNet๊ณผ ๊ฐ์ ๋ชจ๋ธ์์ ์ฌ์ฉ๋๋ ํ ํฐํ ์๊ณ ๋ฆฌ์ฆ์ธ SentencePiece์์ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค.
๐ก ์ด ์น์ ์์๋ ์ ์ฒด ๊ตฌํ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ํฌํจํ์ฌ Unigram์ ๊น์ด ์๊ฒ ๋ค๋ฃน๋๋ค. ํ ํฐํ ์๊ณ ๋ฆฌ์ฆ์ ๋ํ ์ผ๋ฐ์ ์ธ ๊ฐ์๋ฅผ ์ํ๋ ๊ฒฝ์ฐ ์๋ตํด๋ ์ข์ต๋๋ค.
ํ์ต ์๊ณ ๋ฆฌ์ฆ
BPE ๋ฐ WordPiece์ ๋น๊ตํ์ฌ Unigram์ ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก ์๋ํฉ๋๋ค. ์ฆ, ํฌ๊ธฐ๊ฐ ํฐ vocabulary์์ ์์ํ์ฌ ์ํ๋ vocabulary ํฌ๊ธฐ์ ๋๋ฌํ ๋๊น์ง ํ ํฐ์ ์ ๊ฑฐํฉ๋๋ค. ๊ธฐ๋ณธ vocabulary๋ฅผ ๊ตฌ์ถํ๋๋ฐ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์ต์ ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ ํ ํฐํ๋ ๋จ์ด์์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ถ๋ถ ๋ฌธ์์ด์ ์ทจํ๊ฑฐ๋ ํฐ ๊ท๋ชจ์ vocabulary๋ฅผ ๊ฐ์ง ์ด๊ธฐ ๋ง๋ญ์น์ BPE๋ฅผ ์ ์ฉํ ์ ์์ต๋๋ค.
ํ์ต์ ๊ฐ ๋จ๊ณ์์ Unigram ์๊ณ ๋ฆฌ์ฆ์ ํ์ฌ vocabulary๊ฐ ์ฃผ์ด์ก์ ๋์ ๋ง๋ญ์น์ ๋ํ ์์ค(loss)์ ๊ณ์ฐํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์, vocabulary์ ๊ฐ ๊ธฐํธ(symbol)์ ๋ํด, ํด๋น ๊ธฐํธ๊ฐ ์ ๊ฑฐ๋๋ฉด ์ ์ฒด ์์ค์ด ์ผ๋ง๋ ์ฆ๊ฐํ ์ง ๊ณ์ฐํ๊ณ ๊ฐ์ฅ ์ ๊ฒ ์ฆ๊ฐํ๋ ๊ธฐํธ๋ฅผ ์ฐพ์ต๋๋ค. ์ด๋ ๊ฒ ์ฐพ์ ๊ธฐํธ๋ค(symbols)์ ๋ง๋ญ์น์ ๋ํ ์ ์ฒด ์์ค์ ๋ ์ ์ ์ํฅ์ ๋ฏธ์น๋ฏ๋ก ์ด๋ค ์๋ฏธ์์๋ "๋ ํ์(less needed)"ํ๊ณ ์ ๊ฑฐ ๋์์ผ๋ก ๊ฐ์ฅ ์ ํฉํ ํ๋ณด์ ๋๋ค.
์ด๊ฒ์ ๋น์ฉ์ด ๋ง์ด ๋๋ ์์ ์ด๋ฏ๋ก ๊ฐ์ฅ ๋ฎ์ ์์ค์ ์ด๋ํ๋ ๊ธฐํธ ํ๋๋ง ์ ๊ฑฐํ์ง ์๊ณ , ์ด๋ฌํ ๊ธฐํธ๋ค์ %(๋ ์ ์ดํ ์ ์๋ ํ์ดํผํ๋ผ๋ฏธํฐ์ด๊ณ ์ผ๋ฐ์ ์ผ๋ก 10 ๋๋ 20์ ์ง์ )๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ์ด ๊ณผ์ ์ vocabulary๊ฐ ์ํ๋ ํฌ๊ธฐ์ ๋๋ฌํ ๋๊น์ง ๋ฐ๋ณต๋ฉ๋๋ค.
๋ชจ๋ ๋จ์ด๋ฅผ ํ ํฐํํ ์ ์๋๋ก ๊ธฐ๋ณธ ๋ฌธ์๋ค์ ์ ๊ฑฐํ์ง ์๋๋ค๋ ์ ๋ ์ค์ํฉ๋๋ค.
์์ง๋ ์ค๋ช ์ด ์ฝ๊ฐ ๋ชจํธํ ๋ถ๋ถ์ด ์์ง์. ์ด ์๊ณ ๋ฆฌ์ฆ์ ํต์ฌ์ ๋ง๋ญ์น์ ๋ํ ์์ค์ ๊ณ์ฐํ๊ณ vocabulary์์ ์ผ๋ถ ํ ํฐ์ ์ ๊ฑฐํ ๋ ์์ค์ด ์ด๋ป๊ฒ ๋ณํ๋์ง ํ์ธํ๋ ๊ฒ์ด์ง๋ง ์์ง ์ด๋ป๊ฒ ์ํํ๋์ง์ ๋ํ ๋ด์ฉ์ ์ค๋ช ํ์ง ์์์ต๋๋ค. ์ด ๋ถ๋ถ์ Unigram ๋ชจ๋ธ์ ํ ํฐํ ์๊ณ ๋ฆฌ์ฆ์ ๊ธฐ๋ฐํ๋ฏ๋ก ๋ค์์ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ญ์ ์ด์ ์์ ์ ๋ง๋ญ์น๋ฅผ ์ฌ์ฌ์ฉํฉ๋๋ค:
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)
์ด๊ธฐ vocabulary๋ ์ ๋ง๋ญ์น์ ์กด์ฌํ๋ ๋ชจ๋ ๋จ์ด๋ค์ ๋ชจ๋ ํ์ ๋ฌธ์์ด(substrings)๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
["h", "u", "g", "hu", "ug", "p", "pu", "n", "un", "b", "bu", "s", "hug", "gs", "ugs"]
ํ ํฐํ ์๊ณ ๋ฆฌ์ฆ
Unigram ๋ชจ๋ธ์ ๊ฐ๋ณ ํ ํฐ๋ค์ ์ถํ ๋ถํฌ๊ฐ ์๋ก ๋ ๋ฆฝ์ (i.i.d)์ด๋ผ๋ ๊ฐ์ ์ ํ๋ ์ธ์ด ๋ชจ๋ธ ์ ํ์ ๋๋ค. ํ ํฐ X์ ํ๋ฅ ์ด ๋ฌธ๋งฅ์ ์๊ด์์ด ๋์ผํ๋ค๋ ์ ์์ ๊ฐ์ฅ ๋จ์ํ ์ธ์ด ๋ชจ๋ธ์ ๋๋ค. ๋ฐ๋ผ์ Unigram ์ธ์ด ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๊ฒฝ์ฐ ํญ์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ด๊ณ ํํ(common) ํ ํฐ์ ๋์ถํฉ๋๋ค.
ํน์ ํ ํฐ์ ํ๋ฅ ์ ๋ง๋ญ์น ๋ด์์์ ํด๋น ํ ํฐ ์ถํ ๋น๋๋ฅผ vocabulary์ ์กด์ฌํ๋ ๋ชจ๋ ํ ํฐ๋ค์ ์ถํ ๋น๋์ ํฉ์ผ๋ก ๋๋ ๊ฒ์ ๋๋ค(ํ๋ฅ ์ ํฉ์ด 1์ด ๋๋๋ก ํ๊ธฐ ์ํด). ์๋ฅผ ๋ค์ด "ug"๋ "hug", "pug" ๋ฐ "hugs"์ ์์ผ๋ฏ๋ก ๋ง๋ญ์น์์์ ๋น๋๋ 20์ ๋๋ค.
๋ค์์ vocabulary์์์ ๋ชจ๋ ํ์ ๋จ์ด(subwords)์ ๋น๋์ ๋๋ค:
("h", 15) ("u", 36) ("g", 20) ("hu", 15) ("ug", 20) ("p", 17) ("pu", 17) ("n", 16)
("un", 16) ("b", 4) ("bu", 4) ("s", 5) ("hug", 15) ("gs", 5) ("ugs", 5)
๋ฐ๋ผ์ ๋ชจ๋ ๋น๋์ ํฉ์ 210์ด๊ณ ํ์ ๋จ์ด(subword) "ug"์ ํ๋ฅ ์ 20/210์ ๋๋ค.
โ๏ธ Now your turn! ์์ ๋น๋๋ฅผ ๊ณ์ฐํ๋ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ํ์๋ ๊ฒฐ๊ณผ์ ์ดํฉ์ด ์ฌ๋ฐ๋ฅธ์ง ๋ค์ ํ์ธํด๋ณด์ธ์.
์ด์ ์ฃผ์ด์ง ๋จ์ด๋ฅผ ํ ํฐํํ๊ธฐ ์ํด, ๊ฐ๋ฅํ ๋ชจ๋ ํ ํฐ ๋ถํ ์ ์ดํด๋ณด๊ณ Unigram ๋ชจ๋ธ์ ๋ฐ๋ผ ๊ฐ๊ฐ์ ํ๋ฅ ์ ๊ณ์ฐํฉ๋๋ค. ๋ชจ๋ ํ ํฐ์ ์ถํ ๋น๋๊ฐ ๋ ๋ฆฝ์ ์ธ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋๊ธฐ ๋๋ฌธ์ ์ด ํ๋ฅ ์ ๊ฐ ํ ํฐ์ ํ๋ฅ ์ ๊ณฑ์ผ ๋ฟ์ ๋๋ค. ์๋ฅผ ๋ค์ด, "pug"์ ํ ํฐํ ๊ฒฐ๊ณผ์ธ ["p", "u", "g"]์ ํ๋ฅ ์ ๋ค์๊ณผ ๊ฐ์ด ๊ณ์ฐ๋ฉ๋๋ค:
์ด์ ๋นํด ํ ํฐํ ๊ฒฐ๊ณผ์ธ ["pu", "g"]์ ํ๋ฅ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
๋ฐ๋ผ์, ["pu", "g"]์ด ํจ์ฌ ๋ ์์ฃผ ์ถํํ๋ค๊ณ ๋ณผ ์ ์๊ฒ ์ง์. ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ฅ ์ ์ ์์ ํ์ ํ ํฐ๋ค๋ก ๊ตฌ์ฑ๋ ํ ํฐํ ๊ฒฐ๊ณผ๋ ๋น๊ต์ ๋์ ํ๋ฅ (๊ฐ ํ ํฐ์ ๋ํด ๋ฐ๋ณต๋๋ 210์ผ๋ก ๋๋๊ธฐ ๋๋ฌธ์)์ ๊ฐ์ง๋ฉฐ, ์ด๋ ์ฐ๋ฆฌ๊ฐ ์ง๊ด์ ์ผ๋ก ์ํ๋ ๊ฒฐ๊ณผ์ ๋๋ค.
Unigram ๋ชจ๋ธ์ ์ฌ์ฉํ ๋จ์ด์ ํ ํฐํ๋ ๊ฐ์ฅ ๋์ ํ๋ฅ ์ ๋ํ๋ด๋ ๋ถํ ํํ๋ก ํ ํฐํ๋ฉ๋๋ค. "pug"์ ์์์ ๊ฐ๋ฅํ ๊ฐ ๋ถํ ์ ๋ํด ์ป์ ์ ์๋ ํ๋ฅ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
["p", "u", "g"] : 0.000389
["p", "ug"] : 0.0022676
["pu", "g"] : 0.0022676
๋ฐ๋ผ์ "pug"๋ ์ ๋ถํ ๋ฐฉ๋ฒ ์ค์์ ["p", "ug"] ๋๋ ["pu", "g"]๋ก ํ ํฐํ๋ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํฐ ๊ท๋ชจ์ ๋ง๋ญ์น์์๋ ๋ถํ ๋ฐฉ๋ฒ์ ๋ํ ํ๋ฅ ๊ฐ์ด ๊ฐ์ ๊ฒฝ์ฐ๊ฐ ๋งค์ฐ ๋๋ญ ๋๋ค.
์์ ๊ฒฝ์ฐ์์๋ ๊ฐ๋ฅํ ๋ชจ๋ ๋ถํ ์ ์ฐพ๊ณ ํ๋ฅ ์ ๊ณ์ฐํ๋ ๊ฒ์ด ์ฌ์ ์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก๋ ๋ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ์ด๋ฅผ ์ํด ์ฌ์ฉ๋๋ ๊ณ ์ ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ธ Viterbi ์๊ณ ๋ฆฌ์ฆ ์ด ์์ต๋๋ค. ๋ณธ์ง์ ์ผ๋ก, ์ฃผ์ด์ง ๋จ์ด์ ๋ํ ๊ฐ๋ฅํ ๋ชจ๋ ๋ถํ ๋ค์ ๋ํ๋ผ ์ ์๋ ๊ทธ๋ํ๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ง์ผ ์ฃผ์ด์ง ๋จ์ด ๋ด์ ๋ฌธ์ a์์ b๊น์ง์ ํ์ ๋จ์ด(subword)๊ฐ vocabulary์ ์กด์ฌํ๋ค๋ฉด, ์ฐ๋ฆฌ๋ ์ด ๊ทธ๋ํ ๋ด์์ a์์ ์ถ๋ฐํ์ฌ b๊น์ง ๊ฐ๋ ๊ทธ๋ํ ๋ด์ ๊ฐ์ง(branch)๊ฐ ์๋ค๊ณ ๋งํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ํ์ ๋จ์ด์ ํ๋ฅ ์ ํด๋น ๊ฐ์ง(branch)์ ์ง์ ํ ์ ์์ต๋๋ค.
๊ทธ๋ํ์์ ์ต๊ณ ์ ์๋ฅผ ์ป์ ๊ฒฝ๋ก๋ฅผ ์ฐพ๊ธฐ ์ํด Viterbi ์๊ณ ๋ฆฌ์ฆ์ ๋จ์ด ๋ด์ ๊ฐ ์์น(๋ฌธ์)์ ๋ํด ํด๋น ์์น์์ ๋๋๋ ๊ฒฝ๋ก์ ์ต๊ณ ์ ์๋ฅผ ๋ํ๋ด๋ ๋ถํ (segmentation)์ ๊ฒฐ์ ํฉ๋๋ค. ๋จ์ด์ ์ฒ์ ์์น๋ถํฐ ๋๊น์ง ์ด๋ํ๋ฉด์, ํ์ฌ ์์น์์ ๋๋๋ ๋ชจ๋ ํ์ ๋จ์ด๋ฅผ ๊ฒ์ฌํ ๋ค์ ์ด ํ์ ๋จ์ด๊ฐ ์์ํ๋ ์์น์์ ์ต๊ณ ์ ํ ํฐํ ์ ์๋ฅผ ์ฌ์ฉํ์ฌ ์ต์์ ์ ์๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋์ ๋๋ฌํ๊ธฐ ์ํด ์ ํํ ๊ฒฝ๋ก๋ฅผ ํผ์น๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
์์์ ๊ตฌ์ฑํ vocabulary์ "unhug"๋ผ๋ ๋จ์ด๋ฅผ ์ฌ์ฉํ ์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ํด๋น ๋จ์ด์ ๊ฐ ์์น์ ๋ํด ์ต๊ณ ์ ์๋ก ๋๋๋ ํ์ ๋จ์ด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
Character 0 (u): "u" (score 0.171429)
Character 1 (n): "un" (score 0.076191)
Character 2 (h): "un" "h" (score 0.005442)
Character 3 (u): "un" "hu" (score 0.005442)
Character 4 (g): "un" "hug" (score 0.005442)
์์์ ์ฒ์๋ถํฐ ๋ง์ง๋ง ๊ธ์('g')๊น์ง ์งํํ ๊ฒฐ๊ณผ, ["un", "hug"]๊ฐ ๊ฐ์ฅ ๋์ ์ ์์ธ 0.005442๋ฅผ ๋ํ๋์ต๋๋ค. ๋ฐ๋ผ์ "unhug"๋ ["un", "hug"]๋ก ํ ํฐํ๋ฉ๋๋ค.
โ๏ธ Now your turn! "huggun"์ด๋ผ๋ ๋จ์ด๋ฅผ ํ ํฐํํ๊ณ ํด๋น ์ ์๋ฅผ ๊ณ์ฐํด๋ณด์ธ์.
๋ค์ ํ์ต ์๊ณ ๋ฆฌ์ฆ
์ด์ ํ ํฐํ๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ณด์์ผ๋ฏ๋ก ํ์ต ๊ณผ์ ์์ ์ฌ์ฉ๋ ์์ค(loss)์ ๋ํด ์กฐ๊ธ ๋ ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค. ๊ฐ๊ฐ์ ์ฃผ์ด์ง ๋จ๊ณ์์ ์ด ์์ค์ ๋ง๋ญ์น ๋ด์ ๋ชจ๋ ๋จ์ด๋ฅผ ํ ํฐํํ์ฌ ๊ณ์ฐ๋ฉ๋๋ค. ๊ณ์ฐ ๊ณผ์ ์์ ์์์ ์ค๋ช ํ ๊ฒ์ฒ๋ผ ํ์ฌ vocabulary์ ๋ง๋ญ์น์ ์๋ ๊ฐ ํ ํฐ์ ๋น๋์ ์ํด ๊ฒฐ์ ๋ ์ ๋๊ทธ๋จ ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค.
๋ง๋ญ์น์ ๊ฐ ๋จ์ด๋ณ๋ก ์ ์๋ฅผ ๊ณ์ฐํ๋ฉฐ ์์ค์ ํด๋น ์ ์์ ์์ ๋ก๊ทธ ์ฐ๋(negative log likelihood)์ ๋๋ค. ์ฆ, ๋ง๋ญ์น์ ์๋ ๋ชจ๋ ๋จ์ด์ ํฉ๊ณ์ ๋๋ค.
์์์ ์ค๋ช ํ ๋ง๋ญ์น๋ฅผ ๊ฐ์ง๊ณ ์ค๋ช ํฉ๋๋ค:
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)
๊ฐ ๋จ์ด์ ํ ํฐํ ๊ฒฐ๊ณผ ๋ฐ ์ ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
"hug": ["hug"] (score 0.071428)
"pug": ["pu", "g"] (score 0.007710)
"pun": ["pu", "n"] (score 0.006168)
"bun": ["bu", "n"] (score 0.001451)
"hugs": ["hug", "s"] (score 0.001701)
๋ฐ๋ผ์ ์์ค(loss)์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
10 * (-log(0.071428)) + 5 * (-log(0.007710)) + 12 * (-log(0.006168)) + 4 * (-log(0.001451)) + 5 * (-log(0.001701)) = 169.8
์ด์ ๊ฐ ํ ํฐ์ ์ ๊ฑฐํ๋ ๊ฒ์ด ์์ค๊ฐ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น๋์ง ๊ณ์ฐํด์ผ ํฉ๋๋ค. ์ด ์์ ์ ์์์ ์ผ๋ก ํ๊ธฐ์๋ ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ฏ๋ก ์ฌ๊ธฐ์์๋ ๋ ๊ฐ์ ํ ํฐ("pu", "hug")์ ๋ํด ์ด๋ฅผ ์ํํ๊ณ ๋๋จธ์ง ํ๋ก์ธ์ค๋ ์๋์์ ํด๋น ์์ ์ ๋ํ ์ค์ ๊ตฌํ์ด ์๋ฃ๋์์ ๋ ์ํํฉ๋๋ค. ์์์ ์ดํด๋ณด์๋ฏ์ด, ์ด ์์ ์์ "pug"๋ ๋์ผํ ์ ์(0.0022676)๋ฅผ ๊ฐ์ง ๋๊ฐ์ ํ ํฐํ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ง๊ณ ์์๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์์ง์? ๋ฐ๋ก ["p", "ug"]์ ["pu", "g"]๊ฐ ๊ทธ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ "pu" ํ ํฐ์ vocabulary์์ ์ ๊ฑฐํ๋๋ผ๋ ํ ํฐํ ๊ฒฐ๊ณผ๊ฐ ๋์ผํ ์ ์๋ฅผ ๊ฐ์ง ["p", "ug"]๊ฐ ๋๋ฏ๋ก, ๊ฒฐ๋ก ์ ์ผ๋ก๋ ์์์ ๊ณ์ฐํ ๊ฒ๊ณผ ๋๊ฐ์ ์์ค(loss)๊ฐ์ด ๋์ถ๋๊ฒ ์ง์.
๋ฐ๋ฉด์, "hug"๋ฅผ ์ ๊ฑฐํ๋ฉด ์์ค๊ฐ์ด ๋ ์ฌ๋ผ๊ฐ๊ฒ ๋ฉ๋๋ค. ๊ทธ ์ด์ ๋ "hug"์ "hugs"์ ํ ํฐํ ๊ฒฐ๊ณผ๊ฐ ๋ค์๊ณผ ๊ฐ์ด ๋๊ธฐ ๋๋ฌธ์ด๊ฒ ์ง์:
"hug": ["hu", "g"] (score 0.006802) # ์์ ํ ํฐํ ๊ฒฐ๊ณผ๋ณด๋ค ์ ์๊ฐ ๋ฎ์์ง.
"hugs": ["hu", "gs"] (score 0.001701)
๊ทธ ๊ฒฐ๊ณผ ๋ค์ ๊ณ์ฐ ๊ฒฐ๊ณผ๊ฐ ๋งํผ ์์ค๊ฐ์ด ์ฌ๋ผ๊ฐ๊ฒ ๋ฉ๋๋ค:
- 10 * (-log(0.071428)) + 10 * (-log(0.006802)) = 23.5
๊ฒฐ๋ก ์ ์ผ๋ก, ํ ํฐ "pu"๋ vocabulary์์ ์ ๊ฑฐ๋๊ฒ ์ง๋ง "hug"๋ ์ ๊ฑฐ๋์ง ์์ต๋๋ค.
Unigram ๊ตฌํ
์ด์ ์ง๊ธ๊น์ง ์ดํด๋ณธ ๋ชจ๋ ๊ฒ์ ์ฝ๋๋ก ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค. BPE ๋ฐ WordPiece์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด๊ฒ์ Unigram ์๊ณ ๋ฆฌ์ฆ์ ํจ์จ์ ์ธ ๊ตฌํ์ ์๋์ง๋ง ์ ์ฒด ์๊ณ ๋ฆฌ์ฆ์ ์ดํดํ๋๋ฐ๋ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
์ด์ ๊ณผ ๋์ผํ ๋ง๋ญ์น๋ฅผ ์ฌ์ฉํฉ๋๋ค:
corpus = [
"This is the Hugging Face course.",
"This chapter is about tokenization.",
"This section shows several tokenizer algorithms.",
"Hopefully, you will be able to understand how they are trained and generate tokens.",
]
์ด๋ฒ์๋ xlnet-base-cased
๋ฅผ ๋ชจ๋ธ๋ก ์ฌ์ฉํ ๊ฒ์
๋๋ค:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("xlnet-base-cased")
BPE ๋ฐ WordPiece์ ๊ฒฝ์ฐ์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ง๋ญ์น์์ ๊ฐ ๋จ์ด์ ์ถํ ๋น๋๋ฅผ ๊ณ์ฐํ๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค:
from collections import defaultdict
word_freqs = defaultdict(int)
for text in corpus:
words_with_offsets = tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str(text)
new_words = [word for word, offset in words_with_offsets]
for word in new_words:
word_freqs[word] += 1
word_freqs
๊ทธ๋ฆฌ๊ณ ์ต์ข ์ ์ผ๋ก ์ํ๋ ํฌ๊ธฐ๋ณด๋ค ๋ ํฌ๊ฒ vocabulary๋ฅผ ์ด๊ธฐํํด์ผ ํฉ๋๋ค. ์ด๊ธฐํ ๊ณผ์ ์์ vocabulary์ ๋ชจ๋ ๊ธฐ๋ณธ ๋ฌธ์๋ค์ ํฌํจํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ชจ๋ ๋จ์ด๋ฅผ ํ ํฐํํ ์ ์๊ฒ ์ง์. ๋ํ ๊ธธ์ด๊ฐ ๋ ๊ธด ๋ถ๋ถ ๋ฌธ์์ด์ ๋ํด์๋ ๊ฐ์ฅ ๋น๋ฒํ๊ฒ ์ถํํ๋ ๊ฒ๋ค๋ง ์ถ๊ฐํ ๊ฒ์ด๋ฏ๋ก ์ผ๋จ ๋น๋์์ผ๋ก ์ ๋ ฌ์ ์ํํฉ๋๋ค:
char_freqs = defaultdict(int)
subwords_freqs = defaultdict(int)
for word, freq in word_freqs.items():
for i in range(len(word)):
char_freqs[word[i]] += freq
# ๊ธธ์ด๊ฐ ์ ์ด๋ 2 ์ด์์ธ subword๋ค์ ์ถ๊ฐํจ.
for j in range(i + 2, len(word) + 1):
subwords_freqs[word[i:j]] += freq
# Subword๋ค์ ๋น๋ ์ญ์์ผ๋ก ์ ๋ ฌ
sorted_subwords = sorted(subwords_freqs.items(), key=lambda x: x[1], reverse=True)
sorted_subwords[:10]
ํฌ๊ธฐ๊ฐ 300์ธ ์ด๊ธฐ vocabulary๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํด์ ์์์ ๋ง๋ค์ด์ง sorted_subwords
์ค์์ ๋น๋๊ฐ ๋์ ํ์ ๋จ์ด๋ค์ ์ ํํฉ๋๋ค:
token_freqs = list(char_freqs.items()) + sorted_subwords[: 300 - len(char_freqs)]
token_freqs = {token: freq for token, freq in token_freqs}
๐ก SentencePiece๋ ESA(Enhanced Suffix Array)๋ผ๋ ๋ณด๋ค ํจ์จ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ์ด๊ธฐ ์ดํ๋ฅผ ์์ฑํฉ๋๋ค.
๋ค์์ผ๋ก ๋ชจ๋ ๋น๋์ ํฉ์ ๊ณ์ฐํ์ฌ ๋น๋๋ฅผ ํ๋ฅ ๋ก ๋ณํํฉ๋๋ค. ์ฐ๋ฆฌ ๋ชจ๋ธ์ ๊ฒฝ์ฐ ํ๋ฅ ์ ๋ก๊ทธ๊ฐ์ ์ ์ฅํ ๊ฒ์ ๋๋ค. ์์ ์ซ์๋ฅผ ๊ณฑํ๋ ๊ฒ๋ณด๋ค ๋ก๊ทธ๋ฅผ ๋ํ๋ ๊ฒ์ด ์์น์ ์ผ๋ก ๋ ์์ ์ ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ชจ๋ธ ์์ค ๊ณ์ฐ์ด ๋จ์ํ๋ฉ๋๋ค:
from math import log
total_sum = sum([freq for token, freq in token_freqs.items()])
model = {token: -log(freq / total_sum) for token, freq in token_freqs.items()}
์ด์ ๊ฐ์ฅ ์ค์ํ ๋ถ๋ถ์ Viterbi ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ๋จ์ด๋ฅผ ํ ํฐํํ๋ ๊ธฐ๋ฅ์
๋๋ค. ์ด์ ์ ๋ณด์๋ฏ์ด ์ด ์๊ณ ๋ฆฌ์ฆ์ ๋จ์ด์ ๊ฐ ๋ถ๋ถ ๋ฌธ์์ด์ ๋ํ ์ต์์ ๋ถํ ์ ๊ณ์ฐํ๊ณ ์ด๋ฅผ best_segmentations
๋ผ๋ ๋ณ์์ ์ ์ฅํฉ๋๋ค. ๋จ์ด์ ๊ฐ ์์น๋น ํ๋์ ๋์
๋๋ฆฌ(0์์ ์ ์ฒด ๊ธธ์ด๊น์ง)์ ๋ ๊ฐ์ ํค์ ํจ๊ป ์ ์ฅํฉ๋๋ค. ์ด๋ ๊ฐ์ฅ ์ ์๊ฐ ๋์ ๋ถํ (segmentation)์์ ๋ง์ง๋ง ํ ํฐ์ ์์ ์ธ๋ฑ์ค์ ํด๋น ์ ์์
๋๋ค. ๋ง์ง๋ง ํ ํฐ์ ์์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ชฉ๋ก์ด ์์ ํ ์ฑ์์ง๋ฉด ์ ์ฒด ๋ถํ ์ ๊ฒ์ํ ์ ์์ต๋๋ค.
๋ชฉ๋ก ์ฑ์ฐ๊ธฐ๋ ๋จ 2๊ฐ์ ๋ฃจํ๋ก ์๋ฃ๋ฉ๋๋ค. ๊ธฐ๋ณธ ๋ฃจํ๋ ๊ฐ ์์ ์์น๋ก ์ด๋ํ๊ณ ๋ ๋ฒ์งธ ๋ฃจํ๋ ํด๋น ์์ ์์น์์ ์์ํ๋ ๋ชจ๋ ํ์ ๋ฌธ์์ด์ ๊ฒํ ํฉ๋๋ค. ํ์ ๋ฌธ์์ด์ด vocabulary์ ์๋ ๊ฒฝ์ฐ ํด๋น ๋ ์์น๊น์ง ๋จ์ด์ ์๋ก์ด ๋ถํ ์ด ์์ผ๋ฉฐ ์ด๋ฅผ best_segmentations
์ ์๋ ๊ฒ๊ณผ ๋น๊ตํฉ๋๋ค.
๋ฉ์ธ ๋ฃจํ๊ฐ ๋๋๋ฉด ๋จ์ด์ ์์ ๋ถ๋ถ์ ๋๋ฌํ ๋๊น์ง ๋์์ ์์ํ์ฌ ํน์ ์์ ์์น์์ ๋ค์ ์์น๋ก ์ด๋ํ๋ฉด์ ํ ํฐ์ ๊ธฐ๋กํฉ๋๋ค:
def encode_word(word, model):
best_segmentations = [{"start": 0, "score": 1}] + [
{"start": None, "score": None} for _ in range(len(word))
]
for start_idx in range(len(word)):
# This should be properly filled by the previous steps of the loop
best_score_at_start = best_segmentations[start_idx]["score"]
for end_idx in range(start_idx + 1, len(word) + 1):
token = word[start_idx:end_idx]
if token in model and best_score_at_start is not None:
score = model[token] + best_score_at_start
# If we have found a better segmentation ending at end_idx, we update
if (
best_segmentations[end_idx]["score"] is None
or best_segmentations[end_idx]["score"] > score
):
best_segmentations[end_idx] = {"start": start_idx, "score": score}
segmentation = best_segmentations[-1]
if segmentation["score"] is None:
# We did not find a tokenization of the word -> unknown
return ["<unk>"], None
score = segmentation["score"]
start = segmentation["start"]
end = len(word)
tokens = []
while start != 0:
tokens.insert(0, word[start:end])
next_start = best_segmentations[start]["start"]
end = start
start = next_start
tokens.insert(0, word[start:end])
return tokens, score
๋ช ๊ฐ์ ๋จ์ด๋ค๋ก ์ ํจ์๋ฅผ ํ ์คํธํด๋ณผ ์ ์์ต๋๋ค:
print(encode_word("Hopefully", model))
print(encode_word("This", model))
์ด์ ๋ง๋ญ์น์์ ๋ชจ๋ธ์ ์์ค์ ์ฝ๊ฒ ๊ณ์ฐํ ์ ์์ต๋๋ค!
def compute_loss(model):
loss = 0
for word, freq in word_freqs.items():
_, word_loss = encode_word(word, model)
loss += freq * word_loss
return loss
ํ์ฌ ๋ชจ๋ธ์์ ์๋ํ๋์ง ํ์ธํ ์ ์์ต๋๋ค:
compute_loss(model)
๊ฐ ํ ํฐ์ ์ ์๋ฅผ ๊ณ์ฐํ๋ ๊ฒ๋ ๊ทธ๋ฆฌ ์ด๋ ต์ง ์์ต๋๋ค. ๊ฐ ํ ํฐ์ ์ญ์ ํ์ฌ ์ป์ ๋ชจ๋ธ์ ์์ค์ ๊ณ์ฐํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค:
import copy
def compute_scores(model):
scores = {}
model_loss = compute_loss(model)
for token, score in model.items():
# We always keep tokens of length 1
if len(token) == 1:
continue
model_without_token = copy.deepcopy(model)
_ = model_without_token.pop(token)
scores[token] = compute_loss(model_without_token) - model_loss
return scores
๊ฐ ํ ํฐ์ ๋ํด์ ์ ํจ์๋ฅผ ์คํํฉ๋๋ค:
scores = compute_scores(model)
print(scores["ll"])
print(scores["his"])
"ll"์ "Hopefully"์ ํ ํฐํ์ ์ฌ์ฉ๋๋ฉฐ ์ด๋ฅผ ์ ๊ฑฐํ๋ฉด ํ ํฐ "l"์ ๋์ ๋๋ฒ ์ฌ์ฉํ๊ฒ ๋๋ฏ๋ก ์ถ๊ฐ์ ์ธ ์์ค์ด ๋ฐ์ํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. "his"๋ ๊ทธ ์์ฒด๋ก ํ ํฐํ๋ "This" ๋จ์ด ๋ด์์๋ง ์ฌ์ฉ๋๋ฏ๋ก ์์ค์ด 0์ผ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ๊ฒฐ๊ณผ๋ ์์ ๊ฐ์ต๋๋ค.
๐ก ์ด ์ ๊ทผ ๋ฐฉ์์ ๋งค์ฐ ๋นํจ์จ์ ์ด๋ฏ๋ก, SentencePiece๋ ํ ํฐ X๊ฐ ์๋ ๋ชจ๋ธ ์์ค์ ๊ทผ์ฌ์น๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ฒ์๋ถํฐ ์์ํ๋ ๋์ ๋จ์ vocabulary์ ๋ถํ ๋ก ํ ํฐ X๋ฅผ ๋์ฒดํฉ๋๋ค. ์ด๋ฐ ์์ผ๋ก ๋ชจ๋ ์ ์๋ ๋ชจ๋ธ ์์ค๊ณผ ๋์์ ํ ๋ฒ์ ๊ณ์ฐํ ์ ์์ต๋๋ค.
์ด์ ๋ง์ง๋ง์ผ๋ก ํด์ผ ํ ์ผ์ ๋ชจ๋ธ์์ ์ฌ์ฉํ๋ ํน์ ํ ํฐ์ vocabulary์ ์ถ๊ฐํ ๋ค์ ์ํ๋ ํฌ๊ธฐ์ ๋๋ฌํ ๋๊น์ง vocabulary์์ ํ ํฐ์ ๋ฐ๋ณต์ ์ผ๋ก ์ ๊ฑฐํด ๋๊ฐ๋ ๊ฒ์ ๋๋ค:
percent_to_remove = 0.1
while len(model) > 100:
scores = compute_scores(model)
sorted_scores = sorted(scores.items(), key=lambda x: x[1])
# Remove percent_to_remove tokens with the lowest scores.
for i in range(int(len(model) * percent_to_remove)):
_ = token_freqs.pop(sorted_scores[i][0])
total_sum = sum([freq for token, freq in token_freqs.items()])
model = {token: -log(freq / total_sum) for token, freq in token_freqs.items()}
์
๋ ฅ ํ
์คํธ๋ฅผ ํ ํฐํํ๋ ค๋ฉด ์ฌ์ ํ ํฐํ๋ฅผ ์ ์ฉํ ๋ค์ encode_word()
ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค:
def tokenize(text, model):
words_with_offsets = tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str(text)
pre_tokenized_text = [word for word, offset in words_with_offsets]
encoded_words = [encode_word(word, model)[0] for word in pre_tokenized_text]
return sum(encoded_words, [])
tokenize("This is the Hugging Face course.", model)
์ ๋๊ทธ๋จ์ ๋ํด์ ์ค๋ช ํ์ต๋๋ค. ์ง๊ธ์ฏค์ด๋ฉด ํ ํฌ๋์ด์ ์ ๊ดํ ์ ๋ฌธ๊ฐ๊ฐ ๋์ จ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๋ค์ ์น์ ์์๋ ๐ค Tokenizers ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋น๋ฉ ๋ธ๋ก์ ํ๊ตฌํ๊ณ ์ด๋ฅผ ์ฌ์ฉํ์ฌ ์์ ๋ง์ ํ ํฌ๋์ด์ ๋ฅผ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ๊ณต๋ถํด๋ณด๊ฒ ์ต๋๋ค.
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ([๐ค ๊ฐ์ข 6.8] Unigram ํ ํฐํ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@spasis/๊ฐ์ข-6.8-Unigram-ํ ํฐํ์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค