티스토리 뷰
문서의 내용을 분석해서 분류하거나, 문서의 주제를 추출하거나, 문법 분석을 해서 문장 구조를 파악하거나, 고유 명사를 추출하는 등의 용도로 사용한다.
5.1 문서 분류 시스템 만들기
1) 문서 분류에 많이 사용하는 피처
** 단어 빈도 피처
문서 내용을 완벽하게 이해하는 머신러닝 시스템은 아직 존재하지 않는다. 그래서 간단한 모델을 이용하여 약간은 부정확하지만 적당한 수준의 시스템을 만든 후 많은 문서로 학습시켜 조금씩 더 나은 좋은 결과를 만들어내는 방식이 주로 사용된다.
이러한 간단한 모델에 사용되는 피처의 예로는 단어 빈도를 들 수 있다. 이 피처는 문서에서 단어가 얼마나 자주 나오는지 측정해서 문서 내용을 파악하는 방법이다. 단어 빈도는 단어가 문서에서 얼마나 나오는지 계산한 후 문서 전체 단어 숫자로 나누어 그 비율을 계산한다. 물론 단어가 단순히 몇 번 출현하는지 세는 단어 카운팅 방식도 많이 사용하지만, 이 방식은 한 문서가 길고 다른 문서가 짧을 경우 공정한 비교가 어렵기 때문에 횟수보다는 빈도를 더 많이 사용한다. 때로는 단어의 존재 여부만 체크하는 단어 출현도 유용하다(단순히 문서를 긍정 또는 부정으로 평가할 때 의외로 좋은 성능을 보여준다).
i번째 단어 빈도 피처 = i번째 단어가 문서에 나타난 횟수 / 문서의 총 단어 수
즉, 단어 빈도 피처는 가능한 모든 단어(보통 단어집이라고 부른다)의 개수만큼의 피처를 가지며 각각의 값은 단어가 문서에 나타난 횟수와 문서의 총 단어 수로 결정된다.
단어 빈도 피처는 순서를 구분하지 않고 숫자만 세기 때문에 순서에 영향을 받지 않는다.
** TF-IDF
단어 빈도 피처의 한 가지 문제점은 단어 하나하나의 중요도가 동일하기 때문에 빈도수가 높은 단어를 상대적으로 중요하다고 오인할 수 있다. TF-IDF(Term-Frequency Inverse-Document Frequency) 방법을 이용하면 단어의 희귀도를 고려해서 피처를 생성할 수 있다.
TF-IDF = 단어 빈도 * 역문서 빈도
가능한 모든 단어 중 i번째 IDF 피처 = log 전체 문서 수 / i번째 단어가 나타나는 문서 수
많은 문서에서 흔하게 등장하는 단어의 IDF가 낮다. TF-IDF 피처는 중요한 단서에 강조를 주어 문서를 구분하는 데 도움을 준다.
전체적으로 자주 나오지 않는 단어의 로그값이 너무 작아서 IDF가 예외적으로 커지는 것을 막기 위해 IDF에 약간 변형을 주어 사용하기도 한다. 바로 log를 취하기 전에 1을 더해서 다음과 같이 계산하는 방법이다.
스무딩된 IDF 피처 = log(1+전체 문서 수 / i번째 단어가 나타나는 문서 수)
** 토픽 또는 군집에 기반한 피처
지금까지는 단순히 단어 출현 횟수를 세거나 그 중요도를 고려해서 피처를 정하는 방법이었다. 단어 외에 더 큰 의미 단위를 이용해보는 건 어떨까? 예를 들어 단어들을 군집한 후 각 문서에 나타나는 단어가 어떤 군집에 해당되는지, 혹은 각 문서가 어떤 토픽으로 구성되는지 파악한 다음 각 토픽들이 가지는 중요도를 계산해서 피처를 만드는 방법을 생각해볼 수 있다.
2) 피처를 이용해서 실제로 분류하기
** 로지스틱 회귀
로지스틱 회귀는 선형 회귀 모델에 로지스틱 함수를 적용해서 분류를 하는 기법이다. 이 모델은 간단해서 구현이 쉬우며 좋은 성능을 내기 때문에 자주 사용된다. 로지스틱 회귀는 선형 회귀와 밀접한 연관관계를 가지고 있다.
선형회귀는 간단하지만 학습이 빠르고 모델이 단순함에도 불구하고 좋은 성능을 보이므로 굉장히 널리 쓰인다. 하지만 주어진 입력에 따라 연속적인 산술값을 출력하는 회귀 기법이기 때문에 분류를 할 때는 약간 변형시켜 사용해야 한다. 이 변형을 위해 로지스틱 함수를 이용한다. 로지스틱 함수는 임의의 숫자를 0에서 1 사이의 값으로 변환시키는 함수로, 다음과 같이 정의한다.
σ(x) = 1 / 1+e^(-x)

