은공지능 공작소 :: [Python/Jupyter] 영화데이터로 워드클라우드 그리기 - 심화편- (html태그제거, stopwords 업데이트, 긍정/부정 워드클라우드 각각 그리기)

 

안녕하세요. 은공지능 공작소를 운영하는 파이찬입니다~!
오늘은 IMDb 리뷰 데이터로 워드 클라우드를 그리는 3번째 시간입니다.

1편에서는 전처리 작업을 진행했고,
2편에서는 기본적인 워드 클라우드를 그렸습니다.
(아래 포스팅 링크 참조해주세요)
 

[Python/Jupyter] 자연어처리를 위한 IMDB 데이터 전처리 과정 (데이터 다운로드부터 라벨링까지!)

안녕하세요! 은공지능 공작소의 파이찬입니다. 오늘은 파이썬으로 IMDB 영화데이터를 다운받고 전처리해보겠습니다. 전처리 작업은 자연어 처리를 위한 라벨링까지 진행합니다. https://www.imdb.com/ Ratings an..

chan-lab.tistory.com

 

[Python/Jupyter] IMDB 영화데이터로 워드클라우드 그리기 (기본편)

안녕하세요. 은공지능 공작소의 파이찬입니다. 오늘은 IMDb 영화리뷰 데이터로 워드클라우드를 그려보겠습니다. 데이터 전처리 과정은 아래 포스팅을 참조해주시길 바랍니다. [Python/Jupyter] 자연어처리를 위한..

chan-lab.tistory.com

 

 

 

 

 

오늘 진행할 부분은 위의 워드 클라우드에서 <br> 태그를 제거하는 것과,
불용어 사전 업데이트를 통해서 위에 보이는 일부 단어를 제거하는 것입니다.
또한 더 나아가서, 각각 긍정 단어와 부정 단어로만 이루어진 워드 클라우드도 그려보겠습니다.

 

 

 

 

 

 

 

 

 

 

 

 

1. html 태그 제거하기 (Beautiful Soup)

 

 

먼저 데이터를 살펴보겠습니다.
저희가 쓸 데이터는 지난 시간부터 쭉 사용해온 train_data입니다.
이 train_data는 txt, label이라는 2가지 컬럼이 있습니다.

txt 컬럼은 영화 리뷰가 텍스트로 담긴 컬럼이고요,
label 컬럼은 라벨(정답)이 달려있습니다.
각각 1은 긍정적인 리뷰, 0은 부정적인 리뷰를 나타냅니다.

 

 

 

 

 

from bs4 import BeautifulSoup

a = '<br>abcde</br>' # 이런 식으로 br 태그를 포함한 문자열입니다.
print(a)

a = BeautifulSoup(a, 'html5lib').get_text()
print(a)
output:
<br>abcde</br>
abcde
Beautiful Soup를 이용하여, html 태그를 제거하는 예시 코드입니다.
<br>이라고 된 부분이 html 코드입니다. 이는 웹디자인에서 줄을 바꿔주는 역할을 합니다.
하지만 워드클라우드 입장에서는 필요 없으니 제거를 해줘야 합니다.

위와 같이 Beautiful soup를 이용하여 한 번 필터링을 해주면
html 태그가 깔끔하게 제거가 됩니다.
output 부분을 보시면, <br>이라고 된 부분이 없어진 것을 확인할 수 있습니다.

지금 당장은 영화 데이터를 건들지 않겠습니다.
이렇게 Beautiful soup 함수에 대해 이해하시고 넘어가시면 됩니다.

 

 

 

 

 

 

 

2. Stopwords(불용어) 업데이트하기

 

 

 

import nltk

stopwords = nltk.corpus.stopwords.words('english') # 불용어 객체 선언
newStopWords = ['stopWord1','stopWord2'] # 추가하고 싶은 불용어 리스트
stopwords.extend(newStopWords) # 불용어 사전 업데이트
stopwords
output:
['i',
 'me',
 'my',
 ...
  "wouldn't",
 'stopWord1',
 'stopWord2']
위와 같은 방식으로 불용어 사전을 업데이트할 수 있습니다.
output을 보시면 마지막에 stopwords1, stopwords2가 업데이트된 것을
확인하실 수 있을 겁니다.

이렇게 stopwords를 업데이트해주는 것은
바로 wordcloud를 그려줄 때 옵션으로 적용할 수 있습니다.

이제 html 제거와 stopwords 업데이트를 모두 이해했으니,
이를 영화 데이터에 적용시켜 봅시다.

 

 

 

 

 

 

 

3. IMDb 데이터에서 html 태그 제거해주기

 

 

def data_engineering(input):
    from bs4 import BeautifulSoup
    
    rst = [] # rst는 result의 줄임말
    for i in input:
        # html 태그 제거
        data = BeautifulSoup(i, 'html5lib').get_text() # 필터 적용
        rst.append(data) # 결과를 rst리스트에 계속 추가
    
    return rst
    
train_data_html_out = data_engineering(train_data['txt'])
html 태그를 제거하는 함수를 하나 만들어 주고, 이름은 data_engineering으로 붙였습니다.
그리고 이 함수를 통해 train_data의 txt 컬럼을 정제하였습니다.
정제된 결과는 train_data_html_out에 담았고, 결과는 아래와 같습니다.

 

 

 

 

 

영화 리뷰 데이터에서 <br>과 같은 html 태그가 깔끔하게 사라진 모습입니다.

 

 

 

 

 

 

 

4. Stopwords(불용어) 업데이트해주기

 

 

 

위의 워드클라우드는 저번 시간에 그린 워드 클라우드입니다.
html 태그도 제거 안되어있고, 불용어 처리도 기본적인 것들로만 되어 있습니다.

여기서 제거해주고 싶은 단어를 3가지 정도 찾아보겠습니다.
큰 글자일수록, 해당 단어가 데이터에 자주 등장함을 의미합니다.

여기서는 'movie', 'film', 'one' 세 가지 단어를 제거해보겠습니다.
그러기 위해서는 위 3 단어로 불용어 사전을 업데이트해줘야 합니다.

 

 

 

 

 

stopwords_pychan = nltk.corpus.stopwords.words('english')
newStopWords = ['one', 'movie', 'film']
stopwords_pychan.extend(newStopWords)
위에서 보시는 것처럼 'one', 'movie', 'film'이라는 3 단어를 불용어에 추가한 후
이를 extend 함수를 통해 업데이트해주었습니다.
업데이트된 결과는 아래와 같습니다.

 

 

 

 

 

빨간 박스를 보면 3가지 불용어가 잘 추가된 것을 확인하실 수 있습니다.

 

 

 

 

 

 

 

5. 워드클라우드 그려보기

 

 

 

from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
%matplotlib inline

wordcloud = WordCloud(stopwords = stopwords_pychan,
                      background_color = 'black', #배경색
                      width = 800,
                      height = 600).generate(' '.join(train_data_html_out))

plt.figure(figsize = (15, 10)) # 각각 가로 세로 인치 입니다.
plt.axis("off") # 축에 표시되는 눈금을 제거하는 옵션
plt.imshow(wordcloud) # 이미지가 표시되도록 하는 옵션. 
plt.show() # 최종으로 보여주는 옵션. 
html이 제거된 데이터를 가지고 워드 클라우드를 그려보았습니다.
여기서 stopwords 옵션에 주목해주시길 바랍니다.

stopwords_pychan이라고 해준 것을 사용했습니다.
이는 위에서 저희가 'one', 'movie', 'film' 3가지 불용어를 추가해준 것입니다.
불용어 처리를 했기에 앞으로 그릴 워드클라우드에서는 해당 단어들이 보이면 안 되겠지요.

나머지 코드들은 지난 시간에 다 설명드린 내용이므로 넘어가겠습니다.
바로 결과를 확인해보시죠.

 

 

 

 

 

br 태그를 포함해서 film, movie, one이 사라진
워드클라우드가 나온 것을 확인하실 수 있습니다.

그런데 이런 것들을 제거해줬더니,
이번엔 show나 character 같은 엉뚱한 단어들이 수면위로 올라왔습니다.

이런 결과는 워드클라우드를 그린다 해도 별로 의미가 없을 것 같습니다.
제가 생각했을 때, 좀 의미가 있으려면 지역 명칭이 나온다던지, 영화배우 이름이 나온다던지
이런 고유명사가 나와준다면 워드클라우드가 의미가 있을 것 같은데,
이렇게 나오는 것은 좀 더 손을 많이 봐야 할 것 같습니다. 

