이번에는 DTM내에 있는 각 단어에 대한 중요도를 계산할 수 있는 TF-IDF 가중치에 대해 알아본다.
TF-IDF를 사용하면, 기존의 DTM을 사용하는 것보다 보다 더 많은 정보를 고려하여 문서들을 비교할 수 있다.
1. TF-IDF (단어 빈도-역 문서 빈도, Term Frequency-Inverse Document Frequency)
TF-IDF(Term Frequency-Inverse Document Frequency)는 단어의 빈도와 역 문서 빈도(문서의 빈도에 특정 식을 취함)를 사용하여 DTM 내의 각 단어들마다 중요한 정도를 가중치로 주는 방법이다.
TF-IDF는 주로 문서의 유사도를 구하는 작업, 검색 시스템에서 검색 결과의 중요도를 정하는 작업, 문서 내에서 특정 단어의 중요도를 구하는 작업 등에 쓰일 수 있다.
TF-IDF는 TF와 IDF를 곱한 값을 의미한다. 이를 식으로 구현해 볼때, 문서=d, 단어=t, 문서의 총 개수=n 이라고 표현할 때 TF, DF, IDF는 각각 다음과 같이 정의할 수 있다.
2-1) tf(d,t) : 특정 문서 d에서의 특정 단어 t의 등장 횟수.
= 단어 빈도(문서, 단어)
TF는 앞에서 구현한 DTM의 예제에서 본것 처럼 DTM이 각 문서에서의 각 단어의 등장 빈도를 나타내는 값들이다.
2-2) df(t) : 특정 단어 t가 등장한 문서의 수.
= 문서 빈도(단어)
여기서는 오직 특정 단어 t가 등장한 문서의 수에만 관심을 가진다.
앞서 배운 DTM에서 바나나는 문서2와 문서3에서 등장했다. 이 경우, 바나나의 df는 2이다.
2-3) idf(d, t) : df(t)에 반비례하는 수.
= 역 문서 빈도(문서, 단어)
log와 분모에 1을 더해주는 식에 의아하실 수 있다. log를 사용하지 않았을 때, IDF를 DF의 역수로 사용한다면 총 문서의 수 n이 커질 수록, IDF의 값은 기하급수적으로 커지게 된다. 그렇기 때문에 log를 사용한다.
또한 log 안의 식에서 분모에 1을 더해주는 이유는 특정 단어가 전체 문서에서 등장하지 않을 경우에 분모가 0이 되는 상황을 방지하기 위함이다.
TF-IDF는 모든 문서에서 자주 등장하는 단어는 중요도가 낮다고 판단하며, 특정 문서에서만 자주 등장하는 단어는 중요도가 높다고 판단한다.
TF-IDF 값이 낮으면 중요도가 낮은 것이며, TF-IDF 값이 크면 중요도가 큰 것이다.
즉, the나 a와 같이 불용어의 경우에는 모든 문서에 자주 등장하기 마련이기 때문에 자연스럽게 불용어의 TF-IDF의 값은 다른 단어의 TF-IDF에 비해서 낮아지게 된다.
- | 과일이 | 길고 | 노란 | 먹고 | 바나나 | 사과 | 싶은 | 저는 | 좋아요 |
문서1 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 |
문서2 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 |
문서3 | 0 | 1 | 1 | 0 | 2 | 0 | 0 | 0 | 0 |
문서4 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
앞서 DTM을 설명하기위해 들었던 위의 예제를 가지고 TF-IDF에 대해 이해해보도록 하겠습니다. 우선 TF는 앞서 사용한 DTM을 그대로 사용하면, 그것이 각 문서에서의 각 단어의 TF가 된다.
그렇다면 이제 구해야할 것은 TF와 곱해야할 값인 IDF이다.
로그는 자연 로그를 사용하도록 한다.
여기서 로그는 마치 기존의 값에 곱하여 값의 크기를 조절하는 상수의 역할을 한다.
TF-IDF의 로그는 대부분 자연 로그를 사용한다.
자연 로그는 ln이라고 표현한다.
단어 | IDF(역 문서 빈도) |
과일이 | ln(4/(1+1)) = 0.693147 |
길고 | ln(4/(1+1)) = 0.693147 |
노란 | ln(4/(1+1)) = 0.693147 |
먹고 | ln(4/(2+1)) = 0.287682 |
바나나 | ln(4/(2+1)) = 0.287682 |
사과 | ln(4/(1+1)) = 0.693147 |
싶은 | ln(4/(2+1)) = 0.287682 |
저는 | ln(4/(1+1)) = 0.693147 |
좋아요 | ln(4/(1+1)) = 0.693147 |
문서의 총 수는 4이기 때문에 ln 안에서 분자는 늘 4으로 동일하다.
(문서는 아래에서 확인 할 수 있다.)
분모의 경우에는 각 단어가 등장한 문서의 수(DF)를 의미한다.
IDF는 여러 문서에서 등장한 단어의 가중치를 낮추는 역할을 하기 때문에 문서 1개에만 등장한 단어와 문서 2개에만 등장한 단어는 값의 차이를 보인다.
TF는 DTM을 그대로 가져오면 각 문서에서의 각 단어의 TF를 가져오게 되기 때문에, 앞서 사용한 DTM에서 단어 별로 위의 IDF값을 그대로 곱해주면 TF-IDF가 나오게 된다.
- | 과일이 | 길고 | 노란 | 먹고 | 바나나 | 사과 | 싶은 | 저는 | 좋아요 |
문서1 | 0 | 0 | 0 | 0.287682 | 0 | 0.693147 | 0.287682 | 0 | 0 |
문서2 | 0 | 0 | 0 | 0.287682 | 0.287682 | 0 | 0.287682 | 0 | 0 |
문서3 | 0 | 0.693147 | 0.693147 | 0 | 0.575364 | 0 | 0 | 0 | 0 |
문서4 | 0.693147 | 0 | 0 | 0 | 0 | 0 | 0 | 0.693147 | 0.693147 |
문서2에서의 바나나의 TF-IDF 가중치와 문서3에서의 바나나의 TF-IDF 가중치가 다른 것을 볼 수 있다.
수식적으로 말하면, TF가 각각 1과 2로 달랐기 때문인데 TF-IDF에서의 관점에서 보자면 TF-IDF는 특정 문서에서 자주 등장하는 단어는 그 문서 내에서 중요한 단어로 판단하기 때문이다. 문서2에서는 바나나를 한 번 언급했지만, 문서3에서는 바나나를 두 번 언급했기 때문에 문서3에서의 바나나를 더욱 중요한 단어라고 판단하는 것이다.
2. 사이킷런을 이용한 DTM과 TF-IDF 실습
실습을 통해 DTM과 TF-IDF를 직접 만들어본다.
DTM 또한 BoW 행렬이기 때문에, 앞서 BoW 챕터에서 배운 CountVectorizer를 사용하면 간단히 DTM을 만들 수 있다.
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'you know I want your love',
'I like you',
'what should I do ',
]
vector = CountVectorizer()
print(vector.fit_transform(corpus).toarray()) # 코퍼스로부터 각 단어의 빈도 수를 기록한다.
print(vector.vocabulary_) # 각 단어의 인덱스가 어떻게 부여되었는지를 보여준다.
[[0 1 0 1 0 1 0 1 1]
[0 0 1 0 0 0 0 1 0]
[1 0 0 0 1 0 1 0 0]]
{'you': 7, 'know': 1, 'want': 5, 'your': 8, 'love': 3, 'like': 2, 'what': 6, 'should': 4, 'do': 0}
DTM에서 각 단어의 인덱스가 어떻게 부여되었는지를 확인하기 위해, 인덱스를 확인해보았다.
사이킷런은 TF-IDF를 자동 계산해주는 TfidfVectorizer를 제공한다.
사이킷런의 TF-IDF는 위에서 배웠던 보편적인 TF-IDF 식에서 좀 더 조정된 다른 식을 사용하지만 크게 다르진 않다.
(IDF 계산시 분자에다가도 1을 더해주며, TF-IDF에 L2 정규화라는 방법으로 값을 조정하는 등의 차이)
from sklearn.feature_extraction.text import TfidfVectorizer
corpus = [
'you know I want your love',
'I like you',
'what should I do ',
]
tfidfv = TfidfVectorizer().fit(corpus)
print(tfidfv.transform(corpus).toarray())
print(tfidfv.vocabulary_)
[[0. 0.46735098 0. 0.46735098 0. 0.46735098 0. 0.35543247 0.46735098]
[0. 0. 0.79596054 0. 0. 0. 0. 0.60534851 0. ]
[0.57735027 0. 0. 0. 0.57735027 0. 0.57735027 0. 0. ]]
{'you': 7, 'know': 1, 'want': 5, 'your': 8, 'love': 3, 'like': 2, 'what': 6, 'should': 4, 'do': 0}
* 정리:
1. DTM 내에 있는 각 단어에 대한 중요도를 계산할 수 있는 TF-IDF 가중치를 알아 보았다.
2. TF-IDF는 단어의 빈도와 역 문서 빈도를 사용하여 DTM내의 각 단어들마다 중요한 정도를 가중치로 주는 방법이다.
3. TF, DF, IDF를 다음과 같이 정의 할 수 있다.
- tf(d,t) : 특정 문서 d에서의 특정 단어 t의 등장 횟수.
- df(t) : 특정 단어 t가 등장한 문서의 수.
- idf(d, t) : df(t)에 반비례하는 수.
4. IDF의 식중 log와 분모의 1을 더해주는 이유는 아래와 같다.
- log를 사용하지 않으면 문서의 수 n이 커질 수록 IDF의 값이 기하급수적으로 커지게 되므로.
- 분모에 1을 더해주는 이유는 특정 단어가 전체 문서에서 등장 하지 않을 경우 분모가 0이 되는 것을 방지하기 위해
5. CountVectorizer을 사용해 DTM을 만들수 있다.
6. TfidfVectorizer을 사용해 TF-IDF를 자동 계산해준다.
'Deep learning > NLP(자연어처리)' 카테고리의 다른 글
워드 임베딩(Word Embedding) (0) | 2020.03.08 |
---|---|
문서 유사도(Document Similarity) (0) | 2020.03.03 |
문서 단어 행렬(Document-Term Matrix, DTM) (0) | 2020.03.03 |
Bag of Words(BoW) (0) | 2020.03.03 |
카운트 기반의 단어 표현(Count based word Representation) (0) | 2020.03.02 |