14-1. 들어가며


학습 목표

  • 분산 표현의 직관적 이해, 설명
  • 문장 데이터의 정제 방법 학습
  • 토큰화 기법 학습
  • 단어 임베딩(Embedding) 구축 방법 학습

학습 내용

  • 전처리

    • 자연어의 대표적 3가지 노이즈 유형 확인 & 해결 방법 학습
  • 분산표현

    • 분산 표현이 무엇인지에 대한 학습(+희소표현)
  • 기본 토큰화 방법 학습

    • 그녀는?, 그녀+는?
    • 공백, 형태소 기반 토큰화
  • 토큰화의 다른 방법들

    • OOV 문제 해결한 BPE
    • BPE 변형인 WPM 학습
  • 토큰의 의미 부여

    • 단어 간 의미 찾기 3가지 유형(토큰화 기법❌)

자연어(Natural language)

  • 일상에서 자연히 발생하는 언어

  • ↔️ Artificial language

    • ex) Programming language
  • 언어 문법 이론

    • 프로그래밍 언어 : 문맥 자유 문법(Context-Free Grammar)
    • 자연어 : 문맥 의존 문법(Context-Sensitive Grammar)
  • 자연어 파싱의 어려움

    • Announcing SyntaxNet, Google AI Blog
    • "Alice drove down the street in her car." 문장 해석
      • 엘리스는 본인의 차를 운전해 거리를 달려갔다.
      • 엘리스는 본인의 차 안에 있는 거리를 운전해서 달려갔다.
    • 이 모호성을 해결하는 방법 : real world knowledge(현실 세계에 대한 지식)
      • 자동차 안에 거리가 있을리 없기 때문


14-2. 전처리 : 자연어의 노이즈 제거


  • 자연어에 노이즈가 많다는 말의 뜻?
    • 문장 내의 오타, 철자 오류, 문법 오류, 다의어 등 혼란 요소 존재
    • 문맥, 대화 상황 등에 따라 의미가 바뀌기 때문에 모호함
    • 비속어, 사투리, 외래어 등도 노이즈

  • 이상적이지 않은 데이터(ex.채팅 데이터)에서 발견할 수 있는 노이즈의 유형
    • 불완전한 문장으로 구성된 대화
      • 1문장을 여러 번 나눠 전송, 여러 문장 한번에 전송..
    • 문장 길이가 너무 길거나 짧음
      • 너무 긴 문장 : 관계 없는 문장일 확률이 매우 높음
      • 너무 짧은 문장 : 리액션에 해당하는 경우가 많아 언어 모델 왜곡 우려가 있어 제외해야함
    • 문장 시간 간격이 너무 짧거나 긴 경우
      • 너무 짧은 경우 : 바로바로 보내서 말이 얽히는 것
      • 너무 긴 경우 : 연속된 대화로 보기 어려워짐
    • 바람직하지 않은 문장 사용
      • 욕설 혹은 오타 비율이 높은 문장은 제외해주는 것이 좋음

노이즈 유형 - (1) 문장부호 : Hi, my name is john.

  • 컴퓨터의 경우 Hi,에서 ,까지를 알파벳으로 생각할 수 있음
    • 문장부호 양쪽에 공백 추가로 해결 -> replace
    • 예외가 많지만, 불가피한 손실로 취급하여 넘어가는 경우가 많음
def pad_punctuation(sentence, punc):
    for p in punc:
        sentence = sentence.replace(p, " " + p + " ")

    return sentence

sentence = "Hi, my name is john."

print(pad_punctuation(sentence, [".", "?", "!", ","]))


노이즈 유형 - (2) 대소문자 : First, open the first chapter.

  • 영어에서 발생
  • 같은 의미를 가지고 있음에도 대소문자에 따라 다른 단어로 취급할 가능성이 있음
    • 모든 문자를 소문자로 바꿔 처리 -> lower()
sentence = "First, open the first chapter."
print(sentence.lower())


노이즈 유형 - (3) 특수문자 : He is a ten-year-old boy.

  • 나이 표현 단어를 각각 1개의 단어씩 나눠서 생각할 수 있음
    • 특수 문자 제거로 해결
import re

sentence = "He is a ten-year-old boy."
sentence = re.sub("([^a-zA-Z.,?!])", " ", sentence)

print(sentence)

종합

# From The Project Gutenberg
# (https://www.gutenberg.org/files/2397/2397-h/2397-h.htm)