그렇다면 긍정, 부정 단어들로만 워드 클라우드를 딱딱 그릴 수는 없을까 고민을 해보았습니다.
위에서 했던 것처럼 stopwords를 일일이 손으로 추가하다가는 엄청 시간이 많이 걸릴 것 같습니다.

이런 방법이 다른 모델에 적용이 될지도 의심스럽구요.
(여기서 제거된 단어가 다른 자연어 워드클라우드에서는 의미를 가질 수도 있으니까요.)

다행히도 방법이 있었습니다. 바로 긍정 단어, 부정 단어만 모아놓은 일종의 리스트를 적용시키는 것인데요.
구글링 결과 깃허브에 누가 이러한 단어들을 정리를 해두었습니다.
이제부터 그것을 적용시켜서 각각 긍정 워드클라우드, 부정 워드클라우드를 그려볼까 합니다.

 

 

 

 

 

 

 

6. 긍정, 부정 단어 리스트 적용하여 워드 클라우드 그리기

 

 

 

 

shekhargulati/sentiment-analysis-python

sentiment analysis step by step. Contribute to shekhargulati/sentiment-analysis-python development by creating an account on GitHub.

github.com

위의 깃허브에 긍정단어, 부정단어가 정리된 텍스트 파일이 있습니다.
프로필을 보니, 인도 프로그래머 Shekhar Gulati라는 분이네요 ㅎㅎ
(Thank you for your Git :)

 

 

 

 

 

사이트에 들어가시면 위와 같은 화면이 뜹니다.
초록 단추를 누른 후, 위와 같이 웹주소를 복사해 줍니다.

 

 

 

 

 

conda install git
이제 아나콘다 프롬프트를 실행시켜 줍니다.
그리고 git 라이브러리를 설치하지 않으신 분들은 위와 같이,
git 라이브러리를 설치하는 명령어를 날려줍니다.

 

 

 

 

 

git clone https://github.com/shekhargulati/sentiment-analysis-python.git
git clone이라고 치신 후, 아까 복사해 두었던 링크 주소를 붙여넣기 해줍니다.
그러면 해당 프로젝트가 다운로드가 될 것입니다.

 

 

 

 

 

빨간 박스로 된 경로를 확인해주시길 바랍니다.
각각의 txt 파일들을 열어보면 위와 같이 긍정단어, 부정단어들로 구성이 되어 있습니다.

하지만 바로 긍정단어, 부정단어가 나오지는 않습니다.
위에 35줄 정도의 데이터 설명이 함께 들어있기 때문에, 전처리가 조금 필요한 상황입니다.

 

 

 

 

 

import os
word_path = 'C:/Users/white/sentiment-analysis-python/opinion-lexicon-English/'
pos_word = open(os.path.join(word_path, 'positive-words.txt'), 'r').read()
위와 같이 txt 폴더 경로를 word_path에 담아주고,
os.path.join 함수를 이용해서 경로를 조인해 주었습니다.

이 os.path.join 함수는 파일 경로를 조인할 때 쓰는 함수입니다.
저런 식으로 경로를 쓰면, 해당 폴더의 하위 파일까지 경로가 합쳐져 출력됩니다.

 

 

 

 

 

pos_word를 출력한 결과입니다.
중간중간에 \n이라고 써진 것이 유난히 많이 보이는군요.
줄바꿈(엔터)로 구분된 txt 파일이라는 것을 알 수 있습니다.

 

 

 

 

 

negative 파일도 같은 방식으로 불러와 주려고 했는데... 에러가 나버렸습니다.
이는 코덱 에러로, 인코딩 형식이 달라서 생기는 에러입니다.

이럴 경우, 파일의 인코딩을 바꿔주고
open 함수에서 encoding 옵션을 명시하면 에러를 해결할 수 있습니다.

 

 

 

 

 

위의 그림처럼 negative-words.txt 파일을 열고,
다른 이름으로 저장을 클릭합니다.

 

 

 

 

 

다음으로 인코딩을 UTF-8로 바꿔주고, 저장을 클릭해줍니다.

 

 

 

 

 

neg_word = open(os.path.join(word_path, 'negative-words.txt'), 'r', encoding='UTF-8').read()
이제  negative-words.txt를 불러올 때, 위와 같이 인코딩을 명시해줍니다.
encoding='UTF-8'이라고 된 부분이 인코딩을 명시하는 부분입니다.

