자연어의 이해 (NLP)
1. 언어의 문법
-
문맥의존문법(Context sensitive grammar)
-
문맥의존문법인 대표적인 언어는 자연어입니다.
-
자연어는 사람들이 일상적으로 쓰이는 언어로 영어, 중국어, 스페인어, 한국어등 다양한 종류의 언어가 존재합니다.
-
문맥의존문법은 문맥, 문장에 따라서 의미가 바뀌게 되며 ‘나는 사과가 좋아’ 라는 문장에서 과일의 종류인 ‘사과’를 좋아하는 것일수도 있고 누군가 자신에게 잘못을 저지르고 받는 ‘사과’를 좋아하는 것일 수도 있습니다.
이와 같이 자연어는 문맥에 따라서, 읽는 대상자에 따라서 의미가 바뀌는 해석의 모호성이 존재합니다.
-
-
문맥자유문법(Context free grammar)
- 문맥자유문법인 대표적인 언어는 프로그래밍 언어입니다.
- 프로그래밍 언어는 문맥으로부터 자유로우며 Parser가 존재하기에 의미가 모호한 표현없이 작성한 문법대로 프로그램이 작동하게됩니다.
2. 컴퓨터에게 자연어 이해시키기
언어의 문법에서 언급했다시피 컴퓨터는 자연어가 아닌 프로그래밍 언어를 사용하며 프로그래밍 언어에는 Parser가 존재하기 parse tree를 만들 수 있어서 해석의 모호성이 존재하지 않습니다.
하지만 자연어의 경우 Parser가 존재하지 않기에 문맥에 따라서 의미가 달라지는 해석의 모호성이 존재하는데 프로그래밍 언어를 사용하는 컴퓨터에게 해석의 모호성이 존재하는 자연어를 학습시키는 것은 상당히 어려운 문제라는 것을 알 수가 있습니다.
프로그래밍 언어를 사용하는 컴퓨터에게 자연어를 학습하고 이해시키는 자연어 처리를 흔히 NLP(Natural Language Processing)라고 부르며 많은 사람들이 컴퓨터에게 자연어를 이해시키기 위해서 다양한 노력을 해오고 있습니다.
2.1 자연어 임베딩
자연어 임베딩(Embedding)이란 자연어를 숫자의 나열 벡터로 바꾼 결과 또는 과정을 말합니다. 단어 자체의 의미를 생각해보면 Embed라는 단어의 의미는 ‘끼워넣다’라는 뜻으로 단어나 문장을 벡터에 끼워넣는다고 생각해도 좋습니다.
2.1.1 임베딩의 역할
- 단어, 문장간 관련도, 유사도 계산 (단어 벡터간 유사도를 계산하여 t-sne로 시각화)
- 의미적 문법적 정보를 함축시킬 수 있게 되어 벡터이기 때문에 사칙연산또한 가능합니다.
- 대규모 말뭉치로 학습된 언어모델을 미리 만들어 놓고 사용자에게 필요한 태스크에 맞게 모델을 전이학습시키고 Fine-tuning(미세조정)을 통하여 모델의 성능을 높일 수가 있습니다.
2.1.2 임베딩의 역사
-
통계기반 임베딩
-
특이값 분해를 활용한 잠재의미분석(LSA)
-
단어들의 분포로부터 문서가 생성되는 과정을 역추적하는 방식으로 문서의 토픽을 찾아내는 방법(LDA)
-
잠재의미 분석에 들어가는 입력의 구조를 종류
단어 문서 행렬
TF-IDF 행렬
단어 문맥 행렬
점별 상호정보량 행렬
-
-
규칙(rule)기반의 알고리즘을 사용합니다.
-
-
뉴럴 네트워크 기반 임베딩
- end-to-end 모델이 만들어지기 시작하였습니다.
- 단어 수준 임베딩
- NPLM, word2vec, Glove ,FastText, Swivel
- 문장 수준 임베딩(pre-trained model)
- ELMo, BERT, GPT
2.1.3 임베딩 종류
- 행렬 분해 기반
- Glove, Swive
- 예측 기반
- 뉴럴 네트워크 기반 모델들
- 토픽 기반
- 잠재 디레클레 할당(LDA), 잠재의미분석(LSA)
2.2 자연어 처리 task(문제)의 종류
- Downstream task
- 텍스트 데이터, 자연어를 가지고 실제로 풀어야 하는 문제들을 의미합니다.
- 기계번역(Machine Translation), 개체명 인식, Question-Answering, 챗봇, 감성분석
- Upstream task
- Downstream task를 풀기 전에 앞서서 해결되어야 하는 문제들로 단어들의 전처리 방법을 고민하거나 단어의 의미를 담은 벡터를 만들기 위한 임베딩 벡터를 어떻게 만들지 고민하는 부분입니다.
- 전처리, 임베딩
2.3 언어모델
컴퓨터가 사람들이 사용하는 자연어를 체계적이고 그럴듯한 문맥을 만들어내기 위한 노력중 하나로 언어모델을 만드는 것이 있습니다.
언어모델은 단어가 주어졌을 때, 다음으로 출현할 수 있는 단어들을 예측하는 확률모델로 이러한 확률모델이 제대로 작동하기 위해서는 구조화된 문법이나 일정한 대화 패턴들을 가진 텍스트 데이터를 학습시켜야 합니다.
하지만 일상에서 언어모델에 바로 들어갈 수 있을 정도로 깨끗한 데이터는 거의 존재하지 않으며 대부분 학습에 방해가 되거나 연산량이 낭비되는 노이즈가 포함된 텍스트 데이터들이 존재합니다.
이러한 노이즈가 포함된 텍스트 데이터들을 언어모델에 넣을 수 있도록 만들어주는 과정을 텍스트 데이터의 전처리 과정입니다.
3. 자연어 프로젝트의 과정
해당 포스팅에서는 자연어 프로젝트를 진행하는 과정에서 전처리와 임베딩 과정을 위주로 알아보겠습니다.
3.1 노이즈 제거를 위한 텍스트 데이터 전처리
일반적인 전처리
- 띄어쓰기
- 맞춤법
- 약어
- 특수문자 제거
- 불용어 제거
- 이상치 제거
챗봇을 만들기 위해서 고려되는 전처리
- 불완전한 문장 구성
- 너무 길거나 짧은 문장들
- 혐오표현이 포함된 바람직하지 못한 문장들
영문 데이터에서 사용되는 전처리
- 대소문자 통일
3.2 단어의 의미 단위 분절 방법(Tokenization)
-
공백기반 토큰화
- 공백기반 토큰화의 경우 영문자 데이터에서 큰 효과를 발휘할 수가 있습니다.
- 한국어 데이터의 경우 공백기반 토큰화를 진행하면 단어의 의미대로 분절되어진 것이 아니기 때문에 성능이 좋지 않습니다.
-
형태소 기반 토큰화
- 형태소란 의미를 가진 가장 작은 말의 단위로 한국어 데이터는 형태소 단위로 분절을 해야 단어의 의미대로 나뉘어지게 됩니다.
- 대표적인 한국어 형태소 분석을 위한 도구로 ‘Mecab’과 ‘Khaiii’ 가 있습니다.
- 형태소 기반 토큰화의 문제점은 최근에 나온 신조어인 ‘코로나바이러스’와 같이 기존 형태소 사전에 존재하지 않는 단어들은 <unk> 토큰으로 대체되거나 이상하게 분절되는 등, 제대로 분절이 되어지지 않는 OOV(Out-of-vocabulary)문제가 발생하게 됩니다.
-
BPE 기반 토큰화
-
형태소 기반의 토큰화의 경우 OOV문제가 발새하는데 이 문제를 해결하기 위한 방법으로 대두된 방법은 BPE(Byte Pair Encoding) 방식입니다.
-
예시
aaaaabbadacaabab 이 문장을 BPE로 압축하면
A = aa
B = ab
AAaBbadacaBB 로 압축이 되어집니다.
결과적으로는 압축하기 전의 문장길이보다 압축후의 문장길이가 더 작아지게 되었습니다.
-
-
BPE은 1994년 데이터 압축 분야에서 시작되었으며 2015년에 들어서 토큰화에 적용되어 졌습니다.
-
토큰화에서의 BPE는 한 단어를 여러개의 subword(접두사, 접미사)의 집합으로 보는 방식으로 접근하여 자주 등장하는 단어를 새로운 단어로 치환하여 압축하는 방식 입니다.
-
예시
간장 공장 공장장은 강 공장장이고 된장 공장 공장장은 장 공장장이다.
A = 간장
B = 공장
A B B장은 강 B장이고 된장 B B장은 장 B장이다.
-
-
-
WPM(WordPieceModel )기반 토큰화
-
WPM은 BPE 방식과 차이점이 존재합니다.
-
공백복원을 위해서 단어의 시작부분에 언더바(_)를 추가하였습니다.
예시
[i am a boy] 원래 문장
[_i, _a, m, _a, _b, o, y] 단어의 시작부분에만 _를 추가합니다.
[_i_am_a_boy] 다시 복원을 시작할 때는 모든 토큰을 합칩니다.
[i am a boy] _를 공백으로 치환하면 원래 문장이 나옵니다.
-
빈도수 기반이 아닌 가능도(likelihood)를 증가시키는 방향으로 문자쌍을 합쳐줍니다.
가능도는 어떤 값이 관측되었을 때, 이것이 어떤 확률분포에서 왔을지에 대한 확률로 확률의 확률이라고 생각할 수도 있습니다.
원래 가능도 = L(확률분포 D 관측값 X)로 표현이 가능하지만 WPM에서의 가능도는 Katz’s Back-off Model을 통해 앞서 언더바를 추가한 BPE 방식으로 토큰화된 사전으로부터 결합할 단어들의 가능도, 확률을 구하고 그중에서 가장 높은 가능도의 단어를 선정합니다. 이해를 돕기 위해서 Katz’s Back-off Model이 Trigram 모델인 경우 $C(x)$는 해당 토큰들이 출현한 횟수이고 $w_i$는 주어진 문장의 $i$번째 단어를 의미합니다.
$i-2$번째 단어와 $i-1$번째 단어가 주어졌을 때, $i$번째 단어에 대한 가능도를 구할 때,
만약 $i-2$, $i-1$, $i$번째 단어가 함께 나온 토큰이 사전에 존재하는 경우 $P(w_i \lvert w_{i-2}w_{i-1})$를 출력합니다.
$i-2$, $i-1$, $i$번째 단어가 함께 나온 토큰이 사전에 존재하지 않지만 $i-1$ , $i$번째 단어가 함께 나온 토큰이 사전에 존재하는 경우 Good-Turing estimation으로 구한 $\alpha_1$을 곱한 $\alpha_1P(w_i \vert w_{i-1})$를 출력합니다.
이외의 조건의 경우 $\alpha_2P(w_i)$를 출력하며 이 경우에는 $i$번째 단어는 여태까지 등록된적 없는 처음보는 단어가 됩니다.
-
-
WPM은 어떤 언어에든 적용이 가능한 general한 기법입니다.
-
WPM은 아직 비공개 상태이지만 구글의 setencepiece 패키지가 고성능의 BPE 알고리즘을 제공하고 있습니다.
-
3.3 단어의 의미 학습 방법(Vectorization)
-
One-hot-encoding
-
one hot encoding 방식은 각 사전의 토큰이나 단어들을 벡터의 각 차원, 칼럼마다 대응시키는 방식으로 희소표현이라고도 부릅니다.
예시
[나는 게임을 좋아합니다.]
[나는, 게임을, 좋아, 합, 니다, .]
나는 = [1, 0, 0, 0, 0, 0]
게임을 = [0, 1, 0, 0, 0, 0]
좋아 = [0, 0, 1, 0, 0, 0]
합 = [0, 0, 0, 1, 0, 0]
니다 = [0, 0, 0, 0, 1, 0]
. = [0, 0, 0, 0, 0, 1]
-
해당 방식의 문제점이 존재합니다.
- 단어들의 속성 종류가 늘어나게 되면 계산량이 커지게 됩니다.
- 대부분의 벡터의 원소가 0이기 때문에 불필요한 연산이 발생하게 됩니다.
- 단어들간의 의미적 유사도를 계산할 수 없습니다.
-
-
- 하나의 단어를 모든 차원을 사용한 실수로 표현합니다.
- 실수값은 수많은 데이터들을 통하여 적합한 값을 찾아나갑니다.
- word2vec 학습방식
- CBOW(Conitnuous Bag of word) 방식은 주변단어들을 통하여 하나의 중심단어를 예측하는 모델의 hidden state를 사용합니다.
- Skip-gram 방식은 하나의 중심단어를 통하여 주변단어들을 예측하는 모델의 hidden state를 사용합니다.
-
Fasttext
- Fasttext는 BPE와 유사한 방식을 적용하였습니다.
- Fasttext는 한 단어를 n-gram 집합으로 생각하고 단어를 쪼개어 각 n-grma에 할당된 embedding의 평균값을 사용합니다.
- 자주 등장하지 않는 단어는 최악의 경우 단 한번의 연산을 거치지 않았기 때문에 학습을 하지 않은 초기값과 동일하게 나오는 연산의 빈부격차 문제가 발생합니다.
-
- ELMo는 기존의 word2vec와 Fasttext에서 풀지 못하였던 동음이의어 문제를 해결해준 모델입니다.
- 기존 어휘 임베딩 벡터,와 순방향 LSTM hidden state vector, 역방향 LSTM hidden state vector를 concatenate를 하여 contextual word embedding을 구하게 됩니다.