corpus = \
"""
In the days that followed I learned to spell in this uncomprehending way a great many words, among them pin, hat, cup and a few verbs like sit, stand and walk. 
But my teacher had been with me several weeks before I understood that everything has a name.
One day, we walked down the path to the well-house, attracted by the fragrance of the honeysuckle with which it was covered. 
Some one was drawing water and my teacher placed my hand under the spout. 
As the cool stream gushed over one hand she spelled into the other the word water, first slowly, then rapidly. 
I stood still, my whole attention fixed upon the motions of her fingers. 
Suddenly I felt a misty consciousness as of something forgotten—a thrill of returning thought; and somehow the mystery of language was revealed to me. 
I knew then that "w-a-t-e-r" meant the wonderful cool something that was flowing over my hand. 
That living word awakened my soul, gave it light, hope, joy, set it free! 
There were barriers still, it is true, but barriers that could in time be swept away.
""" 

def cleaning_text(text, punc, regex):
    # 노이즈 유형 (1)
    for p in punc:
        text = text.replace(p, " " + p + " ")

    # 노이즈 유형 (2), (3)
    text = re.sub(regex, " ", text).lower()

    return text

print(cleaning_text(corpus, [".", ",", "!", "?"], "([^a-zA-Z0-9.,?!\n])"))
in the days that followed i learned to spell in this uncomprehending way a great many words ,  among them pin ,  hat ,  cup and a few verbs like sit ,  stand and walk .  
but my teacher had been with me several weeks before i understood that everything has a name . 
one day ,  we walked down the path to the well house ,  attracted by the fragrance of the honeysuckle with which it was covered .  
some one was drawing water and my teacher placed my hand under the spout .  
as the cool stream gushed over one hand she spelled into the other the word water ,  first slowly ,  then rapidly .  
i stood still ,  my whole attention fixed upon the motions of her fingers .  
suddenly i felt a misty consciousness as of something forgotten a thrill of returning thought  and somehow the mystery of language was revealed to me .  
i knew then that  w a t e r  meant the wonderful cool something that was flowing over my hand .  
that living word awakened my soul ,  gave it light ,  hope ,  joy ,  set it free !  
there were barriers still ,  it is true ,  but barriers that could in time be swept away .


14-3. 분산표현 : 바나나와 사과의 관계를 어떻게 표현할까?


단어의 희소 표현, 분산 표현

희소 표현(Sparse representation)

  • 단어를 고차원 벡터로 변환
  • 남자와 여자를 수로 표현 - "성별" 속성
    • 남자: [-1], 여자: [1](or 남자: [1], 여자: [-1])
  • 소년, 소녀 추가 - "성별" 속성 + "나이가 어리다" 속성
    • 소년: [-1, -1], 소녀: [1, -1]
    • 할머니, 할아버지 = 할아버지: [-1, 1], 할머니: [1, 1]
      ...
  • 0.0(관계 없음 or 중립 의미)
{
    //     [성별, 연령]
    남자:  [-1.0, 0.0],
    여자: [1.0, 0.0],
    소년: [-1.0, -0.7],
    소녀: [1.0, -0.7],
    할머니: [1.0, 0.7],
    할아버지: [-1.0, 0.7],
    아저씨: [-1.0, 0.2],
    아줌마: [1.0, 0.2]
}

  • "과일인지 아닌지 판단" 속성 추가 + "색깔" 속성 추가
{
    //      [성별, 연령, 과일, 색깔]
    남자: [-1.0, 0.0, 0.0, 0.0],
    여자: [1.0, 0.0, 0.0, 0.0],
    사과: [0.0, 0.0, 1.0, 0.5],   // 빨갛게 익은 사과
    바나나: [0.0, 0.0, 1.0, -0.5] // 노랗게 익은 바나나
}
  • 희소 표현의 문제점
    • 고차원
    • 불필요한 메모리, 연산량 낭비
    • 희소 표현 워드 벡터 -> 단어들 간의 의미적 유사도 계산 불가
      • 의미속성을 공유하지 않는 희소 표현 워드 벡터 코사인 유사도
        • 공유 의미 속성이 없어 두 벡터 내적 0 -> 코사인 유사도 0

