딥러닝을 이용한 자연어처리 입문 7시간 완성 - 메타코드M
https://www.youtube.com/watch?v=Rf7wvs8ZbP4&ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM
메타코드M 채널에 올려주신 영상에 기반하여 정리해 보겠습니다.
자연어: 사람들이 보편적으로 말하고 쓰는 언어
자연어 처리(NLP): 컴퓨터가 알아들을 수 있게 자연어를 처리해주는 과정
대표적인 task로는
가 있다.
활용 예시
80년대 - Logic based method, Word Embedding
00년대 - RNN, 1d-CNN: 간단한 뉴럴넷 활용.
10~ - Transformer, Attention 등장으로 대표적으론 BERT, GPT가 있다.
주로
토큰화 -> 정제 및 추출 -> 인코딩 -> 분류 -> Padding/similarity
순서로 이루어 진다.
문장을 의미를 가진 단어 기준으로 쪼개는걸 말한다.
우선 언어의 형태소를 알아보자
영어는 띄어쓰기 단위로 쪼개면 대충 맞아 떨어진다.
I like apple. -> I, like, apple
하지만 한국어 특성상 띄어쓰기가 안되어 있지만 쪼갤 수 있는 단위가 존재한다.
나는 사과를 좋아한다. -> 나, 는, 사과, 를, 좋아, 하,-ㄴ, 다
이런식으로 어간+어미, 명사+조사 등 한국어 토큰화의 어려움이 존재한다.
강의에서 한국어 토큰화 알고리즘관련 연구도 할만한 연구주제라고 한다.
토큰화를 하는 방식이 매우 다양하다. 사용하는건 존재하는 package다운받아서 쓰면 간단히 되지만, 어떤식으로 토큰화하는지는 알고 쓰는것이 중요하다.
대표적으로 python nltk에서 제공하는 treebank Tokenization을 사용해 보자.
from nltk.tokenize import TreebankWordTokenizer
tokenizer = TreebankWordTokenizer()
text = "T1 won world championship by 3:0 score"
print(tokenizer.tokenize(text))
['T1', 'won', 'world', 'championship', 'by', '3:0', 'score']
애매한 3:1 같은 특수문자는 한덩어리로 묶었다.
문단 내에서 문장 단위로 쪼개는 것이라고 하는데 잘 사용하지 않는다고 한다.
1) 대문자 vs 소문자
컴퓨터는 같은 단어여도 대문자 소문자가 다르면 다른 단어로 인식한다.
computer 과 Computer
는 같은 뜻이지만 다르게 인식한다. 따라서 다 소문자로 바꿔줘야 한다.
하지만 이런건 어떨까
US, us
US는 '미국'이라는 명사이지만 소문자로 다 바꾸니 '우리'라는 뜻이 되었다. 이런 상황들 때문에 잘 고려해서 바꿔주는 수 밖엔 없다.
2) 출연 횟수가 적은 단어 제거
평생 한번 볼 법한 단어들까지 고려한다면 메모리적으로나 계산에 도움이 되지 않는다. 따라서 그 단어가 문장의 핵심 단어가 아니라면 과감히 버리자.
3) 길이가 짧은 단어, 지시대명사, 관사 제거
the, a, 경우에 따라선 I 같은 단어를 지워도 문장을 해석하는데 있어 큰 지장을 주진 않기 때문에 지우자.
lectures playing kindness
이런 예시 처럼 핵심 의미를 담고있는 부분을 추출할 것이다. (역시 경우에 따라 뒤에 부분이 중요할 수도 있다)
두 개가 대표적인데
품사 정보 x
품사 정보 o
품사 정보가 포함되면 메모리 소요는 높아지지만, bear 같이 명사, 동사의 의미가 매우 다르면 품사를 알아야 하기에 표제어 추출을 이용해야만 한다.
문장 내에서 대세로 작용하지 않는, 중요도가 낮은 단어를 제거한다.
이 역시 nltk package를 이용하면 간단히 수행할 수 있다.
import nltk
nltk.download('stopwords')
from nltk.corpus import stopwords
print(stopwords.words('english')[:5])
['i', 'me', 'my', 'myself', 'we']
영어 불용어 5개를 찍어 보았다.
문장을 토큰화하여 각 토큰이 불용어 목록에 포함되어 있는지를 확인하여 목록에 포함 안된 토큰만 최종 결과로 내면 된다.
text = "hi how are you?"
word_tokens = tokenizer.tokenize(text)
stop_words = stopwords.words('english')
result = []
for w in word_tokens:
if w not in stop_words:
result.append(w)
print(word_tokens)
print(result)
['hi', 'how', 'are', 'you', '?']
['hi', '?']
hi how are you? 에서 hi랑 물음표만 살아남았다. how are you는 인사말 내에서 별 뜻이 없으니 잘 줄인거 같다.
처음 보는 단어에 새 정수를 할당해주는 방식이다.
I am student. Student should study hard.
불용어를 지우고
student. student study hard.
만 남았다고 가정하면
student->1, study->2 hard->3
으로 인코딩 되어
1 1 2 3
문장이 이렇게 될 것이다.
좀 더 효율적으로 하기 위해 등장 횟수가 많은 단어들에 낮은 정수를 할당해 준다. 즉 빈도수를 측정하고 sorting 해주는 과정을 거친다.
예를 들어 빈도순으로 정렬한 결과가
[('student', 4), ('study', 3), ('math', 2), ('pen', 1)]
이라면
문장내에서 등장한 순서에 관계없이
student->1, study->2, math->3, pen->4
로 인코딩 해준다.
길이가 다른 문장에 0을 넣어주어 컴퓨터가 계산하기 편하게 길이를 맞춰주는 과정이다.
문장 여러개를 정수 인코딩 했더니
[1,2], [1,2,2,3], [1,3,4]
이런식으로 나왔다고 가정하면, 다 길이가 다른 상황이다.
이때 zero padding으로 길이를 4로 맞춰준다면
[1,2,0,0], [1,2,2,3], [1,3,4,0]
이런 결과가 나온다.
주로 사용하는 loss function인 Cross-Entropy 함수에 넣기 위해서 0과 1로만 이루어진 list형태로 바꿔주는 과정이다.
예를 들어 1->[1,0,0,0], 2->[0,1,0,0], 3->[0,0,1,0], 4->[0,0,0,1]
이런식으로 바꿔준다.
지금은 단어 종류를 4개로 가정해서 4 bit로 끝났지만, 단어가 정말 다양해서 숫자가 커지면 많은 메모리를 필요로 한다.
따라서 필요할 때(실제 CE함수에 넣기 전)에만 one-hot 형태로 바꿔주는 방법을 취하면 좋다.
다음시간에 자세히 보겠지만, 단어의 유사성을 고려하여 인코딩에 활용하는 방법이다.
단어의 유사한 정도를 가중치로 매기는 공식이다.
tf(d,t):
문서 d에서 단어 t가 등장한 횟수
idf(d,t):
N은 총 문서 갯수, df는 단어 t가 등장한 문서의 수
TF-IDF:
대략적으로 이해하면 한 문서에서 자주 등장한 단어는 높은 tf-idf값을 가진다.
이 있는데 통계/확률 기반 모델을 알아보자
나는 밥을 ___
이런 문장이 있다면,
빈칸에 동사가 들어갈 확률이 높아보인다. 하지만 정말 다양한 문장들이 세상에 존재하기에 반드시 동사가 들어간다고 할 순 없다.
-> 데이터를 기반하여 확률을 근사한다.
위의 예시처럼 문장에 단어수가 적으면 표본이 꽤 많다. 하지만 대부분의 문장에 단어가 많이 포함되어 있기 때문에, 표본 수가 적은 Sparcity problem이 발생한다.
문장 에서
n-1번째 단어로 n번째 단어를 예측한다면, 그 확률은 Markov Chain에 의해
가 되는데
n개, n-1개의 단어가 다 들어있는 문장 표본이 너무 적어 Sparcity Problem이 발생한다.
이를 해결하기 위해 N-gram language model을 활용한다.
다음 단어를 예측할 때 문장 전체를 보지말고, N개의 단어만 보고 예측하자.
예를 들어 N=2라면 (띄어쓰기 기준으로 토큰화 가정)
오늘 밤까지 과제를 내야하는데 1시간 밖에 안남았어 ___.
라는 문장에 있다면
빈칸을 예측할 때 밖에
와 안남았어
를 보고 빈칸을 예측할 것이다.
분명 정확도는 떨어지나, 앞에 몇 개의 단어만 보고 예측하기 때문에 Sparcity problem을 해결 할 수 있다.
Vector 유사도를 이용한 Cosine metric
문장별로 벡터를 만들 때 모든 단어를 다 쓰지말고 일부만 쓰자
불용어를 제외하고 여러 문장들 중에서 단어 몇개만 가지고 벡터 구성
ex)
1. Internet connects everything.
2. Me and Minsu are connected through Internet
3. An apple costs 1$ on Internet.
여기서 BoW에
Internet, connect, everything, through, apple, cost
만 사용하면
1. 1 1 1 0 0 0
2. 1 1 0 1 0 0
3. 1 0 0 0 1 1
이 되어 1,2 사이의 유사도는 , 1,3 사이의 유사도는 로 1,2 사이의 유사도가 더 큰 것을 확인할 수 있다.
단순 거리
문장 A를 B로 수정하기 위한 최소 횟수. 단어 삽입/삭제/변경 가능
코테의 DP방식(Tabular method)을 활용하여 계산한다.
규칙
동일한 경우: 대각선 수
변경: 대각선 수+1
삽입: 상단 수+1
제거: 좌측 수+1
이중 낮은 수를 책정
데이타마닝->데이터마이닝
을 예로 보자
같은 글자라면 대각선 위에거 그대로, 다르다면 좌측, 위, 대각 중 작은 수에 1을 더해 가져온다.
최종 levenshtein거리는 2가 된다.
실제로도 생각해보면 데이타마닝에서 '타'->'터'로 변경
, '이'를 '마', '닝'사이에 넣어주면
2번으로 된다.