분석하고싶은코코

텍스트 마이닝 - Bag of words / TF-IDF 본문

데이터분석

텍스트 마이닝 - Bag of words / TF-IDF

코코로코코 2022. 12. 12. 14:47
반응형

 

 

개인 프로젝트를 진행하면서 텍스트 마이닝 할 일이 생겨서 공부하게 되었다.

 

단어의 등장 순서에 상관없이 빈도수에 집중한 표현 방식이다.

 

1. Bag of Words ? TF-IDF ?


1. Bag of Words란 단어들의 순서는 전혀 고려하지 않고, 단어들의 출현 빈도(frequency)에만 집중하는 텍스트 데이터의 수치화 표현 방법이다. Bag of Words를 직역하면 단어들의 가방이라는 의미이다. (여유 있는 가방에 물건을 넣고 다녔을때 넣었을 때 모양 그대로 유지되기 어렵다. 그런 의미에서 가방이라는 표현을 쓴 듯..?)

 

 

2. TF-IDF(Term Frequency - Inverse Document Frequency)란 정보 검색과 텍스트 마이닝에서 사용하는 가중치를 이야기한다. 문서군에서 특정 단어가 그 안에서 얼마나 중요한지를 나태내는지를 보여주는 통계적 수치이다.

 

두 가지를 파이썬에서 구현해보기 앞서 파이썬에서 한글을 다루는 패키지에 대해서 먼저 알아봐야했다.

 

2.KoNLPy(코앤엘파이) - 한국어 정보처리 패키지 


1) KoNLPy - 한국어 정보처리 패키지

 KoNLPy에서는 대한민국 헌법 말뭉치인 kolaw와 국회법안 말뭉치인 kobill을 제공한다. 각 말뭉치가 포함하는 파일의 이름은 fields 메서드로 알 수 있고 open 메서드로 해당 파일의 텍스트를 읽어들인다.

from konlpy.corpus import kolaw

kolaw.fileids()
c = kolaw.open('constitution.txt').read()
print(c[:40])
대한민국헌법

유구한 역사와 전통에 빛나는 우리 대한국민은 3·1운동으로

 

from konlpy.corpus import kobill
kobill.fileids()
d = kobill.open('1809890.txt').read()
print(d[:40])
지방공무원법 일부개정법률안

(정의화의원 대표발의 )

 의 안
 번 호

 

 

 

2) 형태소 패키지

KoNLPy는 다음과 같은 다양한 형태소 분석, 태깅 라이브러리를 파이썬에서 쉽게 사용할 수 있도록 모아놓았다.

 

이 클래스들은 다음과 같은 메서드를 공통적으로 제공한다.

  • nouns : 명사 추출
  • morphs : 형태소 추출
  • pos : 품사 부착

예시는 Okt(Open Korean Text)로 진행

from konlpy.tag import *

okt = Okt()
print(okt.nouns(c[:40]))
print(okt.morphs(c[:40]))

print(okt.pos(c[:40]))
#okt.tagset
['대한민국', '헌법', '유구', '역사', '전통', '우리', '국민', '운동']

['대한민국', '헌법', '\n\n', '유구', '한', '역사', '와', '전통', '에', '빛나는', '우리', '대', '한', '국민', '은', '3', '·', '1', '운동', '으로']

[('대한민국', 'Noun'), ('헌법', 'Noun'), 
('\n\n', 'Foreign'), ('유구', 'Noun'), 
('한', 'Josa'), ('역사', 'Noun'), 
('와', 'Josa'), ('전통', 'Noun'), 
('에', 'Josa'), ('빛나는', 'Verb'), 
('우리', 'Noun'), ('대', 'Modifier'),
('한', 'Modifier'), ('국민', 'Noun'), 
('은', 'Josa'), ('3', 'Number'), 
('·', 'Punctuation'), ('1', 'Number'), 
('운동', 'Noun'), ('으로', 'Josa')]

 + okt.tagset을 통해서 품사 목록 확인 가능.

 

 

 

4. 단어 분리 예제