로지스틱 함수는 선형 회귀의 연속적인 숫자값을 확률값으로 변환한다. 이를 이용해서 결과가 어떤 분류에 해당하는지와 해당하지 않는지 알 수 있다(이항분류). 예를 들어 입력 데이터의 로지스틱 회귀 값이 0.5보다 크면 분류 1에 속하고, 0.5보다 작으면 분류 0에 속한다는 것을 알 수 있다.
y가 어떤 분류에 해당할 확률 = p(y=1) = 1/(1+e^-∑_i(w_i x_i-w_0))
좀 더 복잡한 로지스틱 회귀에는 다항 로지스틱 회귀가 있다. 이를 소프트맥스 회귀라고도 부른다. 이항 로지스틱 회귀와 굉장히 비슷하다. 모든 가능한 항목에 대해 선형 회귀를 수행한 다음 소프트맥스 함수에 통과시킨다. 소프트맥스 함수는 로지스틱 함수의 확장판이라고 생각하면 되는데, 여러 개의 선형 회귀 값을 가지고 각각을 0부터 1까지 변환시킨다고 생각하면 된다.
2) SVM
SVM은 문서 분류 문제에 사용되는 표준적인 분류 모델이다. 로지스틱 회귀가 확률을 로지스틱 함수를 사용해서 모델링한다면 SVM은 확률을 직접 계산하지 않고 데이터가 어떤 '경계선'을 넘는지 넘지 않는지 검사하여 분류한다.결과적으로 SVM은 확률값이 아닌 분류값을 출력한다.
데이터와 경계선 사이의 최소 간격을 최대화하는 경계션을 고른다. 두 분류를 구분하는 경계선만 존재하기 때문에 로지스틱 회귀처럼 확률이 나오지는 않지만, 간격을 정하기 위해 경계선 근처의 데이터들만 고려하기 때문에 모델이 가볍고 노이즈에 강한 장점이 있다.
둘 이상의 항목을 분류하는 대표적인 방법으로는 이항 분류 SVM을 반복 적용하며 구분하는 방법과 데이터와 경계선 사이의 거리를 계산해서 데이터가 속하는 항목을 선택하는 방법이 있다.
5.2 토픽 모델링
문서에 존재하는 토픽을 추출하는 기법이다. 토픽은 문서의 주제를 뜻하는데, 문서 분석의 경우 어떤 단어가 특정하게 분포하는 것을 토픽이라고 한다. 예를 들어 스포츠에 대한 단어가 다른 단어보다 많이 나오면 그 문서의 토픽은 스포츠와 관련되었다고 볼 수 있고, 연예인에 대한 단어가 많이 나오면 연예인과 관련되었다고 볼 수 있다.
토픽 모델링은 문서가 토픽들로부터 생성된 단어로 이루어진다고 가정한다.
* 문서에는 여러 토픽이 각각의 비중을 가지고 존재한다.
* 토픽마다 단어의 분포가 달라진다.
* 문서를 작성할 때 토픽의 비중에 따라 토픽을 골라가면서 단어를 뽑는다.
문서가 토픽에 기반하여 생성된다고 가정하면 문서 내용을 단순히 단어가 아니라 토픽이라는 큰 의미 단위를 통해 파악할 수 있다. 예를 들어서 어떤 문서는 스포츠 토픽과 연예인 토픽을 7:3으로 섞었고, 또 다른 문서는 과학과 기술을 8:2로 섞었다고 판단할 수 있다. 그리고 일반적으로 토픽에 따라서 단어가 나오는 비율만 달라질 뿐 단어의 순서는 고려하지 않는다.
** LDA
LDA는 확률모델을 통해 문서의 토픽과 토픽에 분포하는 단어들을 분석한다. LDA는 잠재 디리클레 할당이라는 뜻인데, 문서 안의 토픽 하나하나가 디리클레 분포를 따르며, 문서를 그런 토픽에 할당한다는 의미에서 이렇게 부른다.
LDA에서는 하나하나의 문서가 다음 과정을 거쳐 생성된다고 가정한다.
1. 문서에 단어가 몇 개 있는지 결정한다.
2. 문서마다 토픽이 어떻게 분포되어 있는지, 토픽마다 단어 분포가 어떤지 디리클레 분포에 따라 정의한다.
3. 문서의 제일 첫 단어부터 끝 단어까지 다음 과정을 거친다.
a. 현재 위치의 단어가 어떤 토픽과 관계있는지 정한다.
b. a에서 정한 현재 위치의 토픽에 따라 단어의 분포를 결정하고 그중에서 가장 높은 확률의 단어를 선택한다.
간단히 요약하면, 문서가 어떤 토픽을 가질 확률, 각 위치의 단어가 어떤 토픽에 해당할지의 확률, 그 토픽에 따라 단어가 어떤 확률로 생성될지 정의해서 문서를 확률 모델로 설명한 것으로 볼 수 있다.
5.3 문법 분석
문서의 문법 구조를 분석해서 내용을 파악하는 기법이다. 문법을 분석해서 파악하기 때문에 단순히 단어 수만 세서 파악할 때보다 내용을 좀 더 정확하게 파악할 수 있다. 같은 단어를 사용하더라도 문법 구조에 따라 의미가 정반대가 되기도 하고, 대명사가 지칭하는 단어가 달라질 수 있기 때문이다.
1) 품사 태깅
주어진 문서에서 각 단어의 품사(주어, 목적어, 형용사 등)를 파악하는 것이다. 보통 문서 전체에서 품사를 한 번에 파악하기보다는 각 문장의 품사를 파악하는 것이 일반적이다.
The brown fox jumps over the lazy dog.
(주어 (명사구 The brown fox)
(동사 jumps
(전치사 over
(명사구 the lazy dog)))
현재 단어와 이전 단어에 따라 품사가 결정된다는 것을 알 수 있다. 품사 태깅에 순차 모델을 이용하면 문장의 첫 단어부터 마지막 단어까지 단어 하나하나가 입력으로 들어가고, 모델의 상태를 순차적으로 업데이트해가며 문장 구조를 분석한다.
** RNN

x는 문장의 각 단어들의 피처가 된다. 간단하게는 전체 단어집에서 몇 번째 단어에 해당하는지 생각할 수 있고, 복잡하게는 사전에서 이 단어에 어떠한 뜻이 있는지 혹은 어떤 품사들을 가질 수 있는지에 대한 정보를 담을 수 있다. 출력 y는 모델이 예측한 함수이다. h는 문장의 처음부터 단어를 하나씩 보면서 전에 어떤 단어들이 모델의 입력으로 들어왔는지 기억하는 부분이다. 즉, 각 단어를 하나씩 보면서 바로 직전의 상태(h_t-1)와 현재 단어(x_1)를 가지고 현재 상태(h_t)를 업데이트 한다.
순서가 없는 경우에는 입력 x와 출력 y의 한 쌍이 다른 입출력과 독립적이기 때문에 각각의 입출력에 대해 최적화를 했었는데, RNN의 경우에는 현재 단어와 지난 단어가 h를 통해 연결되기 때문에 한 문장 안의 단어들을 함께 연관되어 학습되어야 한다(문장끼리는 보통 독립적이라고 생각한다).
RNN은 문장이 길어져서 단어 간의 연관관계가 멀리 떨어져 있을 때 제대로 모델링하지 못하는 문제가 있다. 이론적으로는 내부에 존재하는 표현형(h)과 연관관계가 멀리 떨어져 있더라도 제대로 모델링할 수 있어야 한다. 하지만 '시간에 따라 거슬러 올라가며 계산하는 방법'으로는 멀리 떨어져 있는 단어의 정보가 제대로 전달되지 않는 문제가 있다. 이 문제를 소멸하는 1차 미분값이라고 부른다. 나열된 순서를 거슬러 올라가며 1차 미분값을 계산하다보면 그 값이 점점 작아져서 정보가 잘 전달되지 않는다. 그렇기 때문에 문장이 길어지면 연관관계를 잘 모델링하지 못해서 원하는 성능을 얻지 못하는 문제가 있게 된다.
이 문제를 해결하고자 등장한 것이 LSTM(Long Short-Term Memory)이다. 물론 LSTM 모델이 기본적인 RNN보다 훨씬 더 복잡하기 때문에 학습이 어려워서 항상 잘 동작하는 것은 아니지만 멀리 떨어진 연관관계를 모델링하는 데는 탁월한 성능을 보여준다.
** LSTM
RNN과 비슷하게 문장의 흐름에 따라 각 단어가 입력으로 들어가고 각각에 해당하는 출력이 있다. 하지만 RNN과 달리 상태를 저장하는 부분에 복잡한 박스가 있다. 이 박스는 입력과 현재까지의 상태를 이용해서 내부에 가지고 있던 정보를 업데이트할지 잊을지 판단한다. 문장을 앞에서부터 보다가 내용이 어느 정도 정리된 것 같다고 판단되면 지금까지의 상태 정보를 잊고 새로 입력된 정보를 좀 더 보관한다. 반대로 새로 입력된 단어가 별로 유용하지 않으면 지난 단계까지의 상태를 많이 기억하고 업데이트를 조금만 한다. 그리고 이 상태를 C(셀)라고 불리는 곳에 저장한다.
이러한 선택적인 업데이트와 기억 방식은 박스의 특별한 구조 때문인데, 자세한 동작 방식은 다음과 같다.
1. 맨 왼쪽 첫 번째 구조는 망각 게이트라 불리는데, 지금까지 기억했던 상태와 현재 입력에 파라미터를 곱해서 상태를 잊을지 말지 정한다.
2. 그다음 구조는 입력 게이트인데, 상태와 현재 입력을 가지고 얼마나 기억할지 정한다.
3. 그리고 그다음 상태를 앞에서 설명한 RNN과 비슷하게 추측한다.
4. 이렇게 3가지를 계산하고 나면 망각을 얼마나 하고(항목 1) 업데이트를 얼마나 할지(항목 2) 어떤 값을 업데이트할지(항목 3) 정해서 업데이트한다.
5. 실제 출력은 현재 상태(C_t)와 입력을 이용해서 결정한다.
LSTM 학습은 파라미터들이 어떻게 기억하는지, 출력을 어떻게 내는지에 대한 손실함수를 만들고(보통 교차 엔트로피를 많이 사용한다). 경사하강법을 응용한 방법으로 학습을 수행한다. 이걸 직접 구현하기는 복잡하므로 라이브러리에 주어진 기본 구현을 사용하면 된다.
2) 고유명사 추출(NER)
NER은 텍스트에서 인물, 조직, 장소, 일정 등을 찾아내는 문법 분석 방법이다. 책이나 웹 페이지에서 이름, 장소, 주소, 제품명을 인식하는데 사용할 수 있다.
NER은 POS 태깅 문제와 몇가지 비슷한 성질을 가진다. 첫 번째로 품사 문제 때처럼 사전 정보를 사용하면 많은 도움이 된다. 두 번째로 품사 문제를 풀 때와 마찬가지로 앞뒤에 나열된 단어에 따라 영향을 받는다.
** 순차 모델을 사용한 NER(RNN/LSTM)
NER도 머신러닝의 순차 모델을 많이 사용한다. 예를 들어 LSTM과 같은 순차 모델에 입력으로 NER 문제에 도움이 되는 장소사전이나 품사를 넣고, 출력값으로 NER 항목들을 주어서 학습하는 방법이다. NER 항목은 필요에 따라 여러 가지를 생각할 수 있지만 일반적으로 '장소, 일정, 인물, 해당 항목 없음' 이런 식으로 분류를 만들어 학습을 진행하면 된다.
** 머신러닝은 아니지만 NER에 사용되는 기법
NER은 POS 태깅 문제와 약간 다르게 큰 규모의 문서 분석에서도 종종 사용된다. 예를 들어 소셜 네트워크나 포털사이트에서 사용자가 신문 기사를 포스팅하면 기사에 나오는 장소나 인물에 자동으로 링크를 만들어주는 시스템을 생각할 수 있다.
예를 들어 \d\d\d-\d\d\d\d-\d\d\d\d와 같이 숫자 3개, 4개, 4개가 '-'로 연결되어 있다면 전화번호일 확률이 굉장히 높다. 그리고 XX월 XX일이라고 하면 시간에 해당하는 정보일 확률이 높다. 정규 표현식을 사용하면 순차 모델을 사용하는 것보다는 정확도나 발견 확률이 떨어지지만 빠르게 대규모 분석이 가능하다.
5.4 단어 임베딩 학습 - word2vec
컴퓨터로 단어의 의미를 나타내는 방법은 크게 이산표현discrete representation과 분산표현distributed representation이 있다.
쉽게 설명하자면 이상 표현은 그 단어 자체를 이용하여 의미를 나타내는 것이다. 이산표현에서 단어 하나의 의미는 말뭉치에 든 모든 단어 수를 벡터 크기로 하는 원-핫 인코딩 벡터로 표현한다. 이와 달리 분산 표현은 한 단어의 주변 단어를 이용해서 의미를 표현한다. 즉, 분산 표현에서는 주변 단어로 의미가 정해진다. 이러한 분산 표현은 사전에 정의되지 않은 새로운 단어도 표현할 수 있으므로, 더 많은 단어를 분석에 이용할 수 있다. 분산 표현을 이용하면 단어 하나는 실숫값으로 이루어진 벡터가 되는데, 이를 단어 임베딩이라고 한다.
word2vec는 단어 하나가 주어지면 그 단어와 주변 단어가 같이 일어날 확률을 구한다. word2vec의 목적함수로는 스킵-그램과 COW가 있다.
** 스킵-그램 : 단어 하나(x_t)를 받아서 그 주변에 같이 나타날 확률이 높은 단어들context을 구한다. 즉, p(context|x_t)를 구한다.
** COW(continuous bag of words) : 주변 단어들context를 받아서 그 단어들가ㅗ 같이 일어날 확률이 높은 단어(x_t)를 구한다. 즉, p(x_t|context)를 계산한다.
'Study > 처음 배우는 머신러닝' 카테고리의 다른 글
[ Part Ⅱ] Chapter 7. 이미지 인식 시스템 만들기 (0) | 2021.07.28 |
---|---|
[ Part Ⅱ] Chapter 6. 영화 추천 시스템 만들기 (0) | 2021.07.25 |
[ Part Ⅱ] Chapter 4. 구매 이력 데이터를 이용한 사용자 그룹 만들기 (0) | 2021.07.11 |
[ Part Ⅱ] Chapter 3. 데이터와 문제 (0) | 2021.07.08 |
[ Part Ⅰ] Chapter 2. 머신러닝의 주요 개념 (0) | 2021.07.06 |
- Total
- Today
- Yesterday
- 빌림
- 삼성청년소프트웨어아카데미
- 11051
- 딕셔너리
- 수학
- 브루트포스
- 백준
- 싸피
- 덱
- 1764
- 10816
- 10971
- 조합
- 자료구조
- heapq
- 2805
- 1358
- dp
- 러스트
- 1715
- 큐
- 프로그래머스
- 1759
- 백트래킹
- 파이썬
- 10815
- 17478
- 10845
- 1182
- 스택
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |