1. 도입
자연어 처리란 컴퓨터가 사람의 언어를 이해할 수 있게 하는 방법이다.
자연어 처리의 고전적인 방법 즉, 딥러닝 이전의 방법을 먼저 알아보고, 딥러닝 기술을 활용한 자연어 처리를 알아보고자 한다.
그리고 파이썬으로 텍스트를 다루는 방법도 배우게 된다.
2. 프로그래밍 언어가 아닌 자연어라 하는 이유
코드와 달리 자연어는 같은 의미의 문장도 여러 형태로 표현할 수 있어서 문장의 뜻이 애매할 수 있거나 의미가 유연하게 변할 가능성이 있기때문에 둘은 다르다.
3. 활용 분야
search engine, machine translation, question answering(과거의 방대한 의료 데이터를 활용해 올바른 치료법을 제안하기도 함), document summarization, emotion analysis 등에서 쓰이고 있다.
4. 단어
말의 의미는 단어로 구성이 돼서 단어를 이해하는 것이 중요하다.
5. 단어를 이해하기 위한 방법
- 시소러스를 활용한 방법
- 통계 기반 방법, 분산 표현
- 추론 기반 방법
6. 시소러스
시소러스란, 유의어 사전을 의미한다. 사람이 직접 (단어의 의미를 정의) + (단어 사이의 상위/하위/전체/부분 관계)를 컴퓨터에게 알려주는 방식을 생각한 것이다. 이를 활용한 모델은 wordnet이 있다.
예를 들면, car == automobile machine motorcar 가 있다.
그런데, 문제점이 존재하여 통계기반 -> 추론기반으로 바뀌게 되었다.
1) 시대 변화에 대응하기 어렵다. 크라우드 펀딩과 같은 신조어나 단어의 의미가 변하는 경우가 있다.
2) 수동적으로 하여 사람의 노동력이 많이 필요하다.
(이미지, 자연어 처리 모두 처음에는 수동으로 feature을 뽑아내곤 했는데 이제는 딥러닝 기술을 활용하여 컴퓨터가 스스로 학습한다.)
3) 단어의 미묘한 차이를 알기 어렵다.
7. 통계 기반 방법, 말뭉치(corpus) 다루기
말뭉치는 대량의 텍스트로 문장을 쓰는 방법, 단어를 선택하는 방법, 단어의 의미 등 사람이 알고 있는 자연어에 대한 지식이 포함되어있다.
이렇게 가득한 말뭉치에서 자동으로 핵심을 추출하는 것이 방법의 목표이다.
7-1. corpus preprocessing
대표적인 corpus로는 구글 뉴스, 위키백과 등이 있다. 작은 데이터를 기반으로 텍스트 데이터를 단어로 분할하고 각 단어마다 id를 부여해보자.
실전이라면, 수천, 수만개의 문장이 담겨있을 것이다.
1) len을 통해 id를 부여했다.
2) 말뭉치 전처리를 통해 corpus, word2id, id2word를 얻었다.
7-2. 단어의 분산 표현
색을 표현하는 방법은 두가지로 나뉜다. 하나는 색의 가짓수만큼 이름을 부여하는 방법, 빨강 초록 ... 다른 하나는 색을 rgb 즉, 3차원 벡터로 표현하는 방법이다. 전자의 방법은 간결하게 표현하기 어렵고, 어떤 색인지 짐작하기도 어려우며 색끼리의 관련성도 표현하기 어렵습니다. 반면에 후자의 경우 간결, 색 짐작, 색 관련성을 알 수 있습니다.
단어도 같은 이유로 벡터로 표현하는 후자의 방법을 선택하는 것이 좋습니다. 이를 distributional representation,분산 표현라고 합니다. 단어를 dense vector로 표현하게 됩니다.
이러한 방법에는 "distributional hypothesis, 단어의 의미는 주변 단어에 의해 형성된다는 분포가설"을 기본으로 합니다. 단어 자체에는 의미가 없고 문맥에 따라서 의미가 만들어진다는 것입니다. 이는 생각해보면 당연합니다.
7-3. 동시발생 행렬, co-occurrence matrix
실제로 분포가설에 기초하여 단어를 벡터로 표현하는 방법을 생각해봅시다. 이는 주변에 단어가 몇 번이나 등장하는 지 통계적인 방법을 사용하는 것입니다.
np.zeros를 통해 임의의 2차원 배열을 만들고, 윈도우 크기만큼 주변 단어를 세어나갑니다. 이를 통해 자동으로 동시발생 행렬을 만들어줍니다. 아무리 큰 corpus라도 행렬을 만들 수 있습니다.
7-4. 벡터간 유사도.
자연어 처리에서 word2id, id2word는 중요하다는 것을 꼭 기억합시다!
유사도를 구하는 방법은 정말 많지만 여기서는 코사인 유사도를 사용합니다. 인수로 제로 벡터가 들어오면 divide by zero error가 발생하니 작은 값을 더해주겠습니다.
이제 유사도를 기준으로 랭킹을 만드는 함수를 만들어봅시다. query, word2idm, id2word, word_matrix, top이 중요한 argument입니다.
검색어의 단어 벡터를 꺼냅니다.
검색어와 나머지 단어들에 대한 유사도를 구합니다.
유사도를 기준으로 순위를 정하여 출력합니다.
이때 배열 인덱스의 정렬을 바꾸는데 argsort()메소드가 사용됩니다.
말뭉치가 작아서 약간의 오류가 있습니다. 다음에서는 이를 개선해보도록 하겠습니다.
7-5. 통계 기반 방법 개선하기.
the, a 같은 경우에는 형식적으로 많이 쓰여서 실제로 관련성이 떨어져도 동시 발생 값이 높아져서 관련성이 높게 나올 수 있다. 예를 들어서 car, drive의 관계보다 car, the의 관계가 더 높게 나타날 수 있는데 이를 방지하는 방법이 점별 상호정보량, pmi(pointwise mutual information)다.
p(x)는 corpus에서 단어 x가 등장할 확률이라고 하면, pmi = log(p(x,y) / p(x)*p(y)로 the처럼 전체적인 곳에서 많이 발생한다면 분모가 너무 커져서 pmi값이 매우 낮아질 것이고, 동시 발생 확률 p(x,y)가 커지면 log값이 커져서 pmi가 높아질 것이다. 즉, 더욱 더 문맥에 맞는 단어 벡터를 얻을 수 있다.
추가로 positive pointwise mutual infromation = max(0, pmi)를 사용하여 음수를 예방하였다.
정리하자면 단어의 의미는 문맥에 따라 정해진다는 분산 가설을 기본으로 단어를 벡터로 표현하는 방법에 대해서 알아보았다. 처음에는 co-occurrence matrix를 사용하여나타냈고, 이를 개선한 ppmi를 통해 단어를 벡터로 표현하였다.
7-6. 메모리 문제 개선, 벡터의 차원 감소 dimensionality reduction
위의 방법을 통해 개선했지만 쓸모없는 메모리가 낭비된다는 단점이 있고 이를 개선하기 위해서 차원을 축소하는 방법을 사용해보자.
데이터의 분포를 고려하여 중요한 축을 찾고 그 축으로 사영된 값으로 바꾼다.
정리하면, sparse vector에서 중요한 축을 찾아서 dense vector으로 표현하는 것인데 이것이야말로 우리가 찾던 단어의 분산 표현입니다. 차원을 감소하는 방법에는 singular vector decomposition SVD를 사용합니다.
단어를 이해하고 벡터로 표현하기 위해서 text -> preprocessing -> corpus -> co-occurrence matrix -> ppmi(sparse vector) -> svd -> dense vector 과정을 거쳤습니다.
7-7. 실전 적용편 (PTB dataset)
penn treebank: 말뭉치가 있는 대규모 텍스트 데이터셋
위의 데이터셋을 다운로드 받아서, co-occurrence matrix -> ppmi(sparse vector) -> svd -> dense vector 그리고 이 벡터를 이용해서 코사인 유사도를 구하고 most_similar을 통해서 순위를 확인하였습니다! 확인해보면 단어의 의미, 문법적인 관점에서 비슷한 단어들이 가까운 벡터로 나타났습니다.
단어의 의미를 벡터로 바꿔서 유사한 단어끼리 묶을 수 있게 되었습니다!!!!!!!
**sklearn. randomized svd
https://scikit-learn.org/stable/modules/generated/sklearn.utils.extmath.randomized_svd.html
최종정리.
자연어 처리를 하기위해서는 단어의 의미를 이해해야합니다. 이를 위해 처음 제시된 방법은 시소러스입니다. 시소러스는 단어의 관계나 의미, 유의어를 사람이 직접 정리하는 방법입니다. 이 방법은 미묘한 의미차이, 시대에 따른 의미변화, 막대한 노력이 들어간다는 단점이 있습니다. 이를 개선하기 위해서 통계 기반의 방법이 등장하였습니다. 단어의 의미는 주변 단어에 의해 형성된다는 분산 가설을 기반으로 말뭉치를 이용하여 단어를 벡터화하는 방법입니다. 처음에는 말뭉치를 전처리를 하고 이를 통해 동시발생 벡터를 만듭니다. 여기에 형식적으로 자주 반복되는 단어에 의해 발생하는 문제점을 개선하기 위해서 ppmi 방법을 적용하여 벡터를 만들어냅니다. 이 벡터는 sparse matrix로 메모리 문제를 야기하는데 SVD를 적용하여 dense matrix로 바꿀 수 있습니다. 이를 통해 단어를 벡터로 바꿀 수 있었습니다. 실제로 ptb데이터셋을 통해 의미와 문법이 비슷한 벡터끼리 묶인다는 것을 확인하였습니다. 추가로 cos_smilarity, most_similar을 확인하였습니다.
'이제는 사용하지 않는 공부방 > Artificial intelligence' 카테고리의 다른 글
[추천시스템] (3) LearningToRank 실습정리 (0) | 2021.05.29 |
---|---|
[추천시스템] (2) LearningToRank 논문정리 (0) | 2021.05.29 |
[밑바닥부터 시작하는 딥러닝] 8강 더 깊게 딥러닝 (0) | 2021.05.21 |
[지도학습 모델] svm, logistic regression, random forest, naive bayes, decision tree, k-nn (0) | 2021.05.20 |
[밑바닥부터 시작하는 딥러닝] 7강 CNN 핵심정리 (0) | 2021.05.15 |