[자연어처리] 그래프와 워드클라우드
텍스트 분석이라고 하면 일반적으로 떠올리는 작업 중 하나가 바로 단어 빈도 기반 시각화이다.
머신러닝 기반의 복잡한 모델보다는 단순히 자주 등장하는 단어들을 시각적으로 보여주는 그래프나 워드 클라우드가 훨씬 더 직관적이게 느껴질 수 있다. 텍스트 분석의 가장 기본적인 아이디어는 특정 문서나 말뭉치에서 자주 사용된 단어를 파악하는 것이다.
예를 들어, 대통령의 연설문에 자주 등장하는 단어를 분석하면 어떤 주제에 집중하고 있는지를 유추할 수 있다.
왜 단어 빈도가 중요할까?
뉴스 기사를 예로 들어보자. “열섬 문제”라는 키워드가 유독 자주 등장했다면, 해당 시기의 주요 이슈가 기후 변화일 가능성이 크다.
이처럼 단어의 출현 빈도는 뉴스, 연설문, 보고서 등에서 핵심 주제를 빠르게 파악할 수 있는 중요한 힌트를 제공한다.
시각화 전 전처리
이전에 정리했던 전처리 방법을 통해 의미있는 단어들만 남길 수 있다.
- 토큰화 (Tokenization)
- 어간 추출 또는 표제어 추출 (Stemming, Lemmatization)
- 불용어 제거 (Stopwords removal)
실습을 통해 워드클라우드 알아보기
실습 데이터 : Project Gutenberg와 이상한 나라의 앨리스
실습에 사용할 데이터는 루이스 캐럴의 이상한 나라의 앨리스 (Alice's Adventures in Wonderland)이다.
이 책은 저작권이 만료되어 누구나 자유롭게 사용할 수 있으며, Project Gutenberg라는 사이트를 통해 영어 고전 문헌들을 다운로드할 수 있다.
NLTK는 해당 프로젝트의 일부 문서들을 gutenberg 모듈을 통해 기본 제공한다.
import nltk
nltk.download('gutenberg')
from nltk.corpus import gutenberg
file_names = gutenberg.fileids()
print(file_names)
실행 결과:
['austen-emma.txt', 'austen-persuasion.txt', 'austen-sense.txt',
'bible-kjv.txt', 'blake-poems.txt', 'bryant-stories.txt', 'burgess-busterbrown.txt',
'carroll-alice.txt', 'chesterton-ball.txt', 'chesterton-brown.txt', 'chesterton-thursday.txt',
'edgeworth-parents.txt', 'melville-moby_dick.txt', 'milton-paradise.txt', 'shakespeare-caesar.txt',
'shakespeare-hamlet.txt', 'shakespeare-macbeth.txt', 'whitman-leaves.txt']
carroll-alice.txt 파일이 우리가 분석에 사용할 텍스트이다.
텍스트 불러오기 및 토큰화
(1) 텍스트 로딩
파일을 열고 파일의 내용의 600자를 출력해보자.
doc_alice = gutenberg.open('carroll-alice.txt').read()
# 전체 문자 수
print('#Num of characters used:', len(doc_alice))
print('#Text sample:')
# 600자 출력
print(doc_alice[:600])
실행 결과:
#Num of characters used: 144395
#Text sample:
[Alice's Adventures in Wonderland by Lewis Carroll 1865]
CHAPTER I. Down the Rabbit-Hole
Alice was beginning to get very tired of sitting by her sister on the
bank, and of having nothing to do: once or twice she had peeped into the
book her sister was reading, but it had no pictures or conversations in
it, 'and what is the use of a book,' thought Alice 'without pictures or
conversation?'
So she was considering in her own mind (as well as she could, for the
hot day made her feel very sleepy and stupid), whether the pleasure
of making a daisy-chain would be worth the trouble of getting up and
(2) 단어 토큰화
토큰화 결과를 보면 괄호나 점(.) 같은 특수문자도 함께 포함된 것을 확인할 수 있다. 이후 단계에서 불용어 제거 및 품사 필터링을 통해 의미 있는 단어만 걸러내야 한다.
from nltk.tokenize import word_tokenize
import nltk
nltk.download('punkt_tab')
tokens_alice = word_tokenize(doc_alice)
print('#Num of tokens used:', len(tokens_alice))
print('#Token sample:')
# 20개 토큰 출력
print(tokens_alice[:20])
실행 결과:
#Num of tokens used: 33535
#Token sample:
['[', 'Alice', "'s", 'Adventures', 'in', 'Wonderland', 'by', 'Lewis', 'Carroll',
'1865', ']', 'CHAPTER', 'I', '.', 'Down', 'the', 'Rabbit-Hole', 'Alice', 'was', 'beginning']
불용어 제거 및 품사 기반 단어 선별
토큰화된 결과에는 분석에 필요 없는 불용어(stopwords)가 포함되어 있으므로 제거해준다.
(1) 불용어 제거
from nltk.corpus import stopwords
import nltk
nltk.download('stopwords')
english_stops = set(stopwords.words('english'))
# 불용어 제거
result_alice = [word for word in tokens_alice if word.lower() not in english_stops]
print('#Num of tokens after stopword elimination:', len(result_alice))
print('#Token sample:')
print(result_alice[:20])
실행 결과:
#Num of tokens after stopword elimination: 19814
#Token sample:
['[', 'Alice', "'s", 'Adventures', 'Wonderland', 'Lewis', 'Carroll', '1865', ']',
'CHAPTER', '.', 'Rabbit-Hole', 'Alice', 'beginning', 'get', 'tired', 'sitting', 'sister', 'bank', ',']
(2) 품사 기반 단어 추출
다음으로 품사 태깅을 통해 명사, 동사, 형용사 등 유의미한 단어만 선별해보자
from nltk import pos_tag
import nltk
nltk.download('averaged_perceptron_tagger_eng')
# 명사, 동사, 과거동사, 형용사
my_tag_set = ['NN', 'VB', 'VBD', 'JJ']
my_words = [word for word, tag in pos_tag(result_alice) if tag in my_tag_set]
print(my_words[:20])
실행 결과:
['[', 'Rabbit-Hole', 'get', 'tired', 'sister', 'bank', 'nothing', 'peeped', 'book',
'sister', 'reading', 'use', 'book', 'thought', 'conversation', 'mind', 'hot', 'day',
'made', 'feel']
(3) 단어별 빈도 계산
빈도수가 높은 단어 위주로 텍스트의 주요 내용을 추론할 수 있다.
alice_word_count = dict()
for word in my_words:
alice_word_count[word] = alice_word_count.get(word, 0) + 1
# 상위 20개 단어 출력
sorted_word_count = sorted(alice_word_count, key=alice_word_count.get, reverse=True)
print("#Num of used words:", len(alice_word_count))
print("#Top 20 high frequency words:")
for key in sorted_word_count[:20]:
print(f'{repr(key)}: {alice_word_count[key]}', end=' ')
실행 결과:
#Num of used words: 1677
#Top 20 high frequency words:
'said': 456 'little': 121 'went': 83 'time': 65 'thought': 61 'began': 58
'way': 53 'head': 49 'thing': 49 'voice': 46 'looked': 43 'know': 43 'get': 42
'see': 42 'came': 40 'go': 40 'great': 39 'got': 39 'round': 38 'tone': 38
단어 빈도 시각화 - 막대그래프 그리기
앞서 계산한 단어별 빈도 정보를 바탕으로, 상위 20개 단어를 막대그래프로 시각화해보자.
(1) 상위 단어 및 빈도 리스트 생성
import matplotlib.pyplot as plt
%matplotlib inline
# 상위 20개 단어
n = sorted_word_count[:20][::-1]
# 단어와 빈도를 리스트로 저장
w = [alice_word_count[key] for key in n]
tick_label = n
(2) 막대그래프 그리기
plt.barh(range(len(n)), w, tick_label=tick_label)
plt.title("Top 20 Frequent Words in Alice")
plt.xlabel("Frequency")
plt.ylabel("Words")
plt.show()
실행 결과:
- 가장 많이 등장한 단어는 "said", "little", "went" 등으로, ‘이상한 나라의 앨리스’에서 중요한 키워드임을 알 수 있다.
- 막대그래프는 단어 빈도를 직관적으로 보여줘, 텍스트의 주제나 핵심을 빠르게 파악하는 데 유용하다.
워드 클라우드 시각화
워드 클라우드란?
워드 클라우드(Word Cloud)는 단어의 출현 빈도를 바탕으로, 단어의 크기로 중요도(빈도)를 시각화 하는 방법이다.
단어가 많이 등장할수록 더 크게 표시되기 때문에, 한눈에 핵심 키워드를 파악할 수 있다.
(1) 워드 클라우드 설치
먼저 wordcloud 라이브러리가 설치되어 있어야 한다.
pip install wordcloud
(2) 워드 클라우드 생성
from wordcloud import WordCloud
# 워드 클라우드 생성
wordcloud = WordCloud(width=800, height=600, background_color='white')
wordcloud = wordcloud.generate_from_frequencies(alice_word_count)
(3) 워드 클라우드 출력
plt.figure(figsize=(15, 10))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.title("Word Cloud for Alice's Adventures in Wonderland")
plt.show()