개발자로 후회없는 삶 살기

딥러닝 PART.교과목 단어 임베딩 본문

[AI]/[교과목 | 학습기록]

딥러닝 PART.교과목 단어 임베딩

몽이장쥰 2022. 11. 8. 23:52

서론

교과목 7주차 단어 임베딩에 관한 내용을 정리합니다.

 

본론

- NLP에서 단어의 중요성

단어는 사람끼리 대화를 할 때 의미를 알아들어야 합니다. > 즉 단어에 의미가 있습니다. + 대화에는 문맥이 있어서 문장에서 몇 개 빠져도 무슨 단어가 나와야 하는지 추측합니다. > 따라서 문장을 구성하는 게 단어라서 단어를 모르면 자연어 처리는 없습니다.

 

+ 단어는 의미를 가집니다. 같은 단어도 다른 뜻을 가지는 경우도 많고 상황에 따라 다 다릅니다. > 모델이 단어를 이해해야 합니다. 뜻을 알아야 사용할 수 있습니다. > 따라서 개념의 나열이고 개념의 조합입니다. 개념을 놓치면 자연어는 없습니다. (= 이미지도 이미지에서 이해를 해야 하는 것입니다.) > 단어를 가까운 단어 틀린 단어 등 표현하지 않으면 이해할 수 없습니다! (상황에 따라서 문맥이 다르고 문맥에 따라서 단어를 다르게 표현하면 [단어 임베딩] 모델이 이해할 수 있을 것입니다.)

 

>  이걸 하기 위해선 기본적으로 단어를 벡터화해야 합니다. 한글이든 영어든 벡터로 고치는데 사실 그 벡터가 그 단어가 가지는 고유한 의미가 담겨서 들어있고 그래서 비슷한 단어는 비슷한 벡터를 가집니다. (+같은 단어도 의미가 다르면 다른 벡터를 가집니다.) 

 

> 정의 : 임베딩은 이진 벡터로 고치는 것 + 단어 간의 유사한지 다른지 구별할 수 있는 이진 코드로 바뀌는 것입니다. (유사도가 왜 그렇게 중요하냐면 유사도를 알려면 유사한지 아닌지를 알아야 하고 유사한지 아닌지를 알려면 단어의 의미를 알아야 하기 때문에 유사도를 구했다는 것은 단어의 의미를 알았다는 것이기 때문입니다.)

 

※ 딥러닝 모델은 텍스트와 직접 작동하지 않습니다. 대신 텍스트를 숫자로 변환해야 합니다.

 

=> 단어 임베딩의 과거 기술

1. one-hot encoding 

그냥 encoding과 다른 것입니다. cnn의 feature 추출이 encoding이었습니다. (encoding, one-hot encoding, embedding) > 이걸 하면 유클리드 유사도를 계산해도 다 똑같은 1이라서 유사성을 알 수가 없습니다. > 각 단어를 다른 단어와 완전히 독립적으로 취급합니다.

 

2. tf-idf

정확하게 이름만 보면 단어의 빈도는 많아야 하는데 그런 단어의 빈도가 많은 문서는 적어야 하는 것입니다.(inverse)

 

> 문서에 그 단어가 얼마나 많이 등장하는가 > 과학 논문을 알기 위해서 "과학 키워드를 가지고 있는 논문이 과학 논문이다"라고 보는 것입니다. 따라서 논문 검색을 할 때 과학 논문에서 많이 발생하는 단어가 과학 논문을 나타내는 키워드입니다. = frequency가 크면 대표 단어입니다.

 

> 근데 이렇게 하면 큰 걸 놓칩니다. 많이 등장하는 접속사, 관사는 있으나 마나의 필요 없는 것입니다. > + 의학 논문에도 많이 등장하면 과학 논문의 대표 키워드가 아닙니다.

 

