중소기업 로봇청소기 후기 분류
크롤링사이트 다나와 로봇청소기 - 에브리봇
라이브러리
import pandas as pd
import numpy as np
폰트 설정
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
font_path = "C:/Windows/Fonts/NGULIM.TTF"
font = font_manager.FontProperties(fname=font_path).get_name()
rc('font', family=font)
%matplotlib inline
리뷰 크롤링¶
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
driver = webdriver.Chrome('chromedriver.exe')
driver.implicitly_wait(6)
url = "https://prod.danawa.com/info/?pcode=12058100&keyword=%EC%97%90%EB%B8%8C%EB%A6%AC%EB%B4%87&cate=103744#bookmark_cm_opinion"
driver.get(url)
# version_2 : 10페이지 출력후 다음버튼 누름,
from selenium.webdriver.common.by import By
import pandas as pd
import time
review_list = []
star_list = []
for page in range(1, 42):
reviews = driver.find_element(By.CLASS_NAME,'rvw_list')
titles = reviews.find_elements(By.CLASS_NAME, 'tit')
stars = reviews.find_elements(By.CLASS_NAME, 'star_mask')
print(page, titles[0].text)
for title, star in zip(titles, stars):
review_list.append(title.text)
star_list.append(star.text)
# print(star.text, '---', title.text)
#
# if page<10:
# driver.find_element(By.XPATH, f'//*[@id="danawa-prodBlog-companyReview-content-list"]/div/div/div/a[{page}]').click()
# time.sleep(3)
# else:# 다음 버튼 누르기
# driver.find_element(By.XPATH, f'//*[@id="danawa-prodBlog-companyReview-content-list"]/div/div/a').click()
if page % 10 == 0:
#페이지 10, 20번이면 다음버튼 클릭
driver.find_element(By.XPATH, f'//*[@id="danawa-prodBlog-companyReview-content-list"]/div/div/a').click()
time.sleep(5)
else:
# 페이지 10, 20 아닐때,
driver.find_element(By.XPATH, f'//*[@id="danawa-prodBlog-companyReview-content-list"]/div/div/div/a[{page%10}]').click()
time.sleep(5)
C:\Users\82105\AppData\Local\Temp\ipykernel_6816\170368705.py:4: DeprecationWarning: executable_path has been deprecated, please pass in a Service object
driver = webdriver.Chrome('chromedriver.exe')
1 추천합니다 강력히!!!
2 좋아요
3 좋아요
4 추천하지만 아쉬운 점
5 최고예요
6 최고예요
7 소음이 좀 있긴하지만 청소 잘함 앱을 쓰지 않아서인
8 최고예요
9 최고예요
10 좋아요
11 스마트한 청소기
12 최고예요
13 최고예요
14 에브리봇엣지 사용하면서 너무좋게잘쓰고있어서 이제품도추가
15 턱은 못 넘지만 청소 잘 되고 물걸레질도 잘 되니까 너
16 최고예요
17 구매해서 선물해 드렸어요너무 좋아하시네요빅스마일데이...
18 최고예요
19 최고예요
20 지금 맵 설정 중인데 상당히 오래걸려 충전하러중단해버리...
21 좋아요
22 추천합니다 강력히!!!
23 좋아요
24 추천하지만 아쉬운 점
25 최고예요
26 최고예요
27 소음이 좀 있긴하지만 청소 잘함 앱을 쓰지 않아서인
28 최고예요
29 최고예요
30 좋아요
31 스마트한 청소기
32 최고예요
33 최고예요
34 에브리봇엣지 사용하면서 너무좋게잘쓰고있어서 이제품도추가
35 턱은 못 넘지만 청소 잘 되고 물걸레질도 잘 되니까 너
36 최고예요
37 구매해서 선물해 드렸어요너무 좋아하시네요빅스마일데이...
38 최고예요
39 최고예요
40 지금 맵 설정 중인데 상당히 오래걸려 충전하러중단해버리...
41 좋아요
데이터 프레임 형식 저장¶
review_df = pd.DataFrame(zip(review_list, star_list), columns=['title','star'])
review_df
title | star | |
---|---|---|
0 | 추천합니다 강력히!!! | 80점 |
1 | 최고예요 | 100점 |
2 | 반품했습니다. 제품은 집 구조가 원룸이거나 단순하지 않... | 20점 |
3 | 최고예요 | 100점 |
4 | 좋아요 | 80점 |
... | ... | ... |
405 | 좋아요 | 80점 |
406 | 최고예요 | 100점 |
407 | 우리집 효도쟁이 청소도 잘되고 물걸레도 완전 대만족 가... | 100점 |
408 | 만족스러워요 | 100점 |
409 | ㅎㅎ 꼭 사세요! 애가 참 똑똑해요~ 고집은 쎄서 했던 | 100점 |
410 rows × 2 columns
똑같은 리뷰 제거¶
# 중복 문장 제거 함수 drop_duplicates
review_df.drop_duplicates(subset='title', inplace=True)
별점기반 등급 나누기 "group"¶
# 3등급 나누기
review_df['star']=review_df['star'].str.strip('점') # 문장 중 '점' 인 단어 삭제
review_df['star'] = pd.to_numeric(review_df['star']) # to_numeric -> str를 숫자로 변경
def get_group(v):
if v < 60:
group = 3
elif v < 100:
group = 2
else:
group = 1
return group
review_df["group"] = review_df["star"].apply(lambda v: get_group(v))
review_df
title | star | group | |
---|---|---|---|
0 | 추천합니다 강력히!!! | 80 | 2 |
1 | 최고예요 | 100 | 1 |
2 | 반품했습니다. 제품은 집 구조가 원룸이거나 단순하지 않... | 20 | 3 |
4 | 좋아요 | 80 | 2 |
5 | 친정어머니께 보내드리고 제가 | 100 | 1 |
... | ... | ... | ... |
192 | 배송이 생각보다 빠르고 좋습니다.가격대비 좋은 상품 ... | 60 | 2 |
194 | 빠른배송 감사 합니다.저렴하게 잘 산것 같아요..수... | 100 | 1 |
196 | 정말 청소가 편해졌어요 | 100 | 1 |
197 | 에브리봇3i | 100 | 1 |
199 | 혼자 돌아다니면서 청소 잘하네요대만족입니다 | 100 | 1 |
101 rows × 3 columns
"label" 구분 위한 단어 뭉치 생성 (positive, negative)¶
from konlpy.tag import Hannanum
hunnanum = Hannanum()
positive = review_df[review_df['group']==1].title.tolist() # 그룹이 1인 행만 뽑기
positive1 = list(map(lambda title: hunnanum.nouns(title), positive)) # nouns : 명사 추출 morphs : 형태소 추출 pos : 품사 부착
positive1 = np.concatenate(positive1).tolist() # 명사인 단어만 추출
positive1
['최고',
'친정어머니',
'저',
'것',
'신세계',
'와우',
'판타스틱',
'사용',
'로봇청소기',
'물걸레',
'겸용',
'사용후',
'기대반',
'의심반',
'구매',
'완전',
'신',
'만족',
'도착',
'이틀',
'사용해봤어요~아직',
'맵핑',
'시간',
'사용중이',
'청소',
'시작',
'모습',
'신기',
'생각',
'잘쓰',
'34평아파트',
'걸레청소모드',
'배송',
'정확',
'배송',
'디자인',
'부모님',
'추천',
'생각',
'가동시간',
'짧.',
'은',
'느낌',
'만족',
'청소',
'에브리봇',
'엣지물걸레로봇청소',
'너무좋아서3ipop',
'가격대비',
'시대',
'소음',
'있긴하',
'청소',
'앱',
'않아',
'처음',
'지',
'완성',
'안되서5번넘',
'지도완성',
'통',
'먼지통',
'분리',
'3i',
'청소시간',
'반',
'방안',
'깨끗',
'에브리봇',
'3i,',
'엣지',
'처음',
'한곳',
'여러번',
'적응',
'시간',
'이모님',
'도움',
'있긴',
'빅스마일데',
'덕분',
'만족',
'우리집',
'효도쟁',
'청소',
'물걸레',
'완전',
'대만족',
'만족',
'ㅎㅎ',
'애',
'고집',
'스마트',
'청소기',
'가격',
'저렴하게구입했어요',
'소음',
'편',
'청소',
'것',
'가성비',
'처음',
'내손',
'걸레기능',
'적',
'신통방통',
'에브리봇,',
'좋아요맞벌이부부들',
'정말정말',
'에브리봇',
'구입',
'에브리봇엣지',
'사용',
'너무좋게잘쓰고있어서',
'이제품도추',
'가격',
'비교',
'쿠폰',
'저렴',
'구매',
'가격대비',
'일단',
'디자인이나색상',
'만족스럽네요받고',
'충전',
'도착',
'ㅎㅎ',
'먼지걱정',
'바닥',
'깔끔하네요에브리이모',
'감사',
'도착',
'턱',
'청소',
'물걸레질',
'너',
'물걸레청소',
'그닥',
'먼지청소',
'것',
'청소걱정',
'끝',
'로봇청소기',
'삶의질',
'만족해요청소잘해요',
'어머니',
'걸레질',
'깨끗',
'됩니딘',
'구매해서',
'선물해',
'드렸어요너무',
'좋아하시네요빅스마일데이',
'시끄럽긴하',
'청소잘',
'만족',
'동영상',
'업로드',
'쿠폰',
'사용해서',
'득템',
'우리집',
'로봇이모님',
'생각',
'소리',
'청소기수준',
'소음',
'듭니다ㆍ',
'살걸ㅠ',
'신세계',
'한번',
'사용',
'지',
'집',
'작동',
'좋다네요',
'청소',
'물걸레',
'걍그런데',
'청소',
'물걸레',
'청소기',
'물걸레겸용',
'청소도잘되',
'빠른배송',
'감사',
'저렴',
'것',
'수',
'청소',
'에브리봇3i',
'청소',
'잘하네요대만족']
from konlpy.tag import Hannanum
from konlpy.tag import Okt
import numpy as np
hunnanum = Hannanum()
t = Okt()
# list(map(lambda title: t.nouns(title), review_list))
han_noun_review = list(map(lambda title: hunnanum.nouns(title), review_list))
han_noun_review_1 = np.concatenate(han_noun_review).tolist()
워드 클라우드¶
f = open("words.txt", "at")
for code in range(len(han_noun_review_1)):
f.writelines(f'{han_noun_review_1[code]} \n')
from wordcloud import WordCloud
from konlpy.tag import Twitter
from collections import Counter
# open으로 txt파일을 열고 read()를 이용하여 읽는다.
text = open('words.txt').read()
twitter = Twitter()
# twitter함수를 통해 읽어들인 내용의 형태소를 분석한다.
sentences_tag = []
sentences_tag = twitter.pos(text)
noun_adj_list = []
# tag가 명사이거나 형용사인 단어들만 noun_adj_list에 넣어준다.
for word, tag in sentences_tag:
if tag in ['Noun' , 'Adjective']:
noun_adj_list.append(word)
# 가장 많이 나온 단어부터 40개를 저장한다.
counts = Counter(noun_adj_list)
tags = counts.most_common(40)
font='Light.ttf'
# WordCloud를 생성한다.
# 한글을 분석하기위해 font를 한글로 지정해주어야 된다. macOS는 .otf , window는 .ttf 파일의 위치를
# 지정해준다. (ex. '/Font/GodoM.otf')
wc = WordCloud(font_path=font,background_color="white", max_font_size=60)
cloud = wc.generate_from_frequencies(dict(tags))
# 생성된 WordCloud를 test.jpg로 보낸다.
cloud.to_file('test.jpg')
<wordcloud.wordcloud.WordCloud at 0x275c2f440d0>
with open('positive.txt','w',encoding='UTF-8') as f:
for po in positive1:
f.write(po+'\n')
negative = review_df[review_df['group'] == 3].title.tolist()
negative1 = list(map(lambda title: hunnanum.nouns(title), negative))
negative1 = np.concatenate(negative1).tolist()
negative1
['반품',
'제품',
'집',
'구조',
'원룸',
'단순',
'않.',
'최악',
'별',
'모서리만돌면서청소하고거실가운데는하지도못함쇼파밑에서']
with open('negative.txt','w',encoding='UTF-8') as f:
for po in negative1:
f.write(po+'\n')
긍정, 부정 단어 직접 수정 후, 불러오기
with open("./negative.txt", encoding='utf-8') as neg:
negative = neg.readlines()
negative = [neg.replace("\n", "") for neg in negative]
with open("./positive.txt", encoding='utf-8') as pos:
positive = pos.readlines()
negative = [neg.replace("\n", "") for neg in negative]
positive = [pos.replace("\n", "") for pos in positive]
라벨붙이기¶
from tqdm import tqdm
import re
labels = []
title_data = list(review_df['title'])
for title in tqdm(title_data):
clean_title = re.sub('[-=+,#/\?:^$.@*\"※~&%ㆍ!』\\‘|\(\)\[\]\<\>`\'…\"\“》]', '', title)
negative_flag = False
label = 0
for i in range(len(negative)):
if negative[i] in clean_title:
label = -1
negative_flag = True
print("negative 비교단어 : ", negative[i], "clean_title : ", clean_title)
break
if negative_flag == False:
for i in range(len(positive)):
if positive[i] in clean_title:
label = 1
print("positive 비교단어 : ", positive[i], "clean_title : ", clean_title)
break
labels.append(label)
review_df['label'] = labels
100%|██████████████████████████████████████████████████████████████████████████████| 101/101 [00:00<00:00, 3283.99it/s]
positive 비교단어 : 추천 clean_title : 추천합니다 강력히
positive 비교단어 : 최고 clean_title : 최고예요
negative 비교단어 : 반품 clean_title : 반품했습니다 제품은 집 구조가 원룸이거나 단순하지 않
positive 비교단어 : 친정어머니 clean_title : 친정어머니께 보내드리고 제가
positive 비교단어 : 것 clean_title : 좋은것 같아요
positive 비교단어 : 것 clean_title : 청소영역을 스캔해서 빠짐없이 청소하는 것은 맘에 드네요
positive 비교단어 : 사용 clean_title : 흡입력은 만족 걸레는 아직 사용을 안해봐서 주방매
positive 비교단어 : 신세계 clean_title : 신세계를 맛보고 있습니다
positive 비교단어 : 와우 clean_title : 와우 판타스틱
negative 비교단어 : 최악 clean_title : 최악이에요
positive 비교단어 : 사용 clean_title : 잘 사용하고 있습니다
positive 비교단어 : 로봇청소기 clean_title : 로봇청소기 물걸레 겸용
positive 비교단어 : 사용 clean_title : 사용후기를 보고 기대반 의심반으로 구매했는데 완전 신
positive 비교단어 : 만족 clean_title : 만족합니다
positive 비교단어 : 추천 clean_title : 추천하지만 아쉬운 점
positive 비교단어 : 사용 clean_title : 도착하고 이틀 사용해봤어요아직 맵핑중이라 시간이 좀
positive 비교단어 : 사용 clean_title : 지금 사용중이에요
positive 비교단어 : 신 clean_title : 청소를 시작합니다 하면서 혼자 돌아다니는 모습이 신기해
negative 비교단어 : 별 clean_title : 별로예요
positive 비교단어 : 청소 clean_title : 생각보다 잘쓰고 있습니다 34평아파트 걸레청소모드로
positive 비교단어 : 작동 clean_title : 작동이 안되요
positive 비교단어 : 편 clean_title : 편한건 좋으나 제가 직접할 때보단 오래 걸려요했던데
positive 비교단어 : 배송 clean_title : 배송은 아주 빠르고 정확하게 배송되었습니다디자인이
positive 비교단어 : 부모님 clean_title : 부모님 사다드렸는데 정말 좋아하시네요 쫓아다니시면서
positive 비교단어 : 통 clean_title : 보통이에요
positive 비교단어 : 물걸레 clean_title : 물걸레만 구매하려다가 공용으로 구매했는데 걸레가 얇고
positive 비교단어 : 추천 clean_title : 추천합니다
positive 비교단어 : 만족 clean_title : 생각보다 가동시간이 좀 짧은 느낌이지만 만족하고요
positive 비교단어 : 청소 clean_title : 정말 청소 잘하네요
positive 비교단어 : 로봇청소기 clean_title : 에브리봇 엣지물걸레로봇청소기 쓰다가 너무좋아서3ipop
positive 비교단어 : 가격대비 clean_title : 가격대비 정말 좋아요
positive 비교단어 : 시대 clean_title : 역시 시대가 좋네요
positive 비교단어 : 지 clean_title : 아직 넘어야 할산이 많네요어플 연동 오류가 있고 지도
positive 비교단어 : 청소 clean_title : 소음이 좀 있긴하지만 청소 잘함 앱을 쓰지 않아서인
positive 비교단어 : 처음 clean_title : 처음엔 지도 완성이 잘 안되서5번넘게 해서 지도완성
positive 비교단어 : 지 clean_title : 물통이랑 먼지통이랑 따로 분리되어 있어 3i po
positive 비교단어 : 청소 clean_title : 흡입청소는 잘하네요 옆에서 바람이 느껴져서 먼지가 흗
negative 비교단어 : 모서리만돌면서청소하고거실가운데는하지도못함쇼파밑에서 clean_title : 모서리만돌면서청소하고거실가운데는하지도못함쇼파밑에서
positive 비교단어 : 시간 clean_title : 청소시간이 반으로 줄었네요 자주 돌려주니 방안도 깨끗
positive 비교단어 : 청소 clean_title : 청소기
positive 비교단어 : 너 clean_title : 너무 좋아요
positive 비교단어 : 물걸레 clean_title : 물걸레 기능시 제자리 헛돌기를 합니다 일반 청소 기능
positive 비교단어 : 에브리봇 clean_title : 에브리봇 3i 엣지 쓰다가
positive 비교단어 : 소리 clean_title : 소리가 매우 시끄러워요
positive 비교단어 : 시간 clean_title : 처음에는 한곳만 여러번 닦아 적응하는데 시간이 걸렸는데
positive 비교단어 : 이모님 clean_title : 이모님의 도움을 많이 받고 있긴
positive 비교단어 : 빅스마일데 clean_title : 빅스마일데이 덕분에 너무 잘 샀어요
positive 비교단어 : 만족 clean_title : 만족
negative 비교단어 : 집 clean_title : 우리집 효도쟁이 청소도 잘되고 물걸레도 완전 대만족 가
positive 비교단어 : 만족 clean_title : 만족스러워요
negative 비교단어 : 집 clean_title : ㅎㅎ 꼭 사세요 애가 참 똑똑해요 고집은 쎄서 했던
positive 비교단어 : 청소 clean_title : 스마트한 청소기
positive 비교단어 : 가성비 clean_title : 가성비굿
positive 비교단어 : 저 clean_title : 가격 저렴하게구입했어요소음은 큰편인데 청소 잘되는것
positive 비교단어 : 가성비 clean_title : 가성비 좋네요
negative 비교단어 : 집 clean_title : 역시 좋네요 처음에 집지도 그리는데헤매지만 내손
positive 비교단어 : 걸레기능 clean_title : 잘 쓰고 있어요 걸레기능도 적
positive 비교단어 : 신 clean_title : 신통방통한 에브리봇 넘 맘에 들고 좋아요맞벌이부부들
positive 비교단어 : 정말정말 clean_title : 정말정말 좋아요
positive 비교단어 : 로봇청소기 clean_title : 로봇청소기
positive 비교단어 : 에브리봇 clean_title : 에브리봇 구입
positive 비교단어 : 시간 clean_title : 흡입력은마음에들고배터리시간이 짧아 중간에 충전찾아가는
negative 비교단어 : 제품 clean_title : 에브리봇엣지 사용하면서 너무좋게잘쓰고있어서 이제품도추가
positive 비교단어 : 저 clean_title : 가격 비교하다가 쿠폰으로 저렴하게 구매했어요 가격대비
positive 비교단어 : 만족 clean_title : 일단 디자인이나색상 만족스럽네요받고 충전중입니다
positive 비교단어 : 도착 clean_title : 빠르게 도착했어요 ㅎㅎ
positive 비교단어 : 지 clean_title : 먼지걱정이 없어졌네요 바닥이 깔끔하네요에브리이모 감사
positive 비교단어 : 도착 clean_title : 잘 도착했어요
positive 비교단어 : 물걸레 clean_title : 턱은 못 넘지만 청소 잘 되고 물걸레질도 잘 되니까 너
positive 비교단어 : 것 clean_title : 물걸레청소는 그닥인데 먼지청소는 잘되는것같아요
positive 비교단어 : 청소 clean_title : 청소걱정 끝이네요
positive 비교단어 : 로봇청소기 clean_title : 로봇청소기 들이니 삶의질이 다르네요 만족해요청소잘해요
positive 비교단어 : 깨끗 clean_title : 어머니가 너무너무 좋아하세요 걸레질 깨끗하게 됩니딘
positive 비교단어 : 구매 clean_title : 구매해서 선물해 드렸어요너무 좋아하시네요빅스마일데이
positive 비교단어 : 만족 clean_title : 조금 시끄럽긴하지만 청소잘하고 다니네요 만족합니다
positive 비교단어 : 동영상 clean_title : 동영상 업로드는 안되네요
positive 비교단어 : 만족 clean_title : 아주 똑똑하진 못하지만 만족해요 그래도 옛날보다는 많
negative 비교단어 : 집 clean_title : 좋아요 좋아 쿠폰까지 사용해서 득템 우리집 로봇이모님
positive 비교단어 : 청소 clean_title : 생각보다 소리가 큼 청소기수준의 소음
positive 비교단어 : 살걸ㅠ clean_title : 진즉 살걸ㅠ
positive 비교단어 : 신세계 clean_title : 신세계네요
negative 비교단어 : 집 clean_title : 아직은 한번밖에 사용하지 않아 좋은지 잘 모르겠지만 집
positive 비교단어 : 청소 clean_title : 잘 작동되고 좋다네요청소만 잘되면 좋아요
positive 비교단어 : 물걸레 clean_title : 물걸레는 걍그런데 청소는 잘 하네요
positive 비교단어 : 물걸레 clean_title : 물걸레 청소기
positive 비교단어 : 물걸레 clean_title : 물걸레겸용으로 청소도잘되고 좋아요
positive 비교단어 : 지 clean_title : 지금 맵 설정 중인데 상당히 오래걸려 충전하러중단해버리
positive 비교단어 : 생각 clean_title : 배송이 생각보다 빠르고 좋습니다가격대비 좋은 상품
positive 비교단어 : 저 clean_title : 빠른배송 감사 합니다저렴하게 잘 산것 같아요수
positive 비교단어 : 청소 clean_title : 정말 청소가 편해졌어요
positive 비교단어 : 에브리봇 clean_title : 에브리봇3i
positive 비교단어 : 만족 clean_title : 혼자 돌아다니면서 청소 잘하네요대만족입니다
생성된 라벨 빈도 분석¶
import matplotlib.pyplot as plt
review_df['group'].value_counts().plot(kind='bar')
plt.title('그룹화한거')
plt.show()
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 44536 (\N{HANGUL SYLLABLE GEU}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 47353 (\N{HANGUL SYLLABLE RUB}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 54868 (\N{HANGUL SYLLABLE HWA}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 54620 (\N{HANGUL SYLLABLE HAN}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 44144 (\N{HANGUL SYLLABLE GEO}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
review_df['label'].value_counts().plot(kind='bar')
plt.title('라벨붙인거')
plt.show()
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 46972 (\N{HANGUL SYLLABLE RA}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 48296 (\N{HANGUL SYLLABLE BEL}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 48537 (\N{HANGUL SYLLABLE BUT}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 51064 (\N{HANGUL SYLLABLE IN}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
C:\Users\82105\anaconda3\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 44144 (\N{HANGUL SYLLABLE GEO}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
Train set: 무에서 유로 가기 위해 요구되는 필수 데이터
80%는 학습량으로!
우선 앞선 Lending Club, Pitney Bowes 게시글에도 나와있듯 데이터는 Train set 과 Test set으로 쪼개져 모델링에 활용됩니다. 여기서 둘의 비율은 일반적으로 train:test = 80: 20 으로 할당됩니다. 학습량의 비중이 월등히 높죠. 원래 시험을 앞두고 긴 시간동안 여러 교재를 아우르며 준비하지만, 시험은 짧은 시간 내 몇 페이지로 보는 경우가 비일비재하잖아요?
train test¶
from sklearn.model_selection import train_test_split
data = review_df['title']
target = review_df['label']
# train_test_split
x_train, x_test, label_train, label_test = train_test_split(data, target, test_size=0.2, shuffle=True, stratify=target, random_state=34)
x_train
194 빠른배송 감사 합니다.저렴하게 잘 산것 같아요..수...
4 좋아요
138 좋아요~
89 만족
81 소리가 매우 시끄러워요
...
62 처음엔 지도 완성이 잘 안되서5번넘게 해서 지도완성...
175 아직은 한번밖에 사용하지 않아 좋은지 잘 모르겠지만 집...
171 신세계네요
169 진즉 살걸ㅠ
48 물걸레만 구매하려다가 공용으로 구매했는데, 걸레가 얇고...
Name: title, Length: 80, dtype: object
title 전처리 토큰화¶
stopwords = ['의', '가', '이', '은', '들', '는', '좀', '잘', '걍', '과', '도', '를', '으로', '자', '에', '와', '한', '하다']
import konlpy
from konlpy.tag import Okt
okt = Okt()
X_train = []
for sentence in x_train:
temp_X = []
temp_X = okt.morphs(sentence, stem=True) # 토큰화
temp_X = [word for word in temp_X if not word in stopwords] # 불용어 제거
X_train.append(temp_X)
X_test = []
for sentence in x_test:
temp_X = []
temp_X = okt.morphs(sentence, stem=True) # 토큰화
temp_X = [word for word in temp_X if not word in stopwords] # 불용어 제거
X_test.append(temp_X)
from keras.preprocessing.text import Tokenizer
max_words = 35000
tokenizer = Tokenizer(num_words = max_words)
tokenizer.fit_on_texts(X_train)
X_train = tokenizer.texts_to_sequences(X_train)
X_test = tokenizer.texts_to_sequences(X_test)
#출처: https://somjang.tistory.com/entry/Keras기사-제목을-가지고-긍정-부정-중립-분류하는-모델-만들어보기 [솜씨좋은장씨:티스토리]
import numpy as np
y_train = []
y_test = []
for i in range(len(label_train)):
if label_train.iloc[i] == 1:
y_train.append([0, 0, 1])
elif label_train.iloc[i] == 0:
y_train.append([0, 1, 0])
elif label_train.iloc[i] == -1:
y_train.append([1, 0, 0])
for i in range(len(label_test)):
if label_test.iloc[i] == 1:
y_test.append([0, 0, 1])
elif label_test.iloc[i] == 0:
y_test.append([0, 1, 0])
elif label_test.iloc[i] == -1:
y_test.append([1, 0, 0])
y_train = np.array(y_train)
y_test = np.array(y_test)
pad_sequences¶
from keras.layers import Embedding, Dense, LSTM
from keras.models import Sequential
from keras_preprocessing.sequence import pad_sequences
max_len = 13 # 전체 데이터의 길이를 13로 맞춘다
X_train = pad_sequences(X_train, maxlen=max_len)
X_test = pad_sequences(X_test, maxlen=max_len)
validation_split=0.2 를 지정하기 위한 비율 계산¶
model = Sequential()
model.add(Embedding(max_words, 100))
model.add(LSTM(128))
model.add(Dense(3, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
history = model.fit(X_train, y_train, epochs=10, batch_size=10, validation_split=0.2)
print("\n Accuracy: %.4f" % (model.evaluate(X_train, y_train)[1]))
Epoch 1/10
7/7 [==============================] - 3s 107ms/step - loss: 0.8868 - accuracy: 0.7031 - val_loss: 0.6818 - val_accuracy: 0.8125
Epoch 2/10
7/7 [==============================] - 0s 19ms/step - loss: 0.6898 - accuracy: 0.8125 - val_loss: 0.7959 - val_accuracy: 0.8125
Epoch 3/10
7/7 [==============================] - 0s 19ms/step - loss: 0.6429 - accuracy: 0.8125 - val_loss: 0.6111 - val_accuracy: 0.8125
Epoch 4/10
7/7 [==============================] - 0s 20ms/step - loss: 0.5939 - accuracy: 0.8125 - val_loss: 0.6284 - val_accuracy: 0.8125
Epoch 5/10
7/7 [==============================] - 0s 20ms/step - loss: 0.5052 - accuracy: 0.8125 - val_loss: 0.7745 - val_accuracy: 0.8125
Epoch 6/10
7/7 [==============================] - 0s 20ms/step - loss: 0.5987 - accuracy: 0.8125 - val_loss: 0.6813 - val_accuracy: 0.8125
Epoch 7/10
7/7 [==============================] - 0s 19ms/step - loss: 0.4364 - accuracy: 0.8125 - val_loss: 0.7038 - val_accuracy: 0.8125
Epoch 8/10
7/7 [==============================] - 0s 18ms/step - loss: 0.3939 - accuracy: 0.8438 - val_loss: 0.7599 - val_accuracy: 0.8125
Epoch 9/10
7/7 [==============================] - 0s 20ms/step - loss: 0.3654 - accuracy: 0.8594 - val_loss: 0.7518 - val_accuracy: 0.8125
Epoch 10/10
7/7 [==============================] - 0s 18ms/step - loss: 0.2979 - accuracy: 0.8750 - val_loss: 1.1034 - val_accuracy: 0.8125
3/3 [==============================] - 0s 5ms/step - loss: 0.5072 - accuracy: 0.8625
Accuracy: 0.8625
print('\n 테스트 정확도 : {:.2f}%'.format(model.evaluate(X_test,y_test)[1]*100))
1/1 [==============================] - 0s 25ms/step - loss: 0.8896 - accuracy: 0.8095
테스트 정확도 : 80.95%
워드클라우드¶
f = open("words.txt", "at")
for code in range(len(han_noun_review_1)):
f.writelines(f'{han_noun_review_1[code]} \n')
from wordcloud import WordCloud
from konlpy.tag import Twitter
from collections import Counter
# open으로 txt파일을 열고 read()를 이용하여 읽는다.
text = open('txt.txt').read()
twitter = Twitter()
# twitter함수를 통해 읽어들인 내용의 형태소를 분석한다.
sentences_tag = []
sentences_tag = twitter.pos(text)
noun_adj_list = []
# tag가 명사이거나 형용사인 단어들만 noun_adj_list에 넣어준다.
for word, tag in sentences_tag:
if tag in ['Noun' , 'Adjective']:
noun_adj_list.append(word)
# 가장 많이 나온 단어부터 40개를 저장한다.
counts = Counter(noun_adj_list)
tags = counts.most_common(40)
font='Light.ttf'
# WordCloud를 생성한다.
# 한글을 분석하기위해 font를 한글로 지정해주어야 된다. macOS는 .otf , window는 .ttf 파일의 위치를
# 지정해준다. (ex. '/Font/GodoM.otf')
wc = WordCloud(font_path=font,background_color="white", max_font_size=60)
cloud = wc.generate_from_frequencies(dict(tags))
# 생성된 WordCloud를 test.jpg로 보낸다.
cloud.to_file('test13.jpg')
C:\Users\82105\anaconda3\lib\site-packages\konlpy\tag\_okt.py:17: UserWarning: "Twitter" has changed to "Okt" since KoNLPy v0.4.5.
warn('"Twitter" has changed to "Okt" since KoNLPy v0.4.5.')
<wordcloud.wordcloud.WordCloud at 0x275c2ed3fd0>
프로젝트를 하면서 느낀 점¶
- 조원 정혜진
크롤링을 이해하는데 많은 시간이 필요했지만 이번 팀 프로젝트에서 필요한 데이터를 직접 수집하고
그것을 바탕으로 분석을 진행하니 지금까지 해왔던 프로젝트와는 다른 새로운 경험이였습니다.
분석을 진행하면서 생각처럼 진행되지 않는 부분들도 있었지만 팀원들과 끝까지 마무리하며 많은 것을 배웠습니다.
- 박가온
최종분석 결과를 나타내기 위한 시각화로 긍정/부정으로 분류된 리뷰들에 대한 워드클라우드 제작을 하지 못한 것이 아쉽습니다.
그렇지만 이 분석을 통해 동적 웹크롤링을 사용하면서 웹의 이해도가 높아졌습니다.
또한 형태소 분석기 konlpy를 사용해 보면서 여러 분석기의 비교 또한 할 수 있었고,
텍스트분석을 위한 전처리 과정도 수업보다 실전으로 실습하면서 더욱 이해도가 높아졌습니다.
row data의 질과 양 또한 딥러닝 분석에 중요한 작용을 하는 것 또한 체감할 수 있었던 분석이었습니다.
선생님의 걱정어린 설명과 지도 덕분에 분석을 마칠 수 있었습니다. 감사합니다.
- 심형준
프로젝트를 하면서 팀원들과 같이 협동하는 과정을 거쳐 좋은 경험이 되었습니다.
기존의 크롤링기법이 아닌 새로운 크롤링을 통해 다양한 기법을 배울 수 있었습니다.
배울 때는 이해가 되지 않던 것들이 실제 프로젝트를 통해 하면서 이해할 수 있었습니다.
분석을 하면서 다양한 시도를 통해 딥러닝과 더 가까워질수 있었던 시간이었던 같습니다.
자연어 처리가 어려웠으나 같이 문제를 찾을 수 있는 힘을 기를수 있어서 좋았습니다.