키워드 분석
핵심어(keyword)란 텍스트 자료의 중요한 내용을 압축적으로 제시하는 단어 또는 문구이다.
키워드 분석이란 불용어 제거와 어간 추출 및 형태소 분석 등의 자연어 처리를 시행한 후 텍스트에서 많이 등장하는 형태소의 등장 빈도를 분석함으로써 핵심어를 추출하는 것이다.
특정 텍스트 자료에 많이 나타나는 형태소가 그 텍스트 주제를 표출할 가능성이 높다는 가정에 기초한다.
빈도 분석에서 영어의 전치사나 한국어의 조사와 같이 의미를 별로 담고 있지 않은 불용어는 제외하는 것이 좋다.
키워드 분석은 텍스트의 주제 추정, 텍스트 유사도, 검색 엔진의 검색 결과 우선 순위 측정 등 다양하게 사용될 수 있다.
네이버 영화 리뷰 데이터
데이터를 확인해 보면 모두 바이트로 이루어져 있으며, 리뷰 외의 다른 데이터도 존재한다.
import urllib.request
raw = urllib.request.urlopen('https://raw.githubusercontent.com/e9t/nsmc/master/ratings.txt').readlines()
print(raw[:5])
-------------------------------------------
[b'id\tdocument\tlabel\n', b'8112052\t\xec\x96\xb4\xeb\xa6\xb4\xeb\x95\x8c\xeb\xb3\xb4\xea\xb3\xa0 \xec\xa7\x80\xea\xb8\x88\xeb\x8b\xa4\xec\x8b\x9c\xeb\xb4\x90\xeb\x8f\x84 \xec\x9e\xac\xeb\xb0\x8c\xec\x96\xb4\xec\x9a\x94\xe3\x85\x8b\xe3\x85\x8b\t1\n', b'8132799\t\xeb\x94\x94\xec\x9e\x90\xec\x9d\xb8\xec\x9d\x84 \xeb\xb0\xb0\xec\x9a\xb0\xeb\x8a\x94 \xed\x95\x99\xec\x83\x9d\xec\x9c\xbc\xeb\xa1\x9c, \xec\x99\xb8\xea\xb5\xad\xeb\x94\x94\xec\x9e\x90\xec\x9d\xb4\xeb\x84\x88\xec\x99\x80 \xea\xb7\xb8\xeb\x93\xa4\xec\x9d\xb4 \xec\x9d\xbc\xea\xb5\xb0 \xec\xa0\x84\xed\x86\xb5\xec\x9d\x84 \xed\x86\xb5\xed\x95\xb4 \xeb\xb0\x9c\xec\xa0\x84\xed\x95\xb4\xea\xb0\x80\xeb\x8a\x94 \xeb\xac\xb8\xed\x99\x94\xec\x82\xb0\xec\x97\x85\xec\x9d\xb4 \xeb\xb6\x80\xeb\x9f\xac\xec\x9b\xa0\xeb\x8a\x94\xeb\x8d\xb0. \xec\x82\xac\xec\x8b\xa4 \xec\x9a\xb0\xeb\xa6\xac\xeb\x82\x98\xeb\x9d\xbc\xec\x97\x90\xec\x84\x9c\xeb\x8f\x84 \xea\xb7\xb8 \xec\x96\xb4\xeb\xa0\xa4\xec\x9a\xb4\xec\x8b\x9c\xec\xa0\x88\xec\x97\x90 \xeb\x81\x9d\xea\xb9\x8c\xec\xa7\x80 \xec\x97\xb4\xec\xa0\x95\xec\x9d\x84 \xec\xa7\x80\xed\x82\xa8 \xeb\x85\xb8\xeb\x9d\xbc\xeb\x85\xb8 \xea\xb0\x99\xec\x9d\x80 \xec\xa0\x84\xed\x86\xb5\xec\x9d\xb4\xec\x9e\x88\xec\x96\xb4 \xec\xa0\x80\xec\x99\x80 \xea\xb0\x99\xec\x9d\x80 \xec\x82\xac\xeb\x9e\x8c\xeb\x93\xa4\xec\x9d\xb4 \xea\xbf\x88\xec\x9d\x84 \xea\xbe\xb8\xea\xb3\xa0 \xec\x9d\xb4\xeb\xa4\x84\xeb\x82\x98\xea\xb0\x88 \xec\x88\x98 \xec\x9e\x88\xeb\x8b\xa4\xeb\x8a\x94 \xea\xb2\x83\xec\x97\x90 \xea\xb0\x90\xec\x82\xac\xed\x95\xa9\xeb\x8b\x88\xeb\x8b\xa4.\t1\n', b'4655635\t\xed\x8f\xb4\xeb\xa6\xac\xec\x8a\xa4\xec\x8a\xa4\xed\x86\xa0\xeb\xa6\xac \xec\x8b\x9c\xeb\xa6\xac\xec\xa6\x88\xeb\x8a\x94 1\xeb\xb6\x80\xed\x84\xb0 \xeb\x89\xb4\xea\xb9\x8c\xec\xa7\x80 \xeb\xb2\x84\xeb\xa6\xb4\xea\xbb\x98 \xed\x95\x98\xeb\x82\x98\xeb\x8f\x84 \xec\x97\x86\xec\x9d\x8c.. \xec\xb5\x9c\xea\xb3\xa0.\t1\n', b'9251303\t\xec\x99\x80.. \xec\x97\xb0\xea\xb8\xb0\xea\xb0\x80 \xec\xa7\x84\xec\xa7\x9c \xea\xb0\x9c\xec\xa9\x94\xea\xb5\xac\xeb\x82\x98.. \xec\xa7\x80\xeb\xa3\xa8\xed\x95\xa0\xea\xb1\xb0\xeb\x9d\xbc\xea\xb3\xa0 \xec\x83\x9d\xea\xb0\x81\xed\x96\x88\xeb\x8a\x94\xeb\x8d\xb0 \xeb\xaa\xb0\xec\x9e\x85\xed\x95\xb4\xec\x84\x9c \xeb\xb4\xa4\xeb\x8b\xa4.. \xea\xb7\xb8\xeb\x9e\x98 \xec\x9d\xb4\xeb\x9f\xb0\xea\xb2\x8c \xec\xa7\x84\xec\xa7\x9c \xec\x98\x81\xed\x99\x94\xec\xa7\x80\t1\n']
raw = [x.decode() for x in raw[1:]]
reviews = []
for i in raw:
reviews.append(i.split('\t')[1]) # \t는 간격을 탭만큼 띄움.
print(reviews[:5])
------------------------------------------------------------
['어릴때보고 지금다시봐도 재밌어요ㅋㅋ', '디자인을 배우는 학생으로, 외국디자이너와 그들이 일군 전통을 통해 발전해가는 문화산업이 부러웠는데. 사실 우리나라에서도 그 어려운시절에 끝까지 열정을 지킨 노라노 같은 전통이있어 저와 같은 사람들이 꿈을 꾸고 이뤄나갈 수 있다는 것에 감사합니다.', '폴리스스토리 시리즈는 1부터 뉴까지 버릴께 하나도 없음.. 최고.', '와.. 연기가 진짜 개쩔구나.. 지루할거라고 생각했는데 몰입해서 봤다.. 그래 이런게 진짜 영화지', '안개 자욱한 밤하늘에 떠 있는 초승달 같은 영화.']
1. 형태소 분석을 이용한 명사 추출
형태소 분석기 MeCab으로 명사만 추출한다.
from konlpy.tag import Mecab
tagger = Mecab()
nouns = []
for review in reviews:
for noun in tagger.nouns(review):
nouns.append(noun)
nouns[:10]
------------------------------------
['때', '디자인', '학생', '외국', '디자이너', '그', '전통', '발전', '문화', '산업']
불용어 사전 만들기
한국어는 명사에서도 상당히 많은 불필요한 단어들이 포함된다.
ex) 전 난 일 걸 뭐 줄 만 건 분 개 끝 잼 이거 번 중 듯 때 게 내 말 나 수 거 점 것…
빈도가 너무 커서 분석에 방해되는 단어도 제거가 필요하다.
stop_words = '영화 전 난 일 걸 뭐 줄 만 건 분 개 끝 잼 이거 번 중 듯 때 게 내 말 나 수 거 점 것'
stop_words = stop_words.split(' ')
불용어를 제외하여 형태소 분석 수행
한글 텍스트에 대해서 형태소 분석을 수행한다.
분석으로 추출하는 명사 중에서 불용어에 포함되지 않는 텍스트만 추출하여 저장한다.
nouns = []
for review in reviews:
for noun in tagger.nouns(review):
if noun not in stop_words:
nouns.append(noun)
nouns[:10]
-----------------------------------
['디자인', '학생', '외국', '디자이너', '그', '전통', '발전', '문화', '산업', '우리']
2. 단어 빈도수 측정
단어 빈도수 측정에는 collections 라이브러리의 Counter 함수를 이용한다.
Counter를 이용하면 각 단어와 그의 빈도수를 딕셔너리로 편리하게 생성이 가능하다.
from collections import Counter
nouns_counter = Counter(nouns)
top_nouns = dict(nouns_counter.most_common(50))
top_nouns
{'연기': 9175,
'최고': 8813,
'평점': 8514,
'스토리': 7163,
'생각': 6943,
'드라마': 6896,
'사람': 6742,
'감동': 6489,
'배우': 5893,
'내용': 5731,
'감독': 5629,
'재미': 5479,
'시간': 5320,
'년': 4936,
'사랑': 4741,
'쓰레기': 4585,
'작품': 3985,
'하나': 3923,
'정도': 3656,
'이건': 3650,
'마지막': 3647,
'액션': 3568,
'기대': 3465,
'장면': 3262,
'이게': 3046,
'편': 3044,
'최악': 3019,
'돈': 2980,
'이야기': 2947,
'이해': 2745,
'애': 2730,
'명작': 2685,
'여자': 2678,
'이상': 2676,
'처음': 2673,
'한국': 2640,
'주인공': 2553,
'우리': 2531,
'연출': 2376,
'때문': 2371,
'기억': 2364,
'현실': 2193,
'마음': 2128,
'굿': 2110,
'남자': 2078,
'결말': 2066,
'인생': 2060,
'공포': 2048,
'전개': 2035,
'짜증': 2011}
3. 단어 빈도 시각화
막대 그래프
import numpy as np
y_pos = np.arange(len(top_nouns))
plt.figure(figsize = (10,10))
plt.barh(y_pos,top_nouns.values())
plt.title('Word Count')
plt.yticks(y_pos,top_nouns.keys())
plt.show()
단어 빈도 막대 그래프
WordCloud
텍스트에 담겨있는 여러 형태소들의 등장 빈도를 가장 직관적으로 시각화하는 방법이다.
텍스트에 등장하는 단어를 그 등장 빈도에 따라 서로 크기가 다르게 구름 형태로 표현함으로써, 단어의 빈도수를 한번에 알 수 있다.
빈도수만을 시각적으로 표현한 것이기 때문에, 단어들 사이의 연관성이나 의미 구조 등을 분석하는 데는 한계가 있다.
WordCloud를 이용해 객체를 생성한다.
generate_from_frequencies() 함수로 빈도수에 따라 워드클라우드를 생성한다.
from wordcloud import WordCloud
wc = WordCloud(background_color = 'white',font_path = './font/NanumBarunGothic.ttf')
wc.generate_from_frequencies(top_nouns)
워드클라우드를 시각화할 때는 imshow() 함수를 사용해야 한다.
figure = plt.figure(figsize = (12,12))
ax = figure.add_subplot(1,1,1)
ax.axis('off')
ax.imshow(wc)
plt.show()
단어 빈도 워드클라우드
Squarify 트리맵 시각화
Squarify 라이브러리를 이용해 키워드와 키워드 빈도수를 트리맵으로 나타낸다.
import squarify
norm = mpl.colors.Normalize(vmin = min(top_nouns.values()),
vmax = max(top_nouns.values()))
colors=[mpl.cm.Blues(norm(value)) for value in top_nouns.values()]
squarify.plot(label = top_nouns.keys(),
sizes = top_nouns.values(),
color = colors,
alpha = .7)
단어 빈도 트리맵