> 우리는 특정 문서가 가지고 있는 단어를 원합니다. > 그래서 '적다'의 의미가 inverse입니다. > 결론 : 특정 문서에 많이 등장하는 것 + 모든 문서에 나오면 안 되는 것의 곱입니다.

 

+ tf-idf로 같이 많이 나오는 것을 구하면 유사성이 높은 단어라고 생각도 했습니다. 

 

※ LSA(Latent Semantic Analysis : 잠재 문맥 분석), 주제 모델링과 함께 단어의 잠재 특징으로 구성된 벡터로 생각할 수 있습니다. (이미지로 치면 feature map이 임베딩 벡터입니다. 왜냐하면 단어의 잠재 특징을 가지고 있기 때문입니다.)

 

※ 분산 표현

한 단어의 의미를 문맥상에서 다른 단어와의 관계를 고려해 파악하려는 시도 -> 주변 단어를 보면 그 단어가 무엇인지 알게 될 것입니다. 

 

ex) 파리는 프랑스의 수도다/ 베를린은 독일의 수도다. 

세계 지리를 모르더라도 이 두 문장을 통해 파리, 프랑스, 베를린, 독일의 개체들 사이에 어떤 관계가 있음을 알 수 있습니다. 이는 파리와 프랑스의 관계는 베를린과 독일의 관계와 유사하다고 나타낼 수 있습니다. 다시 말해 분산 임베딩 공간이란 유사한 문맥에서 사용된 단어들은 서로 가깝게 위치하는 공간을 의미합니다. ★ 그러므로 word 벡터들 사이의 공간상 유사성은 대략 이 단어들 사이의 의미상 유사성과 일치합니다.

 

=> 그래서 의미적 유사성이 도대체 뭐길래 그렇게 중요할까요?

가장 중요한 게 단어의 의미를 표현하는 거였고 그러니 유사성도 매우 중요한 것입니다.

 

임베딩하고 찍어보니 킹과 맨이 가깝고 킹과 워먼은 멉니다. = 유사성에는 의미가 반영된다는 것!

 

+ 가정 : 같은 문단이나 문장, 문서 안의 같이 등장하는 두 단어는 많이 관련되어 있고 유사합니다. (근데 그런 문서가 적어야 합니다. =tf-idf) > 그런 걸 같은 문맥을 구성한다고 합니다.

 

-> 문맥

문맥은 문장, 문서 단위입니다. + 문맥 안에 같이 등장하는 단어는 유사한 단어입니다. > 이런 걸 고려하면서 단어를 이진화해야 합니다.

 

★ 정리 : 지금까지 유사성이고 encoding이고 과거의 기술들 전부 다 단어의 의미가 중요하고 의미가 문맥을 구성하고 따라서 의미를 뽑아야 하니 의미를 알아야 문장, 문서의 문맥을 구성할 수 있다는 것을 장황하게 설명했습니다.

 

> 근데 두 단어가 유사하면 같은 문맥을 구성합니다. 따라서 두 단어가 유사한지를 알아야 하고 유사한지 알려면 의미를 뽑아야 하는데 그러려면 임베딩을 해야 합니다.

 

 

- 임베딩

정적 : 다시는 안 바뀝니다. > 학습할 때 바꾸는 방식이 변화가 없습니다. > 어디 가도 말은 같은 벡터로 됩니다.(한계 : 중의어는 구분할 수 없습니다.) 그리고 그 말은 아마 같은 코퍼스에 있는 말(동물, 사람의 말) 일 것입니다. -> 단어를 키로 생각하고 해당 벡터를 값으로 사용한 사전으로 생각할 수 있습니다. 따라서 원래 학습시킨 말뭉치에 포함되지 않은 단어 임베딩의 단어를 찾아야 한다면 못 찾습니다. 

 

동적 : 학습하는 도중에 주변에 어떤 단어가 있냐에 따라서 다르게 변합니다. 사람의 말과 동물 말이 주변에 따라서 뭔지를 알아서 벡터를 차별 있게 만듭니다.

 