이런 방법으로 다양한 인코딩 문제들을 쉽게 해결할 수 있습니다.

 

 

 

 

 

negative words도 정상적으로 불러와졌습니다.
positive words 파일과 마찬가지로 \n으로 구분되어 있는 것을 알 수 있습니다.

 

 

 

 

 

pos_word = pos_word.split('\n')
pos_word = pos_word[35:]

neg_word = neg_word.split('\n')
neg_word = neg_word[35:]
위와 같은 방식으로 전처리를 조금 해줍니다.
각각 \n으로 구분자를 명시해서 쪼개 주고(split)
35번째 인덱스부터 다시 변수에 담아주는 방식입니다.

\n을 구분자로 쓴 이유는, 해당 txt 파일이 줄바꿈(엔터)로 구분되어 있기 때문입니다.
또한 35번째 index부터 긍정/부정 단어가 나오기 때문에,
인덱스를 [35:]로 설정해, [1:34]의 설명 부분을 제외시켰습니다.

 

 

 

 

 

def data_cleaning(input, pos):
    
    clean_word = [] # 리턴값을 담아줄 리스트 선언
    
    for i in input: # i에는 여러 문장들이 담김.
        for j in i.split(): # i를 단어별로 쪼개 j에 담음
            
            if pos: # pos가 True라면 실행
                if j in pos_word: # 단어를 하나씩 positive-word와 비교
                    clean_word.append(j)
                    
            else: # pos가 False라면 실행
                if j in neg_word: # 단어를 하나씩 negative-words와 비교
                    clean_word.append(j)
    return clean_word
이제 위와 같이 데이터에서 긍정, 부정단어들을 필터링 해주는 함수를 만들어줍니다.
input 변수로 리뷰 데이터를 받아서 return값으로 긍정/부정 단어가 담긴
리스트를 출력해주는 방식입니다.

자세한 설명은 코드 주석으로 대신하겠습니다 ^^;
참고로 제 유튜브 영상을 보시면 어떻게 생각하면서 함수를 짜는지
세세하게 설명이 되어있습니다.

 

 

 

 

 

clean_pos_data = data_cleaning(train_data_html_out, pos = True)
clean_neg_data = data_cleaning(train_data_html_out, pos = False)
이제 위에서 만든 함수를 이용하여, 데이터를 클렌징해줍니다.
각각 clean_pos_data와 clean_neg_data에는
긍정, 부정 단어의 알맹이들만 남아 있을 것입니다.

 

 

 

 

 

wordcloud = WordCloud(stopwords = stopwords, # 불용어
                      background_color='black', #배경색
                      width = 800, #가로
                      height = 600).generate(' '.join(clean_pos_data))

plt.figure(figsize = (15, 10)) # 가로, 세로
plt.axis('off') # 눈금을 제거해주는 옵션
plt.imshow(wordcloud) # 안 써주면 워드클라우드가 빈 화면으로 나옴
plt.show()
wordcloud = WordCloud(stopwords = stopwords, # 불용어
                      background_color='black', #배경색
                      width = 800, #가로
                      height = 600).generate(' '.join(clean_neg_data))

plt.figure(figsize = (15, 10)) # 가로, 세로
plt.axis('off') # 눈금을 제거해주는 옵션
plt.imshow(wordcloud) # 안 써주면 워드클라우드가 빈 화면으로 나옴
plt.show()
각각 긍정 워드클라우드, 부정 워드클라우드를 출력하는 코드입니다.

 

 

 

 

 

짜잔!

아름다운 워드클라우드가 완성이 됐습니다.
긍정워드 클라우드는 like, good, great 등의 단어가 많이 보입니다.
반면에 부정 워드클라우드는 bad, hard, worst 등의 단어들이 눈에 띕니다.

 

 

 

 

 

네 이렇게 해서 html 태그 제거, 불용어 업데이트,
마지막으로 긍정/부정 워드클라우드 그리는 법까지 모두 다루어보았습니다.

현재 포스팅 날짜 8월 14일... 무더운 날씨가 이어지고 있습니다.
모두 무더위에 건강 챙기시길 바랍니다. 긴 글 읽어주셔서 감사합니다.

 

반응형
블로그 이미지

pychan

딥러닝에 관련된 시행착오, 사소하지만 중요한 것들, 가능한 모든 여정을 담았습니다.

,