분산 표현(distributed representation)

  • 임베딩 레이어를 통해 구현
  • 각 단어가 몇 차원 속성을 가질지 정의하는 것
    • ex) 100개의 단어를 256차원 속성으로 표현
    embedding_layer = tf.keras.layers.Embedding(input_dim=100, output_dim=256)
  • 속성값의 임의 정의가 아닌 텍스터 데이터를 읽어가는 과정에서 적합한 값을 찾아가는 것
    • 훈련된 분산 표현 모델로 단어 간 의미 유사도 계산
    • feature를 통해 복잡한 자연어 처리 모델 훈련

정리

  • 희소 표현
    • 이진화 or 빈도수 등 방식으로 표현(단어를 고정된 크기의 벡터로 표현하지 않음)
    • 단어 존재 유무만
    • 벡터 공간 상 거리 측정 불가
    • 단어 간 의미 관계 파악 어려움

  • 분산 표현
    • 단어를 고정된 크기 벡터로 표현
    • 1개의 단어 ➡️ 여러 차원 값으로 나타냄
    • 단어 간 거리 측정 ➡️ 단어 간 의미 관련 파악 가능

단어 사전 구성과 활용의 문제

  • 컴퓨터는 문장을 단어 단위로 정확히 끊지 못해 문제가 발생할 수 있음


14-4. 토큰화 : 그녀는? 그녀+는?


토큰(Token)과 토큰화(Tokenization) 기법

  • 토큰 : 문장을 어떤 기준으로 쪼갰을 때의, 쪼개진 각 단어들을 뜻함
  • 토큰화 기법 : 쪼갠 기준

토큰화의 필요성

  • 텍스트 전처리, 문장 의미 파악, 모델 성능 향상, 정보 검색 등을 이유로 필요
  • 적절한 토큰화 기법을 사요해야 자연어 처리 모델 성능이 향상될 것

공백 기반 토큰화

  • split() 사용
    • 불가피한 손실 : days, day가 따로 저장되는 문제
corpus = \
"""
in the days that followed i learned to spell in this uncomprehending way a great many words ,  among them pin ,  hat ,  cup and a few verbs like sit ,  stand and walk .  
but my teacher had been with me several weeks before i understood that everything has a name . 
one day ,  we walked down the path to the well house ,  attracted by the fragrance of the honeysuckle with which it was covered .  
some one was drawing water and my teacher placed my hand under the spout .  
as the cool stream gushed over one hand she spelled into the other the word water ,  first slowly ,  then rapidly .  
i stood still ,  my whole attention fixed upon the motions of her fingers .  
suddenly i felt a misty consciousness as of something forgotten a thrill of returning thought  and somehow the mystery of language was revealed to me .  
i knew then that  w a t e r  meant the wonderful cool something that was flowing over my hand .  
that living word awakened my soul ,  gave it light ,  hope ,  joy ,  set it free !  
there were barriers still ,  it is true ,  but barriers that could in time be swept away . 
"""

tokens = corpus.split()

print("문장이 포함하는 Tokens:", tokens)
문장이 포함하는 Tokens: ['in', 'the', 'days', 'that', 'followed', 'i', 'learned', 'to', 'spell', 'in', 'this', 'uncomprehending', 'way', 'a', 'great', 'many', 'words', ',', 'among', 'them', 'pin', ',', 'hat', ',', 'cup', 'and', 'a', 'few', 'verbs', 'like', 'sit', ',', 'stand', 'and', 'walk', '.', 'but', 'my', 'teacher', 'had', 'been', 'with', 'me', 'several', 'weeks', 'before', 'i', 'understood', 'that', 'everything', 'has', 'a', 'name', '.', 'one', 'day', ',', 'we', 'walked', 'down', 'the', 'path', 'to', 'the', 'well', 'house', ',', 'attracted', 'by', 'the', 'fragrance', 'of', 'the', 'honeysuckle', 'with', 'which', 'it', 'was', 'covered', '.', 'some', 'one', 'was', 'drawing', 'water', 'and', 'my', 'teacher', 'placed', 'my', 'hand', 'under', 'the', 'spout', '.', 'as', 'the', 'cool', 'stream', 'gushed', 'over', 'one', 'hand', 'she', 'spelled', 'into', 'the', 'other', 'the', 'word', 'water', ',', 'first', 'slowly', ',', 'then', 'rapidly', '.', 'i', 'stood', 'still', ',', 'my', 'whole', 'attention', 'fixed', 'upon', 'the', 'motions', 'of', 'her', 'fingers', '.', 'suddenly', 'i', 'felt', 'a', 'misty', 'consciousness', 'as', 'of', 'something', 'forgotten', 'a', 'thrill', 'of', 'returning', 'thought', 'and', 'somehow', 'the', 'mystery', 'of', 'language', 'was', 'revealed', 'to', 'me', '.', 'i', 'knew', 'then', 'that', 'w', 'a', 't', 'e', 'r', 'meant', 'the', 'wonderful', 'cool', 'something', 'that', 'was', 'flowing', 'over', 'my', 'hand', '.', 'that', 'living', 'word', 'awakened', 'my', 'soul', ',', 'gave', 'it', 'light', ',', 'hope', ',', 'joy', ',', 'set', 'it', 'free', '!', 'there', 'were', 'barriers', 'still', ',', 'it', 'is', 'true', ',', 'but', 'barriers', 'that', 'could', 'in', 'time', 'be', 'swept', 'away', '.']

