2021. 2. 17. 19:13ㆍ교육과정/KOSMO
키워드 : 형태소분석 / 네이버 영화 감상평 문장 분석 / 지식인 문장 분석 및 워드클라우드 / 나이브베이즈 분류 / 영문 분류 / 한글 분류 / 스팸메일 판단
****
1. 형태로 분석
형태소 분석 (Morphological Analysis)¶
- 자연 언어의 문장을 "형태소"라는 의미의 최소 단위로 분할하고, 품사를 판별하는 작업
-
기계번역, 텍스트 마이닝에서 활용되는 중요한 작업
-
영어의 형태소 분석은 쉽다 "I want to eat a apple" 조사역할의 to, a를 거르면 I, eat, apple 단어 추출
-
한국어의 형태소 분석은 어렵다 "나는 사과를 먹고 싶다" 단어에 조사가 붙어 있어서 모든 품사와 문법 사전을 기반으로 대조하면서 단어를 추출해야 한다 단순하게 '는' '을'을 제거한다고 되는 것이 아니다. "소은 노을 이쁘다고 한다" 여기서 '은'과 '을'을 제거하면 안되고 '이쁜다고 한다'에서 '이쁘다' 어원도 추출해야 한다.
-
한국어 형태소 분석 라이브러리 중 KoNLPy 사용 http://konlpy.org/ko/latest
-
형태소 분석 라이브러리 : KoNLPy ( http://konlpy.org/ko/latest/ )
-
형태소 분석기 :Okt / 한나눔 / 꼬꼬마 / Kormoran / MeCab 등
*** KoNLPy 설치¶
-
http://konlpy.org/ko/latest/install/
왼쪽 메뉴에서 윈도우 선택하고 확인하면서 실행하는 방식 확인
-
https://www.lfd.uci.edu/~gohlke/pythonlibs/#jpype
(1) JPype 확인 - 컴퓨터 bit / 파이썬 버전 ( python --version ) 에 맞는 실행 파일 다운로드 (하단 사진 참고)
[주의] JPype1 설치할 때 ( 최신 버전 확인 )
JPype1‑0.7.1‑cp37‑cp37m‑win_amd64.whl ( 컴퓨터 64bit / cp37 : python 3.7 버전 )
-
(2) Anaconda Prompt 창이나 cmd 창
> pip install --upgrade pip > cd 다운받은폴더 > pip install JPype1-1.1.2-cp38-cp38-win_amd64.whl
(3) pip install konlpy
(4) jupyter notebook을 다시 재실행해야 한다
` Anaconda Prompt 에서도 실행가능
- 다운로드 파일

- 다운받은 파일 설치

[참고] 데이타 사이언스 스쿨 :
꼬꼬마¶
# KoNLPy의 kkma 형태소 분석기 확인
from konlpy.tag import Kkma
from konlpy.utils import pprint
kkma = Kkma()
# 문장분석
kkma.sentences('네 안녕하세요 오늘도 행복합시다')
['네 안녕하세요', '오늘도 행 복합 시다']
# 명사분석
kkma.nouns('한국어 분석을 시작합니다 재미있었어요?')
['한국어', '분석', '재미']
# 품사분석 : 한국어는 형태변화가 많아 영어처럼 쉽게 안됨
kkma.pos('한국어 분석을 시작합니다 재미있어')
[('한국어', 'NNG'),
('분석', 'NNG'),
('을', 'JKO'),
('시작하', 'VV'),
('ㅂ니다', 'EFN'),
('재미있', 'VA'),
('어', 'ECD')]
한나눔 엔진¶
from konlpy.tag import Hannanum
hannanum = Hannanum()
# 명사분석 : 꼬꼬마 엔진과 다른 결과
hannanum.nouns('한국어 분석을 시작합니다 재미있었을까')
['한국어', '분석', '시작']
# 형태소분석
hannanum.morphs('한국어 분석을 시작합니다 재미있었을까')
['한국어', '분석', '을', '시작', '하', 'ㅂ니다', '재미있', '었을까']
# 품사분석
hannanum.pos('한국어 분석을 시작합니다 재미있었을까')
[('한국어', 'N'),
('분석', 'N'),
('을', 'J'),
('시작', 'N'),
('하', 'X'),
('ㅂ니다', 'E'),
('재미있', 'P'),
('었을까', 'E')]
Okt 엔진 ( 예전의 Twitter 엔진)¶
from konlpy.tag import Okt
okt = Okt()
# 명사분석
okt.nouns('한국어 분석을 시작합니다 재미있었을까')
['한국어', '분석', '시작']
# 형태소분석
okt.morphs('한국어 분석을 시작합니다 재미있었을까')
['한국어', '분석', '을', '시작', '합니다', '재미있었을까']
# 품사분석
okt.pos('한국어 분석을 시작합니다 재미있었을까')
[('한국어', 'Noun'),
('분석', 'Noun'),
('을', 'Josa'),
('시작', 'Noun'),
('합니다', 'Verb'),
('재미있었을까', 'Adjective')]
KoNLPy 형태소 분석기 중에서 '나는사과를좋아한다' 문장을 분석할 수 있는 분석기는 많지 않지만 계속 발전하고 있는 중이다 관련 사항 확인 http://konlpy.org/ko/latest/api/konlpy.tag
[ 연습 ] 독도는 대한민국의 아름다운 섬이다
2. 네이버 영화 감상평 문장 분석
# 데이타 확인
# https://github.com/e9t/nsmc/
import pandas as pd
train_df = pd.read_csv('nsmc-master/ratings_train.txt', sep='\t')
train_df.head(5)
# label 값이 1이면 긍정, 0이면 부정
id | document | label | |
---|---|---|---|
0 | 9976970 | 아 더빙.. 진짜 짜증나네요 목소리 | 0 |
1 | 3819312 | 흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나 | 1 |
2 | 10265843 | 너무재밓었다그래서보는것을추천한다 | 0 |
3 | 9045019 | 교도소 이야기구먼 ..솔직히 재미는 없다..평점 조정 | 0 |
4 | 6483659 | 사이몬페그의 익살스런 연기가 돋보였던 영화!스파이더맨에서 늙어보이기만 했던 커스틴 ... | 1 |
# 0과 1 (부정과 긍정)의 비율이 균등한 분포임을 확인
train_df['label'].value_counts()
0 75173
1 74827
Name: label, dtype: int64
# null 값 확인
train_df.isnull().sum()
id 0
document 5
label 0
dtype: int64
# 'document' 컬럼에 Null 값이 있는데 이는 공백으로 변환
train_df = train_df.fillna(' ')
# 숫자를 공백으로 변경
import re
train_df['document'] = train_df['document'].apply(lambda x: re.sub(r"\d+",' ', x))
# 테스트 데이타로 위와 동일한 작업 - 데이터 로드, null값 공백처리, 숫자를 공백으로 변경
test_df = pd.read_csv('nsmc-master/ratings_test.txt', sep='\t')
test_df = test_df.fillna(' ')
test_df['document'] = test_df['document'].apply(lambda x: re.sub(r"\d+",' ', x))
#!pip install konlpy
#pip install sklearn
# 형태소 분석
# Twitter 객체의 morphs() 는 입력 인자로 들어온 문장을 형태소 단어 형태로 토큰화해 리스트 객체로 반환
from konlpy.tag import Twitter
twitter = Twitter()
C:\Users\kosmo_03\anaconda3\lib\site-packages\konlpy\tag\_okt.py:16: UserWarning: "Twitter" has changed to "Okt" since KoNLPy v0.4.5.
warn('"Twitter" has changed to "Okt" since KoNLPy v0.4.5.')
# 입력 인자로 들어온 텍스트를 형태소 단어로 토큰화하여 리스트 형태로 변환
def tw_tokenizer(text):
tokens_ko = twitter.morphs(text)
return tokens_ko
# 시간소요 ( 노트북 16G : 30 분이상)
# TF-IDF 방식으로
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
tfidf_vect = TfidfVectorizer(tokenizer=tw_tokenizer, ngram_range=(1,2), min_df=3, max_df=0.9)
# 상위 90%로 제한
tfidf_vect.fit(train_df['document'])
tfidf_matrix_train = tfidf_vect.transform(train_df['document'])
C:\Users\kosmo_03\anaconda3\lib\site-packages\sklearn\feature_extraction\text.py:484: UserWarning: The parameter 'token_pattern' will not be used since 'tokenizer' is not None'
warnings.warn("The parameter 'token_pattern' will not be used"
# 회귀를 이용해 감성 분석 분류
lg_clf = LogisticRegression(random_state=0)
# 파라미터 C 최적화를 위해 GridSearchCV를 이용
params = {'C':[1, 3.5, 4.5, 5.5, 10]}
grid_cv = GridSearchCV(lg_clf, param_grid=params, cv=3, scoring='accuracy', verbose=1)
grid_cv.fit(tfidf_matrix_train, train_df['label'])
print(grid_cv.best_params_, round(grid_cv.best_score_,4))
# [결과] {'C': 3.5} 0.8592
# C가 3.5일 때 0.8592 정확도임
Fitting 3 folds for each of 5 candidates, totalling 15 fits
{'C': 3.5} 0.8591
# 학습 데이타에 적용한 TfidfVectorizer를 테스트 데이터에도 사용 ( 시간소요 : 10분)
tfidf_matrix_test = tfidf_vect.transform(test_df['document'])
# classifier는 GridSearchCV에서 최적 파라미터로 학습된 classifier를 그대로 이용
best_estimator = grid_cv.best_estimator_
preds = best_estimator.predict(tfidf_matrix_test)
from sklearn.metrics import accuracy_score
print('LogisticRegression 정확도: ', accuracy_score(test_df['label'], preds))
LogisticRegression 정확도: 0.86184
댓글로 부정인지 긍정인지 확인¶
# type(test_df['document']) -> Series
comment = pd.Series(['안보면 후회'])
tfidf_matrix_test = tfidf_vect.transform(comment)
preds = best_estimator.predict(tfidf_matrix_test)
preds
array([1], dtype=int64)
comment = pd.Series(['감독 꼬라지하고는'])
tfidf_matrix_test = tfidf_vect.transform(comment)
preds = best_estimator.predict(tfidf_matrix_test)
preds
array([0], dtype=int64)
comment = pd.Series(['이 훌륭한 배우들을 데려다가'])
tfidf_matrix_test = tfidf_vect.transform(comment)
preds = best_estimator.predict(tfidf_matrix_test)
preds
array([1], dtype=int64)
comment = pd.Series(['이 훌륭한 배우들을 데려다가 이렇게 만들었네'])
tfidf_matrix_test = tfidf_vect.transform(comment)
preds = best_estimator.predict(tfidf_matrix_test)
preds
array([0], dtype=int64)
comment = pd.Series(['쌍팔년도 영화인듯'])
tfidf_matrix_test = tfidf_vect.transform(comment)
preds = best_estimator.predict(tfidf_matrix_test)
preds
array([0], dtype=int64)
comment = pd.Series(['지구의 자전축이 기울어진 이유는 이 영화에 예의를 표하기 위함이다'])
tfidf_matrix_test = tfidf_vect.transform(comment)
preds = best_estimator.predict(tfidf_matrix_test)
preds
array([0], dtype=int64)
comment = pd.Series(['영화가 콩이네'])
tfidf_matrix_test = tfidf_vect.transform(comment)
preds = best_estimator.predict(tfidf_matrix_test)
preds
array([0], dtype=int64)
comment = pd.Series(['3탕중'])
tfidf_matrix_test = tfidf_vect.transform(comment)
preds = best_estimator.predict(tfidf_matrix_test)
preds
array([0], dtype=int64)
3. 지식인 문장 분석 및 워드클라우드
네이버 지식IN 을 통한 검색을 워드클라우드¶
-
물론 네이버 개발자 API를 이용하면 훨씬 빠르게 데이타를 가져올 수 있다
-
간단하게 주소창의 주소로 크롤링한다.
-
크롬 개발자모드에서 검색부분을 가져온다 ( 각 dl 태그 )
import pandas as pd
import numpy as np
import platform
import matplotlib.pyplot as plt
from bs4 import BeautifulSoup
from urllib.request import urlopen
import urllib
import time
%matplotlib inline
# 간단한 한글 폰드 등록
from matplotlib import rc
plt.rcParams['axes.unicode_minus']=False
rc('font', family='Malgun Gothic')
# 주소를 약간 수정함
html = 'https://kin.naver.com/search/list.nhn?query={key_word}&page={num}'
response = urlopen(html.format(num=1, key_word=urllib.parse.quote('여자친구 선물')))
soup = BeautifulSoup(response, "html.parser")
tmp = soup.find_all('dl')
# 테스트로 첫번째 페이지의 텍스트만 가져온다
tmp_list = []
for line in tmp:
tmp_list.append(line.text)
tmp_list[:1]
['\n\n여자친구 선물 찾아보구있습니다!\n\n2021.02.04.\n... 그래서 여자친구 선물 고르는데 조언을 좀 받고 싶은데 여자친구 선물로 어떤 걸 주면 좋아할까요? 도움주세요ㅠ 여자친구 선물로 이건 어떠세요? 저도 얼마전에... \n\nQ&A\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t > 헤어관리\n|\n답변수 10\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\xa0추천수 0\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n']
#1000 만개 정도의 검색 결과를 읽어온다.
# 첫번째 페이지 start=1, 두번째 페이지인 경우 start=11인거 확인한다.
# 웹 페이지 직접 접근 할 땐느 간단이 time.sleep()으로 요청을 간격적으로 한다.
# 시간이 10분 정도 소요되기에 상태바를 보여준다. ( tqdm.tqdm_notebook 이용)
from urllib.request import urlopen
from tqdm import tqdm_notebook
present_candi_text = []
# 진행상태바
for n in tqdm_notebook(range(1, 1000, 10)):
response = urlopen(html.format(num=n, key_word=urllib.parse.quote('여자친구 선물')))
soup = BeautifulSoup(response, "html.parser")
tmp = soup.find_all('dl')
for line in tmp:
present_candi_text.append(line.text)
time.sleep(0.5) # 읽어오는 시간 여유가 없을 경우 예외 발생해버림. 정석대로 하려면 그래도 예외처리 필요
<ipython-input-4-578b13d66125>:12: TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0
Please use `tqdm.notebook.tqdm` instead of `tqdm.tqdm_notebook`
for n in tqdm_notebook(range(1, 1000, 10)):
len(present_candi_text)
90
import nltk
from konlpy.tag import Okt
okt = Okt()
present_text = ''
for tmp_line in present_candi_text[:1000]:
present_text = present_text + tmp_line + '\n'
# 형태소 분석
ko_tokens = okt.morphs(present_text)
# 토큰 수 확인
ko = nltk.Text(ko_tokens)
print(len(ko.tokens))
print(len(set(ko.tokens))) # 중복제거
5861
1225
ko.vocab().most_common(15)
[('\n', 358),
('선물', 250),
('여자친구', 242),
('.', 234),
('...', 135),
('답변', 112),
('|', 108),
('수', 93),
('Q', 90),
('&', 90),
('A', 90),
('\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t ', 90),
('>', 90),
('\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t', 90),
('\n\n', 88)]
# 의미없는 단어들을 수동으로 제거해준다.
stop_words = ['.','가','요','답변','...','을','수','에','질문','제','를','이','도',
'좋','1','는','로','으로','2','것','은','다',',','니다','대','들',
'2017','들','데','..','의','때','겠','고','게','네요','한','일','할',
'10','?','하는','06','주','려고','인데','거','좀','는데','~','ㅎㅎ',
'하나','이상','20','뭐','까','있는','잘','습니다','다면','했','주려',
'지','있','못','후','중','줄','6','과','어떤','기본','!!',
'단어','선물해','라고','중요한','합','가요','....','보이','네','무지', '\n']
ko_tokens = [each_word for each_word in ko_tokens
if each_word not in stop_words]
ko = nltk.Text(ko_tokens)
ko.vocab().most_common(10)
[('선물', 250),
('여자친구', 242),
('|', 108),
('Q', 90),
('&', 90),
('A', 90),
('\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t ', 90),
('>', 90),
('\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t', 90),
('\n\n', 88)]
# !pip install wordcloud
""" 워드 크라우드 그리기 """
from wordcloud import WordCloud, STOPWORDS
from PIL import Image
data = ko.vocab().most_common(100)
wordcloud = WordCloud(font_path='c:/Windows/Fonts/malgun.ttf',
relative_scaling=0.2,
background_color='white').generate_from_frequencies(dict(data))
plt.figure(figsize=(16,8))
plt.imshow(wordcloud);
plt.axis('off');
""" 이미지로 마스킹하여 워드 크라우드 그리기 """
from wordcloud import ImageColorGenerator
mask = np.array(Image.open('./img/heart_image.jpg'))
image_color = ImageColorGenerator(mask)
data = ko.vocab().most_common(100)
wordcloud = WordCloud(font_path='c:/Windows/Fonts/malgun.ttf',
relative_scaling=0.2,
mask = mask,
background_color='white').generate_from_frequencies(dict(data))
plt.figure(figsize=(16,8))
plt.imshow(wordcloud.recolor(color_func=image_color));
plt.axis('off');
4. 나이브베이즈 분류 이론
*** 조건부 확률 P(B|A) : "사건 A가 발생한 조건"에서 "다른 사건 B가 일어날 확률" 비가 내릴 확률 : P(비) 교통사고가 발생할 확률 : P(교통사고) 비가 내리는 날에 교통사고가 발생할 확률 : P(교통사고|비) *** 베이즈 정리 (Bayes' theorem) - 조건부 확률과 관련된 이론 P(B|A) = P(A|B)P(B)/P(A) P(A) : A가 일어날 확률 P(B) : B가 일어날 확률 P(A|B) : B가 일어난 후에 A가 일어날 확률 P(B|A) : A가 일어난 후에 B가 일어날 확률 [예] 마트의 매출 전체 손님 수 : 100 맥주를 산 손님 수 : 50 라면을 산 손님 수 : 20 맥주와 라면을 산 손님 수 : 10 ` 맥주를 사고 라면을 구매할 확률 : 50/100 * 10/50 = 1/10 전체손님 중에서 맥주를 살 확률 : 50/100 맥주를 산 손님중 라면을 살 확률 : 10/50 ` 라면을 사고 맥주를 구매할 확률 : 20/100 * 10/20 = 1/10 전체손님 중에서 라면을 살 확률 : 20/100 라면을 산 손님중 맥주를 살 확률 : 10/20 P(A|B)*P(B) = P(B|A)P(A) *** 나이브 베이즈 분류 베이즈 정리를 이용한 텍스트 분류에서 A는 입력 텍스트, B를 카테고리 판정 결과라고 한다면 이메일 스팸 필터에서 A는 받은 메일이고, B는 스팸메일 판정 결과이다. 나이브베이즈분류는 텍스트의 단어 출현 비율을 조사하여 어떤 카테고리로 분류할 때 사용한다. <단어의 출현 횟수>/<카테고리 전체 단어수> = <어떤 카테고리에 해당 단어 출현할 확률> [참고] 파이썬을 이용한 머신러닝 딥러닝 실전개발 입문 [추가공부] 데이타 사이언스 스쿨 : 감성 분류 |
5. 나이브베이즈 분류 - 영문 분류
Naive Bayes Classifier
- 지도학습의 한 종류로 간단한 분류기
- 두 사건을 서로 독립이라 가정하고 각가의 조건부 확률을 계산
[예]
i like you pos
i hate you neg
you like me neg
i like her pos
i like dog ???
from nltk.tokenize import word_tokenize
import nltk
nltk.download('punkt')
[nltk_data] Downloading package punkt to
[nltk_data] C:\Users\kosmo_03\AppData\Roaming\nltk_data...
[nltk_data] Package punkt is already up-to-date!
True
""" 훈련데이타 """
train = [('i like you', 'pos'),
('i hate you', 'neg'),
('you dislike me', 'neg'),
('i like her', 'pos')]
# 훈련문장에서 사용된 단어들 모두 찾기
all_words = set(word.lower() for sentence in train
for word in word_tokenize(sentence[0]))
all_words
{'dislike', 'hate', 'her', 'i', 'like', 'me', 'you'}
# 위 모든 단어들이 각각 훈련문장에 속한 단어인지 아닌지 확인
t = [({word: (word in word_tokenize(x[0])) for word in all_words}, x[1])
for x in train]
t
[({'dislike': False,
'you': True,
'i': True,
'hate': False,
'like': True,
'me': False,
'her': False},
'pos'),
({'dislike': False,
'you': True,
'i': True,
'hate': True,
'like': False,
'me': False,
'her': False},
'neg'),
({'dislike': True,
'you': True,
'i': False,
'hate': False,
'like': False,
'me': True,
'her': False},
'neg'),
({'dislike': False,
'you': False,
'i': True,
'hate': False,
'like': True,
'me': False,
'her': True},
'pos')]
# 나이브베이즈 분류기
cls = nltk.NaiveBayesClassifier.train(t)
# 테스트
test_sens = 'he funny blackpink'
test_dic = { word.lower() : (word in word_tokenize(test_sens.lower()))
for word in all_words }
cls.classify(test_dic)
'neg'
6. 나이브베이즈 분류 - 한글 분류
[참고-예제] 2중 반복
result = [x*y for x in range(2,10) for y in range(1,10)]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 3, 6, 9, 12, 15, 18, 21, 24, 27, 4, 8, 12, 16, 20, 24, 28, 32, 36, 5, 10, 15, 20, 25, 30, 35, 40, 45, 6, 12, 18, 24, 30, 36, 42 , 48, 54, 7, 14, 21, 28, 35, 42, 49, 56, 63, 8, 16, 24, 32, 40, 48, 56, 64, 72, 9, 18, 27, 36, 45, 54, 63, 72, 81]
from nltk.tokenize import word_tokenize
import nltk
# 2020.07 실행시 에러 발생하여 추가
nltk.download('punkt')
from konlpy.tag import Okt
pos_tagger = Okt()
[nltk_data] Downloading package punkt to
[nltk_data] C:\Users\kosmo_03\AppData\Roaming\nltk_data...
[nltk_data] Package punkt is already up-to-date!
""" 훈련데이타 """
train = [('메리가 좋아', 'pos'),
('고양이도 좋아', 'pos'),
('난 수업이 지루해', 'neg'),
('메리는 이쁜 고양이야', 'pos'),
('난 마치고 메리랑 놀거야', 'pos')]
all_words = set(word.lower() for sentence in train
for word in word_tokenize(sentence[0]))
all_words
{'고양이도',
'고양이야',
'난',
'놀거야',
'마치고',
'메리가',
'메리는',
'메리랑',
'수업이',
'이쁜',
'좋아',
'지루해'}
t = [({word: (word in word_tokenize(x[0])) for word in all_words}, x[1])
for x in train]
# 나이브베이즈 분류기
cls = nltk.NaiveBayesClassifier.train(t)
# 테스트
test_sens = '수업 끝나면 밥 먹어야지'
test_dic = { word.lower() : (word in word_tokenize(test_sens.lower()))
for word in all_words }
cls.classify(test_dic)
'pos'
형태소 분석을 한 경우
# github의 Lucy Park 님의 코드에 따르면 태그를 붙여주는 것이 좋다고 권장함
def tokenize(doc):
return ['/'.join(t) for t in pos_tagger.pos(doc, norm=True, stem=True)]
# norm 동사의 기본값을 찾음, stem 어근을 찾음
train_docs = [ (tokenize(row[0]), row[1]) for row in train ]
train_docs
[(['메리/Noun', '가/Josa', '좋다/Adjective'], 'pos'),
(['고양이/Noun', '도/Josa', '좋다/Adjective'], 'pos'),
(['난/Noun', '수업/Noun', '이/Josa', '지루하다/Adjective'], 'neg'),
(['메리/Noun', '는/Josa', '이쁘다/Adjective', '고양이/Noun', '야/Josa'], 'pos'),
(['난/Noun', '마치/Noun', '고/Josa', '메리/Noun', '랑/Josa', '놀다/Verb'], 'pos')]
# 사용되는 전체 단어(말뭉치) 찾기
# train_docs를 한 줄씩 읽어서 d라고 하고,
# d의 0번째를 읽어서 t라고 하여 리스트에 담는다.
tokens = [ t for d in train_docs for t in d[0] ]
tokens[:5]
['메리/Noun', '가/Josa', '좋다/Adjective', '고양이/Noun', '도/Josa']
# 훈련문장의 단어들이 전체 단어(말뭉치)에 있는 단어인지 확인
# 명사와 조사를 구분하여 판독이 용이
def term_exists(doc):
return {word: (word in set(doc)) for word in tokens}
train_xy = [ (term_exists(d), c) for d, c in train_docs ]
train_xy[:1]
[({'메리/Noun': True,
'가/Josa': True,
'좋다/Adjective': True,
'고양이/Noun': False,
'도/Josa': False,
'난/Noun': False,
'수업/Noun': False,
'이/Josa': False,
'지루하다/Adjective': False,
'는/Josa': False,
'이쁘다/Adjective': False,
'야/Josa': False,
'마치/Noun': False,
'고/Josa': False,
'랑/Josa': False,
'놀다/Verb': False},
'pos')]
# 나이브베이즈 분류기
cls = nltk.NaiveBayesClassifier.train(t)
# 테스트
test_sens = [('수업이 끝나면 메리랑 놀자')]
test_dic = pos_tagger.pos(test_sens[0])
test_features = { word : (word in tokens) for word in test_dic }
cls.classify(test_features)
'pos'
7. 스팸메일 판단
from Ex09_bayes import BayesianFilter
bf = BayesianFilter()
# 텍스트 학습
bf.fit("파격 세일 - 오늘까지만 30% 할인", "광고")
bf.fit("쿠폰 선물 & 무료 배송", "광고")
bf.fit("현데계 백화점 세일", "광고")
bf.fit("봄과 함께 찾아온 따뜻한 신제품 소식", "광고")
bf.fit("인기 제품 기간 한정 세일", "광고")
bf.fit("오늘 일정 확인", "중요")
bf.fit("프로젝트 진행 상황 보고","중요")
bf.fit("계약 잘 부탁드립니다","중요")
bf.fit("회의 일정이 등록되었습니다.","중요")
bf.fit("오늘 일정이 없습니다.","중요")
# pred, scorelist = bf.predict('재고정리, 무료 배송')
# pred, scorelist = bf.predict('회의가 변경되었습니다')
# pred, scorelist = bf.predict('참석자가 바뀌었습니다')
pred, scorelist = bf.predict('회의 장소가 백화점으로 바뀌었습니다')
print('결과 : ', pred)
print(scorelist)
결과 : 중요
[('광고', -16.697549079582547), ('중요', -15.955936186257098)]