JavaScript/자연어 처리

[node.js] JavaScript TF-IDF, 코사인 유사도 검사

BigmacGood 2022. 6. 26. 19:14

문서 유사도 검사를 위해 필요한 TF-IDF나 코사인 유사도 모듈을 찾아봤다.

https://www.npmjs.com/

위의 npm search 사이트에서 노드서버에서 사용할 모듈들을 찾아 봤지만 내가 원하는 입력에 원하는 출력을 해주는 모듈이 없었다. 그래서 간단한 자연어 처리 모듈을 직접 만들기로 했다.

 

형태소 분석기는 mecab-ya 라이브러리를 사용했다.

2022.06.25 - [JavaScript/자연어 처리] - [node.js] 형태소 분석기 mecab 사용하기

 

1. TF-IDF

아래 두 개의 사이트에서 TF-IDF에 관한 자세한 설명을 얻었다.

https://wikidocs.net/31698

http://bigdata.dongguk.ac.kr/lectures/TextMining/_book/%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%9E%90%EB%A3%8C%EC%9D%98-%ED%91%9C%ED%98%84-text-representation.html

 

위의 사이트에서 내가 사용할 것들을 간단하게 요약하자면

BOW(Bag of Words) : 단어의 순서에 상관없이 등장 횟수만을 고려한 표현 방법

단어사전 : BOW에서 등장한 단어들을 고유한 index와 맵핑시킨 것

TF(Term Frequency) : 한 문서에서 특정 단어가 등장한 횟수

DF(Document Frequency) : 특정 단어가 등장한 문서의 수

IDF(Inverse Document Frequency) : DF의 역수

TF-IDF : TF와 IDF의 스칼라곱, 단어의 가중치

 

2. 코사인 유사도

각 문서별로 TF-IDF 벡터를 구했다면 코사인 유사도 검사를 통해서 문서의 유사도를 확인할 수 있다.

https://wikidocs.net/24603

 

3. 예제

TF-IDF와 코사인 유사도 검사를 간단하게 구현해봤다. 자세한 코드는 아래 깃헙주소에 있다.

https://github.com/kangsunghyun111/simple-tf-idf

 

예제로 사용한 문장은 아래와 같다.

    const simpleTfidfTest = require('../simple-tf-idf-test');
    
    let document = [];
    document.push('정부가 발표하는 물가상승률과 소비자가 느끼는 물가상승률은 다르다.');
    document.push('소비자는 주로 소비하는 상품을 기준으로 물가상승률을 느낀다.');
    console.log(document);

    simpleTfidfTest.similarity_test(document);

 

위의 코드를 실행시키면 문서 토큰화 -> 단어사전 -> TF -> DF -> IDF -> TF-IDF -> 코사인 유사도 검사까지 과정을 출력해준다.

 

 

document를 tokenizer 함수에 넣으면, tokenizer 함수에서 mecab의 nounsSync를 실행한 결과를 반환해준다. document의 문장에서 명사만 추출된 모습을 확인할 수 있다.

    let tokenized_document = tokenizer(document);

 

 

토큰화된 문서를 build_bag_of_words에 넣으면 단어사전인 vocab과 각 문서의 bow벡터 배열인 bow를 반환해준다. 여기선 TF와 BOW가 같은 벡터를 나타낸다. 전체 문서에 대한 단어사전과 각 문서의 bow(TF)벡터가 만들어진 것을 확인할 수 있다.

    let result = build_bag_of_words(tokenized_document);
    let vocab = result[0];
    let bow = result[1];

 

 

각 문서의 bow벡터(TF)를 get_idf에 넣으면 DF벡터를 구한 후 IDF벡터를 반환해준다. IDF 공식은 1+ln((1+N)/(1+DF))를 사용했다.

    let idf = get_idf(bow);

 

 

각 문서의 bow벡터(TF)와 IDF벡터를 get_tfidf에 넣으면 TF-IDF벡터를 반환해준다. TF-IDF 벡터값은 각 문서에서 특정 단어의 가중치를 의미한다. 여러 문서에서 공통적으로 등장하는 단어의 경우 TF-IDF 값이 상대적으로 낮은 것을 확인할 수 있다.

    let tfidf = get_tfidf(bow, idf);

 

 

마지막으로 TF-IDF벡터를 코사인 유사도 함수에 넣으면 0번 문서와 다른 문서의 유사도가 나온다.

    let cos_sim = cosine_similarity(tfidf);

 

 

simple-tf-idf-test.js 코드는 문서의 유사도를 측정하는 과정을 살펴보기 위한 것이므로, 5개 이하의 짧은 문장을 document에 넣고 사용하면 된다.

 

참고한 사이트

https://wikidocs.net/31698

 

4) TF-IDF(Term Frequency-Inverse Document Frequency)

이번에는 DTM 내에 있는 각 단어에 대한 중요도를 계산할 수 있는 TF-IDF 가중치에 대해서 알아보겠습니다. TF-IDF를 사용하면, 기존의 DTM을 사용하는 것보다 보 ...

wikidocs.net

http://bigdata.dongguk.ac.kr/lectures/TextMining/_book/%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%9E%90%EB%A3%8C%EC%9D%98-%ED%91%9C%ED%98%84-text-representation.html

 

6 장 텍스트 자료의 표현 (Text representation) | 텍스트 자료 분석

벡터공간모형(Vector Space model): 문서의 단어들의 여부 (또는 빈도)를 단어집합(딕션너리) 크기 만큼의 벡터로 표현 \[ d_i = (w_{i1}, w_{i2}, ..., w_{iN}). \] 여기서, \(d_i \in D\)는 문서집합 \(D\)의 \(i\)번째

bigdata.dongguk.ac.kr

 

기록용입니다.