형태소 기반 토큰화

  • 한국어는 공백 기반으로 토큰화하기 어려운 언어
  • 형태소?
    • 뜻을 가진 가장 작은 말의 단위
    • ex) "오늘도 공부만 한다" -> 오늘, , 공부, , 한다

KoNLPy

Q. 100만 문장 데이터를 형태소 분석, 속도 측면에서 가장 뛰어난 분석기는?
A. mecab

Q. 정확도 기준(시간 오래 걸려도 됨) + 띄어쓰기, 오탈자에 강한 분석기?
A. KOMORAN을 사용하고 추가적으로 mecab, 꼬꼬마도 고려


한국어 형태소 분석기 사용 비교 실험

  • konlpy, Mecab 설치
$ pip install konlpy
$ git clone https://github.com/SOMJANG/Mecab-ko-for-Google-Colab.git
$ bash install_mecab-ko_on_colab190912.sh
  • JVM 관련 오류 발생 시
$ sudo apt update
$ sudo apt install default-jre
  • 형태소 분석
tokenizer_list = [Hannanum(),Kkma(),Komoran(),Mecab(),Okt()]

kor_text = '코로나바이러스는 2019년 12월 중국 우한에서 처음 발생한 뒤 전 세계로 확산된, 새로운 유형의 호흡기 감염 질환입니다.'

for tokenizer in tokenizer_list:
    print('[{}] \n{}'.format(tokenizer.__class__.__name__, tokenizer.pos(kor_text)))