-> 순서 : 0. 문장을 확보 > 코퍼스를 만듭니다. (가장 많이 쓰이는 게 위키피디아) > 1. 문맥을 구합니다. -> 이 데이터를 가지고 어떻게 학습을 할까요?(어떻게 임베딩할까 = 어떻게 의미를 찾을까 = 임베딩하는 그 규칙을 학습합니다.)  > 지도 학습에서 라벨이 없는데요? > self 지도학습을 합니다. 써놓은 문장 자체가 정답입니다. 놓은 문장을 보고 모델이 입력-라벨로 만들도록 합니다.

 

= 0. 데이터를 지가 스스로 만들고 만든 말뭉치를 보고 1. 그 단어들을 어떻게 벡터화하는 것이 좋은지 학습을 해야 합니다.

 

=> word2vec(w2v은 너무 범용화 되어있어서 사용할 일이 없을 것이라고 말한다.)

셀프 지도학습입니다. > 학습자가 알아서 훈련 데이터를 입력-출력으로 만들고 인간이 별도로 라벨링 하지 않습니다. > 셀프는 다르다 아예 라벨이 없습니다. 근데 모델은 그걸 받아서 데이터와 라벨을 만듭니다. 데이터를 모델이 데이터-라벨로 만듭니다. -> 셀프 : 문장은 사람이 그냥 줌 근데 그걸 모델이 고쳐서 입력과 라벨을 만듭니다.

 

모델 1. cbow

 

완전 연결망 두 층입니다. 입력층 출력층 2층으로 된 신경망이고 그걸 학습을 시켜야 합니다.(학습 결과는 임베딩 결과를 내야 합니다.) > 두 모델의 차이는 뭘 입력으로 주고 뭘 출력으로 주는 것인가 이것인데 cbow는 임베딩하고 싶은 단어의 한 문장 내에 옆에 인접한 주변 단어(context word)를 줘서 입력으로 들어갑니다. > 이런 걸 '암시적으로 입력을 준다'라고 합니다. > 출력은 중간에 빠진 t가 타겟으로 나오기를 바랍니다.

 

모델 2. skip gram

입력이 타겟이 들어가고 단어를 통해서 은닉, 출력을 거쳐서 주변 단어를 출력으로 내야 합니다.

 

-> 그러면 cbow는 여러 단어가 드러나요? 맞습니다 한 단어도 되지만 윈도우 사이즈로 여러 단어가 들어갑니다. skip-gram은 주변 단어를 한 번에 여러 개 뽑는 게 아니고 주변 단어를 하나씩 하나씩 뽑습니다. (나중에 보면 input과 output을 만드는 것은 그냥 self-supervised 방식인 거라서 데이터 셋에서 여러 행을 먹는다는 것을 의미합니다.) 

 

★지금 하는 것은 원래 있던 단어를 주면 임베딩된 벡터로 나와야 합니다. 사실 얻는 것은 입, 출력이 아니고 가운데 w를 얻는 것입니다. > w를 얻고자 하는 거고 마지막에 얻는 것은 빨간색 w를 얻는다 학습 다 시키고 다 필요 없고 얻는 것은 빨간 w만 얻고 싶습니다. = 표가 나오고 단어 하나당 어떤 벡터로 바뀌어야 하는 지의 행렬 표입니다.

 

※ CBOW가 더 빠르기는 하지만 빈도가 낮은 단어를 예측하는 데는 skip-gram이 더 효과적이라고 합니다.

 

> skip-gram만 설명해 보겠습니다. :

입력 단어의 차원 vdim > 전체 단어가 10000이라면 vdim은 10000입니다. > 만 단어를 다 구분할 수 있도록 one-hot encoding으로 표현하면 10000 열입니다. > c*는 c를 주변 단어를 몇 개를 같이 주는지 의미합니다. > c를 동시에 주나요? 그것도 아니고 > 입력에 대해서 같은 w를 곱해서 마지막에 한 번 더해서 벡터 하나가 만들어진 게 hidden layer를 통과한 것입니다. > 여기는 n차원입니다. > 이게 임베딩 벡터의 dim입니다. 예전에 imdb의 256입니다. = 은닉층의 뉴런 개수가 ndim입니다. > 지금 의미가 비슷한 애들을 차원을 축소시켜서 비슷하게 벡터화하는 것입니다.

 