Tripadvisor 여행사이트에서 "제주 호텔"로 검색해서 나온 리뷰들을 활용
(https://www.tripadvisor.co.kr)

%matplotlib inline

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

import warnings
warnings.filterwarnings('ignore')

df = pd.read_csv("https://raw.githubusercontent.com/yoonkt200/FastCampusDataset/master/tripadviser_review.csv")
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1001 entries, 0 to 1000
Data columns (total 2 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   rating  1001 non-null   int64 
 1   text    1001 non-null   object
dtypes: int64(1), object(1)
memory usage: 15.8+ KB

 

텍스트 확인

df['text'][0]
여행에 집중할수 있게 편안한 휴식을 제공하는 호텔이었습니다. 위치선정 또한 적당한 편이었고 청소나 청결상태도 좋았습니다.

 

텍스트에서 한글만 가져오기

 

import re

def apply_regular_expression(text):
    hangul = re.compile('[^ ㄱ-ㅣ 가-힣]')  # 한글 추출 규칙: 띄어 쓰기(1 개)를 포함한 한글
    result = hangul.sub('', text)  # 위에 설정한 "hangul"규칙을 "text"에 적용(.sub)시킴
    return result
print(apply_regular_expression(df['text'][0]))
여행에 집중할수 있게 편안한 휴식을 제공하는 호텔이었습니다 위치선정 또한 적당한 편이었고 청소나 청결상태도 좋았습니다

형태소 추출 - KoNLPy -> Okt 사용

from konlpy.tag import Okt
from collections import Counter

# 형태소 추출
okt = Okt()  # 명사 형태소 추출 함수
nouns = okt.nouns(apply_regular_expression(df['text'][0]))
nouns
['여행', '집중', '휴식', '제공', '호텔', '위치', '선정', '또한', '청소', '청결', '상태']

모든 리뷰를 하나의 텍스트로 합쳐 형태소 추출 후 상위 10개 항목 출력.

corpus = "".join(df['text'].tolist())
nouns = okt.nouns(apply_regular_expression(corpus))

counter = Counter(nouns)
counter.most_common(10)
[('호텔', 803),
 ('수', 498),
 ('것', 436),
 ('방', 330),
 ('위치', 328),
 ('우리', 327),
 ('곳', 320),
 ('공항', 307),
 ('직원', 267),
 ('매우', 264)]

 

'수', '것', '방', '곳'과 같은 한 글자 단어는 분석에 방해되는 요소들 같아 삭제 진행

available_counter = Counter({x: counter[x] for x in counter if len(x) > 1})
available_counter.most_common(10)
[('호텔', 803),
 ('위치', 328),
 ('우리', 327),
 ('공항', 307),
 ('직원', 267),
 ('매우', 264),
 ('가격', 245),
 ('객실', 244),
 ('시설', 215),
 ('제주', 192)]

 

단어 목록중 의미가 없는 단어들(불용어)를 제거 작업을 진행. 지금까지으 과정을 모두 합쳐 하나의 함수에서 작업을 진행.

# 불용어 사전 불러오기
stopwords = pd.read_csv("https://raw.githubusercontent.com/yoonkt200/FastCampusDataset/master/korean_stopwords.txt").values.tolist()

def text_cleaning(text):
    hangul = re.compile('[^ ㄱ-ㅣ 가-힣]')  # 정규 표현식 처리
    result = hangul.sub('', text)
    okt = Okt()  # 형태소 추출
    nouns = okt.nouns(result)
    nouns = [x for x in nouns if len(x) > 1]  # 한글자 키워드 제거
    nouns = [x for x in nouns if x not in stopwords]  # 불용어 제거
    return nouns

 

BoW만들기

CountVectorizer는 단어 집합에서 단어를 집계하여 BoW인코딩 백터를 생성해준다.

(참고 - https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html)

from sklearn.feature_extraction.text import CountVectorizer

vect = CountVectorizer(tokenizer = lambda x: text_cleaning(x))
bow_vect = vect.fit_transform(df['text'].tolist())
word_list = vect.get_feature_names()
count_list = bow_vect.toarray().sum(axis=0)

1. vect 변수는 (text_cleaning)을 모두 걸친 텍스트 모음을 CountVectorizer해주는 lambda 설정

2. vect에 모든 리뷰가 담긴 텍스트를 리스트 형태로 넘겨주면 lambda 실행됨

3. 토근 형태로 들어가 있기 때문에 딕셔너리 형태로 넣어주기 위해 word 키워드를 가져오고

4. 각 리뷰마다 단어가 카운트 되어 있는 것을 배열 형태로 나열한 후 열 기준으로 합쳐 빈도수를 구한다.

 

word_count_dict = dict(zip(word_list, count_list))
word_count_dict

zip을 통해 (단어 키워드 : 빈도수)로 정리된 단어 딕셔너리를 만들어준다.

'가가': 4,
 '가게': 8,
 '가격': 245,
 '가격표': 1,
 '가구': 8,
 '가급': 1,
 '가기': 20,
 '가까이': 20,
 '가끔': 5,
 '가능': 10,
 '가도': 7,
 .
 .
 .

 

 

TF-IDF 중요도 나타내기

from sklearn.feature_extraction.text import TfidfTransformer

tfidf_vectorizer = TfidfTransformer()
tf_idf_vect = tfidf_vectorizer.fit_transform(bow_vect)


# 첫 번째 리뷰에서의 단어 중요도(TF-IDF 값) -- 0이 아닌 것만 출력
print(tf_idf_vect[0])

첫번째 리뷰 단어의 중요도

  (0, 3588)	0.35673213299026796
  (0, 2927)	0.2582351368959594
  (0, 2925)	0.320251680858207
  (0, 2866)	0.48843555212083145
  (0, 2696)	0.23004450213863206
  (0, 2311)	0.15421663035331626
  (0, 1584)	0.48843555212083145
  (0, 1527)	0.2928089229786031
  (0, 790)	0.2528176728459411

 

 

텍스트 마이닝을 위한 기본적인 데이터 전처리 방법에 대해서 알아보았다. 이를 활용해서 별점이나 방문횟수 등 여러가지 요인들을 복학접으로 활용한다면 리뷰에 대한 긍/부정에 대한 판단하는 모델을 만들 수 있을 것 같다는 생각이든다. 다음에는 리뷰를 긍/부정에 대해서 평가하는 모델에 대해서 포스팅 할 계획이다.

반응형