[Hannanum] 
[('코로나바이러스', 'N'), ('는', 'J'), ('2019년', 'N'), ('12월', 'N'), ('중국', 'N'), ('우한', 'N'), ('에서', 'J'), ('처음', 'M'), ('발생', 'N'), ('하', 'X'), ('ㄴ', 'E'), ('뒤', 'N'), ('전', 'N'), ('세계', 'N'), ('로', 'J'), ('확산', 'N'), ('되', 'X'), ('ㄴ', 'E'), (',', 'S'), ('새롭', 'P'), ('은', 'E'), ('유형', 'N'), ('의', 'J'), ('호흡기', 'N'), ('감염', 'N'), ('질환', 'N'), ('이', 'J'), ('ㅂ니다', 'E'), ('.', 'S')]
[Kkma] 
[('코로나', 'NNG'), ('바', 'NNG'), ('이러', 'MAG'), ('슬', 'VV'), ('는', 'ETD'), ('2019', 'NR'), ('년', 'NNM'), ('12', 'NR'), ('월', 'NNM'), ('중국', 'NNG'), ('우', 'NNG'), ('하', 'XSV'), ('ㄴ', 'ETD'), ('에', 'VV'), ('서', 'ECD'), ('처음', 'NNG'), ('발생', 'NNG'), ('하', 'XSV'), ('ㄴ', 'ETD'), ('뒤', 'NNG'), ('전', 'NNG'), ('세계', 'NNG'), ('로', 'JKM'), ('확산', 'NNG'), ('되', 'XSV'), ('ㄴ', 'ETD'), (',', 'SP'), ('새', 'NNG'), ('롭', 'XSA'), ('ㄴ', 'ETD'), ('유형', 'NNG'), ('의', 'JKG'), ('호흡기', 'NNG'), ('감염', 'NNG'), ('질환', 'NNG'), ('이', 'VCP'), ('ㅂ니다', 'EFN'), ('.', 'SF')]
[Komoran] 
[('코로나바이러스', 'NNP'), ('는', 'JX'), ('2019', 'SN'), ('년', 'NNB'), ('12월', 'NNP'), ('중국', 'NNP'), ('우', 'NNP'), ('한', 'NNP'), ('에서', 'JKB'), ('처음', 'NNG'), ('발생', 'NNG'), ('하', 'XSV'), ('ㄴ', 'ETM'), ('뒤', 'NNG'), ('전', 'MM'), ('세계로', 'NNP'), ('확산', 'NNG'), ('되', 'XSV'), ('ㄴ', 'ETM'), (',', 'SP'), ('새롭', 'VA'), ('ㄴ', 'ETM'), ('유형', 'NNP'), ('의', 'JKG'), ('호흡기', 'NNG'), ('감염', 'NNP'), ('질환', 'NNG'), ('이', 'VCP'), ('ㅂ니다', 'EF'), ('.', 'SF')]
[Mecab] 
[('코로나', 'NNP'), ('바이러스', 'NNG'), ('는', 'JX'), ('2019', 'SN'), ('년', 'NNBC'), ('12', 'SN'), ('월', 'NNBC'), ('중국', 'NNP'), ('우한', 'NNP'), ('에서', 'JKB'), ('처음', 'NNG'), ('발생', 'NNG'), ('한', 'XSV+ETM'), ('뒤', 'NNG'), ('전', 'NNG'), ('세계', 'NNG'), ('로', 'JKB'), ('확산', 'NNG'), ('된', 'XSV+ETM'), (',', 'SC'), ('새로운', 'VA+ETM'), ('유형', 'NNG'), ('의', 'JKG'), ('호흡기', 'NNG'), ('감염', 'NNG'), ('질환', 'NNG'), ('입니다', 'VCP+EF'), ('.', 'SF')]
[Okt] 
[('코로나바이러스', 'Noun'), ('는', 'Josa'), ('2019년', 'Number'), ('12월', 'Number'), ('중국', 'Noun'), ('우한', 'Noun'), ('에서', 'Josa'), ('처음', 'Noun'), ('발생', 'Noun'), ('한', 'Josa'), ('뒤', 'Noun'), ('전', 'Noun'), ('세계', 'Noun'), ('로', 'Josa'), ('확산', 'Noun'), ('된', 'Verb'), (',', 'Punctuation'), ('새로운', 'Adjective'), ('유형', 'Noun'), ('의', 'Josa'), ('호흡기', 'Noun'), ('감염', 'Noun'), ('질환', 'Noun'), ('입니다', 'Adjective'), ('.', 'Punctuation')]

사전에 없는 단어의 문제

코로나바이러스는 2019년 12월 중국 우한에서 처음 발생한 뒤
전 세계로 확산된, 새로운 유형의 호흡기 감염 질환입니다.

<unk>는 2019년 12월 중국 <unk>에서 처음 발생한 뒤
전 세계로 확산된, 새로운 유형의 호흡기 감염 질환입니다.
  • 공백 기반, 형태소 기반 토큰화 기법 모두 "의미를 가지는 단위로 토큰 생성"
    • 자주 등장한 상위 N개 단어만 사용
    • 나머지는 Unknown Token으로 치환
  • 핵심 단어를 Unknown Token으로 처리한다면?
    • OOV(Out-Of-Vocabulary) 문제 발생
    • 새 단어에 대해 약한 모습을 보임
    • 해결 : Wordpiece Model


14-5. 토큰화 : 다른 방법들


Byte Pair Encoding(BPE)

  • 데이터 중 가장 많이 등장하는 Byte Pair를 새 단어로 치환 -> 압축 반복
aaabdaaabac # 가장 많이 등장한 바이트 쌍 "aa"를 "Z"로 치환합니다.
→ 
ZabdZabac   # "aa" 총 두 개가 치환되어 4바이트를 2바이트로 압축하였습니다.
Z=aa        # 그다음 많이 등장한 바이트 쌍 "ab"를 "Y"로 치환합니다.
→ 
ZYdZYac     # "ab" 총 두 개가 치환되어 4바이트를 2바이트로 압축하였습니다.
Z=aa        # 여기서 작업을 멈추어도 되지만, 치환된 바이트에 대해서도 진행한다면
Y=ab        # 가장 많이 등장한 바이트 쌍 "ZY"를 "X"로 치환합니다.
→ 
XdXac
Z=aa
Y=ab
X=ZY       # 압축이 완료되었습니다!