=> skip-gram 방식 w2v 훈련 방법

① 훈련 데이터를 셀프로 하게 만들어야 합니다. > 이 문장을 위키에서 가져왔습니다. > 윈도우 사이즈는 내 맘이니다. 1이면 킹을 타겟으로 넣어서 이웃(타겟)을 구하면 브레이브이다 맨은 안 됩니다. > 타겟을 브레이브로 하면 주변이 킹과 맨이 나옵니다. 두 번째 문장도 똑같이 윈도우 1로 합니다. > 이렇게 라벨이 없는 데이터를 훈련할 수 있는 데이터 + 라벨로 바꾸는 것입니다. 데이터가 인풋, 아웃풋이 라벨입니다.

 

이웃의 범위가 넓어지면 훈련 데이터가 많아집니다. > pg8을 보면 word가 skip-gram의 입력, 이웃이 주변인 출력입니다. > 이렇게 데이터를 만들고 학습을 시킵니다. > 사람은 그냥 통문장을 줍니다. 라벨 없습니다. > 모델 스스로 데이터, 라벨을 만드므로 self 지도 학습입니다.

 

> 근데 이건 그냥 학습 없이 윈도우 사이즈로 정할 수 있는 거 아닌가요? 맞습니다. 근데 왜 모양이 pg7처럼 괴상하나요? skip-gram 방식 w2v이니 self 지도학습 모양으로 데이터 가공만 하고 w2v를 괴상한 모양으로 학습하는 것입니다.

 

② 학습을 시켜서 단어 임베딩을 하는 것이 skip-gram embedding 방법입니다. > 학습 : 이제는 데이터는 구한 것입니다. 그것을 pg7을 봐서 encoding으로 입력을 넣고 그게 256으로 바꿔고 다시 10000을 구하도록 학습을 하는데 결국 원하는 것은 빨간 w입니다. = 10000 > 256 변환기를 가져옵니다.

 

 

=> pg10

 

pg10 ndim은 2로 내 맘입니다. vdim은 단어 종류 개수 > 마지막 단도 10000이 나와야 하니 softmax를 써야 합니다.

 

 

 

=> pg12

단어의 종류가 6개이고 단어의 개수도 6개라서 6 by 6의 벡터이고 임베딩 layer의 개수는 내 맘대로 2개라서 결국 6 by 6 * 6 by 2인 6 by 2의 빨간 W가 나옵니다. (왜 단어의 개수가 6개인가요? 위 사진은 12개인데요? 저건 데이터 셋이 윈도우를 2로 해서 그런 것입니다. > 순수 단어의 개수만 봐야 하고 중복을 빼고 세야 합니다.)

 

 

결국 pg12의 은닉 층의 w가 2차원 코드로 바뀝니다. > 킹을 넣으면 1, 1이 무조건 나옵니다. 왜냐면 정적 임베딩이기 때문입니다.

 

> 한 번 학습된 w는 변동이 안되고 w에 단어를 곱하기만 하면 해당되는 애가 나옵니다.  왜냐면, 입력은 encoding으로 들어올 거고 그러니 그냥 w 행렬을 끄집어내기만 하면 그게 w입니다. 우리는 w를 원하는 거고 그게 룩업테이블로 이 변환기를 갖고 싶었던 것이고 학습된 결과입니다.

 

★ 왜 룩업 데이블이 정답이냐면 입력이 one-hot으로 들어오고 one-hot의 1이랑 곱해지니깐 (나머지는 0) 변환기지만 사실 그게 임베딩 결과입니다.

 

 

 

Comments