[Java] TF-IDF 개념과 자바로 구현

    TF-IDF는 자연어처리에서 가장 기본적이고 가장 많이 활용하는 기술이라 할 수 있으며 그만큼 강력하며 쉽다. TF-IDF는 Term-Frequency와 Inverse Document Frequency의 약어로 되어 있으며, 문서에서 자주 등장하는 문서별 중요 단어에서 다른 문서에서 자주 등장하는 패널티를 빼는 역빈도를 구하여 최종 스코어를 구하게 된다.

     

    이를 예로 들면, 편의점마다 많이 팔리는 물건을 조사하고 싶은데 단순히 매출로만 판단하게 되면 모든 편의점마다 담배가 1위로 올라설 것이다. 이렇게 다수가 나오는 패널티를 빼게 되면 결국 편의점마다 독특하게 등장하는 물건들이 있을 것이고, 이를 토대로 선호 물품과 해당 편의점 주변의 나이대 등을 간접적으로 알수도 있을 것이다.

     

    TF-IDF 개념과 자바로 구현

     

    TF-IDF로 가장 많이 활용되는 것은 아무래도 말뭉치(Corpus) 혹은 사전을 생성하는 것이다. 딥러닝을 돌리거나 나이브베이즈를 돌리거나 제일 먼저 Feature를 생성해야 하며, 이는 자연어처리에서 단어이다. 대다수의 문서에 등장하는 단어는 분류 등의 문제에 도움이 안되기에 제거를 해야 하는데 이때 가장 많이 활용하는 것으로 TF-IDF를 사용한다.

     

    예제 데이터

    List<String> list1 = Arrays.asList("딥러닝","케라스","TFIDF","인공지능");
    List<String> list2 = Arrays.asList("인공지능","컴퓨터공학","자연어처리","NLP");
    List<String> list3 = Arrays.asList("인공지능","컴퓨터공학","딥러닝","신경망");
    List<List<String>> lists = Arrays.asList(list1, list2, list3);

    데이터는 3개의 List형태로 만들었으며, 각각 단어들을 넣었다. 그리고 3개의 리스트를 다시 lists라는 List<List<String>> 타입의 변수에 저장하였다고 가정한다.

     

    TFIDF tfidf = new TFIDF();
    for(String word : list1) {
    	System.out.println(word + "->" + tfidf.tfIdf(list1, lists, word));
    }

    이 lists와 개별 list들을 이용하여 특정 단어의 TF-IDF를 구하고자 한다. 위 내용은 list1에서의 단어들을 호출하여 각각의 TF-IDF 스코어를 반환한다.

     

    TF(Term-Frequency)

    우선 문서별 단어의 중요도를 계산한다. 

    /**
     * Term-Frequency를 구한다.
     * @param doc
     * @param term
     * @return
    */
    public double tf(List<String> list, String word) {
    	double result = 0;
    	for (String targetWord : list)
    		if (word.equalsIgnoreCase(targetWord)) result++;        
    	return result / list.size();
    }

     

    IDF(Inverse Document Frequency)

    단어가 다른 문서에 얼만큼 등장하는 지를 계산하여 역빈도 값을 구한다

    /**
     * Inverse Document Frequency를 구한다.
     * @param lists
     * @param word
     * @return
    */
    public double idf(List<List<String>> lists, String word) {
    	double n = 0;
    	for (List<String> list : lists) {
    		for (String targetWord : list) {
    			if (word.equalsIgnoreCase(targetWord)) {
    				n++;
    				break;
    			}
    		}
    	}
    	return Math.log(lists.size() / n);
    }

     

    TF-IDF 

    TF와 IDF를 호출하여 최종 TF-IDF 값을 연산한다

    /**
     * TF-IDF를 연산한다
     * 
     * @param list
     * @param lists
     * @param word
     * @return
    */
    public double tfIdf(List<String> list, List<List<String>> lists, String word) {
    	return tf(list, word) * idf(lists, word);
    }

     

    예제 실행

    딥러닝->0.1013662770270411
    케라스->0.27465307216702745
    TFIDF->0.27465307216702745
    인공지능->0.0

     

    TF-IDF는 텍스트 분석에 다양하게 활용되다 보니 관련된 연구가 활발히 진행중이며 공식을 그대로 활용하기도 하고 다양하게 사이트에 맞추어 변형하여 사용하는 연구 역시 늘어나고 있다. 일단 TF-IDF에 대해서 자세히 써본적이 없다면 공식 그대로 사용하는 것이 좋겠지만 어느정도 적응이 되면 다양한 TF-IDF를 사용해보면서 커스터마이징한 사이트만의 TF-IDF 공식을 사용하는 것을 권하고 싶다.

     

     

     

    댓글

    Designed by JB FACTORY