Q. BPE가 OOV 문제를 해결했다고 하는 이유?
A. BPE를 통해 기존에 없던 단어가 등장해도 그 단어를 구성하는 문자 조합들이 기존에 등장한 문자 쌍과 일치하는지 확인할 수 있다면 -> 문제 해결이 가능하다는 의미


관련 논문 : Neural Machine Translation of Rare Words with Subword Units

import re, collections

# 임의의 데이터에 포함된 단어들입니다.
# 우측의 정수는 임의의 데이터에 해당 단어가 포함된 빈도수입니다.
vocab = {
    'l o w '      : 5,
    'l o w e r '  : 2,
    'n e w e s t ': 6,
    'w i d e s t ': 3
}

num_merges = 5

def get_stats(vocab):
    """
    단어 사전을 불러와
    단어는 공백 단위로 쪼개어 문자 list를 만들고
    빈도수와 쌍을 이루게 합니다. (symbols)
    """
    pairs = collections.defaultdict(int)
    
    for word, freq in vocab.items():
        symbols = word.split()

        for i in range(len(symbols) - 1):             # 모든 symbols를 확인하여 
            pairs[symbols[i], symbols[i + 1]] += freq  # 문자 쌍의 빈도수를 저장합니다. 
        
    return pairs

def merge_vocab(pair, v_in):
    """
    문자 쌍(pair)과 단어 리스트(v_in)를 입력받아
    각각의 단어에서 등장하는 문자 쌍을 치환합니다.
    (하나의 글자처럼 취급)
    """
    v_out = {}
    bigram = re.escape(' '.join(pair))
    p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)')
    
    for word in v_in:
        w_out = p.sub(''.join(pair), word)
        v_out[w_out] = v_in[word]
        
    return v_out, pair[0] + pair[1]

token_vocab = []

for i in range(num_merges):
    print(">> Step {0}".format(i + 1))
    
    pairs = get_stats(vocab)
    best = max(pairs, key=pairs.get)  # 가장 많은 빈도수를 가진 문자 쌍을 반환합니다.
    vocab, merge_tok = merge_vocab(best, vocab)
    print("다음 문자 쌍을 치환:", merge_tok)
    print("변환된 Vocab:\n", vocab, "\n")
    
    token_vocab.append(merge_tok)
    
print("Merged Vocab:", token_vocab)
>> Step 1
다음 문자 쌍을 치환: es
변환된 Vocab:
 {'l o w ': 5, 'l o w e r ': 2, 'n e w es t ': 6, 'w i d es t ': 3} 

>> Step 2
다음 문자 쌍을 치환: est
변환된 Vocab:
 {'l o w ': 5, 'l o w e r ': 2, 'n e w est ': 6, 'w i d est ': 3} 

>> Step 3
다음 문자 쌍을 치환: lo
변환된 Vocab:
 {'lo w ': 5, 'lo w e r ': 2, 'n e w est ': 6, 'w i d est ': 3} 

>> Step 4
다음 문자 쌍을 치환: low
변환된 Vocab:
 {'low ': 5, 'low e r ': 2, 'n e w est ': 6, 'w i d est ': 3} 

>> Step 5
다음 문자 쌍을 치환: ne
변환된 Vocab:
 {'low ': 5, 'low e r ': 2, 'ne w est ': 6, 'w i d est ': 3} 

Merged Vocab: ['es', 'est', 'lo', 'low', 'ne']
  • lowest라는 새 단어 등장 ➡️ 알고리즘 적용 ➡️ low, est 결합으로 표현 가능
  • 큰 데이터도 원하는 크기로 사전 정의 가능(OOV 문제 발생하지 않음)
  • Embedding 레이어 : 단어 개수 x Embedding 차원 수 Weight 생성
    • 단어 개수 줄어듦 -> 메모리 절약

Wordpiece Model(WPM)

  • 구글에서 BPE 변형해 알고리즘 구현
  • 공개되어 있지 않음
  • 구글 SentencePiece 라이브러리고성능 BPE 사용은 가능
    • 전처리도 포함되어 데이터 정제 필요 없음

      차별성

      • 공백 복원 : 단어 시작 부분에 _ 추가
        ex) [_i, _am, _a, _b, o, y, _a, n, d, _you, _are, _a, _gir, l] : 문장 복원 시 모든 토큰 합치기 + _를 공백으로 치환하면 되기 때문에 간단

      • 가능도(Likelihood) 증가 방향으로 문자싸 합침
    • 더 그럴듯한 토큰을 생성하는 것
    • JAPANESE AND KOREAN VOICE SEARCH

  • WPM의 시사점
    • 한국어(조사, 어미 등 활용 많고, 복잡)와 같은 모델의 토크나이저로 사용 가능함
    • 한국어 형태소 분석기와 같은 기법보다 제너럴함
      • language-neutral하고 general한 기법

  • 가능도
    • 확률 vs 가능도
    • 모델이나 가설이 ➡️ 관찰 데이터에 얼마나 잘 맞는지 정량적 추정(측정)
    • 즉, 관찰된 데이터가 주어진 경우 다양한 모델 혹은 매개변수 설정이 그 데이터를 얼마나 잘 설명하는지 평가하는 것
    • 최대 가능도 추정(MLE) : 주어진 데이터에 대한 가능도 최대화 매개변수를 찾는 방법으로 사용됨

  • Katz's Back-off Model
    • LM에서 등장하지 않은 단어에 대한 확률 할당이 가능한 모델

soynlp

  • 한국어 자연어 처리 라이브러리(단어 추출, 품사 판별, 전처리 등도 제공)
  • 형태소 기반 koNLPy 단점 보완
  • "학습데이터를 이용하지 않으면서 데이터에 존재하는 단어를 찾거나, 문장을 단어열로 분해, 혹은 품사 판별을 할 수 있는 비지도학습 접근법을 지향합니다"
    • 단어 경계 결정을 비지도학습으로 하겠다는 의미
    • 미등록 단어에 대한 토큰화가 가능해짐
    • 이러한 방법은 통계적 방법 -> 통계 기반 토크나이저로 분류하기도 함

여전한 문제점

  • 한국어
    • 자동차 ➡️ _자동 / 차
      • 차의 의미가 또 다시 모호해짐
    • 토큰화가 완벽히 되더라도, 남자가 [-1, 0]인지 [1, 0]인지 알기 어려움
    • Embedding 레이어 : 선언 즉시 랜덤 실수로 weight 채움 -> 학습 진행하면서 튜닝하는 걸로 속성을 맞추는데..확실한 방법이 아님


14-6. 토큰에게 의미를 부여하기


Word2Vec

  • 단어를 벡터로 만드는 것
  • 동시에 등장하는 단어들 ➡️ 연관성이 있다는 아이디어에서 시작된 알고리즘
  • 2가지 방식
    • CBOW(Continuous Bag of Words) : 주변에 있는 단어를 입력으로 중간에 있는 단어들을 예측
    • Skip-Gram : 중간에 있는 단어들을 입력으로 주변 단어들을 예측

  • Word2Vec는 딥러닝 모델이 아님
    • 은닉층이 1개이기 때문에 Shallow Neural Network임

  • 어느 것이 더 성능이 좋을까?
    • 논리적으로만 봤을 경우, CBOW가 더 좋아 보임
    • 그러니, 실제 실험에서는 Skip-gram이 더 우세함!

FastText


ELMo - the 1st Contextualized Word Embedding

  • 이전의 문제들

    • 동음이의어에 대한 처리가 잘 되지 않음
    • Context-sensitive Grammar를 따르는 자연어 이해에는 context 활용이 필요
    • 단어 의미 벡터를 구하기 위해서는 그 단어 주변 단어의 맥락뿐만 아니라 시퀀스 전체 맥락을 함께 고려해야함(그러한 Word Embedding이 필요)
  • ELMo : 데이터에 단어가 등장하면, 그때 바로 그 주변 단어 정보를 이용해 임베딩을 구축

    • Contextualized Word Embedding Model
  • 전이 학습 기반 NLP (1): ELMo

  • Contextual Word Embedding이 되는 벡터 3가지

    • 기존 어휘 임베딩(입력 토큰 워드 벡터)
    • 순방향 LSTM hidden state vector
    • 역방향 LSTM hidden state vector ➡️ concatenate한 벡터
profile
언젠가 내 코드로 세상에 기여할 수 있도록, BE&Data Science 개발 기록 노트☘️

0개의 댓글