텍스트 분석
어떻게 가공할 것인지, 가공한 텍스트로 어떻게 예측할 것인지
ex)영화 줄거리를 가지고 영화 장르 예측?
판다스와 데이터프레인 사용법에 대해 복습
형태소 분석과 워드클라우드 실습
머신러닝 개념 이해, 분류하기
파이썬에서 반드시 기억할 것
리스트 컴프리헨션 배울 것임 좀 어려울 수 있음
반복 학습 무조건 할 것.
한글 표시하려면 폰트 필요 근데 코랩은 가상컴이라 없음
폰트코드 실행하고 exécution - redémarrer l'env
csv데이터를 코랩에 업로드
폰트, 파일업로드는 코랩 켤때마다 입력해야함
불러온 데이터들이 어떻게 이루어져있는가?
중복된 값이 있는가? 있다면 제거
df.isnull()
빈 행이 있는지 (결측치)
print(df.isnull().sum())
빈 값이 있는지 (결측치)
df['news'].unique()
.unique는 news열에 있는 고유값만 출력
df['code'].nunique()
code열에 있는 고유값이 몇 개인지 (nunique)
df.drop_duplicates(subset=['news'], inplace=True)
여기서 inplace=true를 빼면 df는 달라지지 않는다. df에 있는 원본데이터는 그대로 남아있고 혹시나 사용자가 원하면 df2로 저장만 도와줌.
inplace --> 현재 df 데이터프레임을 바꿔주는 것
len(df)
길이만 확인
.
중복 제거했으니 남은 기사에 대해 카테고리별로 기사가 몇 개씩 있는지 보기
df['code'].value_counts()
어떤 열인지 꼭 명시 (여기서 code)
.
df['code'].value_counts().plot(kind='bar')
바 형태의 그래프로 시각화
데이터프레임에서 각각 기사 본문에 대해서 혹시 필요한 단어가 있는지 확인하고 제거하기
ex)워드 클라우드를 만들었는데 워드클라우드에 너무 자주 등장하는 단어 (뉴스, 최근)같이 내용과 필요없이 빈번한 단어를 제거
형태소분석
한국어 텍스트 처리할 때는 형태소 분석기를 통해 자연어처리.
형태소 단위 또는 명사 단위 뽑아냄 --> 형태소 혹은 명사 단위로 토큰화
konply 인스톨
from konlpy.tag import Okt
konlpy불러옴. 여기서 Okt는 개발자가 정한 것이므로 뭔뜻인지 나도 모름
tokenizer = Okt()
--> 명사 분석기를 tokenizer라는 이름으로 사용하겠다는 뜻
\ (백슬래시)는 문자열이 다음줄까지도 이어진다는 것.
print(tokenizer.nouns(kor_text))
이제 tokenizer로 kor_text를 분석하겠다는 뜻
여기서 최근, 기자, 제공, 무단배포 등은 기사마다 자주 등장하는 단어이므로 제거 --> 불용어 리스트 (stopwords)
stop_words = ['기자', '제공', '무단', '배포', '무단배포', '배포금지', '이번', '위해', '라며', '금지', '뉴스', '통해', '오늘', '지난달', '지난', '대한', '경우', '관련', '뉴시스', '현재', '지난해', '때문', '지금', '또한', '만큼', '최근', '당시', '올해', '대해', '다시', '모두']
이제 news.data에 있는 모든 행을 각각 토큰화진행
--> 그래야 불용어리스트에 있는지 확인
df['tokenized'] = df['news'].apply(tokenizer.nouns)
news에 tokenizer로 kor_text를 분석한 걸 news에 접목시키고 df['tokenized'] 로 명명
그리고 출력
해보면 황범,순 등 가끔 못알아듣는 경우 있음 --> 그래서 여러방법으로 진행
tokenized열에 저장한 단어 중 불용어리스트에 있는 단어가 있으면 제거
test_list = ['경찰서', '상해', '혐의', '씨', '구속', '수사', '일']
remove_word_list = ['경찰서', '구속']
test_list_copy = [item for item in test_list]
print(test_list_copy)
리스트를 만들 때 쓰는 것.
여기서 item for item in test_list를 보자
--> 리스트를 만들건데 리스트에 있을 요소는 item이라는 요소가 들어가 있을 것이다. 라고 말하는 것.
그게 어떤 아이템이냐면(for문) test_list에 있는 아이템을 하나하나 뽑아서 리스트 형태(test_list_copy)로 저장하겠다.
test_list = ['경찰서', '상해', '혐의', '씨', '구속', '수사', '일']
remove_word_list = ['경찰서', '구속']
test_list = [item for item in test_list if item not in remove_word_list and len(item) > 1]
print(test_list)
여기서 'if item not in remove_word_list and len(item) > 1'은
--> item이 remove_word_list에 없고 글자 수가 1 초과인 걸 만족하면 보여달라는 뜻. 만족하지 않으면 보여주지말라
1 초과로 하는 이유 --> 씨, 일 등 필요없는 단어 없애기 위함
이제 열마다 이걸 모두 적용할 것임
df['tokenized'] = df['tokenized'].apply(lambda x: [item for item in x if item not in stop_words and len(item) > 1])
여기서 'df['tokenized'] = df['tokenized'].apply()'을 보자.
apply는 각각의 행에 대해서 () 안에 있는 함수를 실행하겠다는 뜻
그런데 위에 item들어가는 건 함수가 아니고 연산. 그래서 따로 함수를 만들것임 그게 lambda x
lambda x:
lambda x 는 이 하나의 행을 일단 x라 지칭하겠다는 뜻.
그리고 불용어리스트에 있는 단어를 제외시키자.
그리고 df를 출력하면 황범, 순 등이 제거된 걸 확인할 수 있다.
불용어가 제거된 df를 가지고 각 분야의 단어 빈도수를 확일할 것임.
빈도수를 세기 위해 각 분야에 나온 단어들을 일렬로 쭉 한 리스트에 작성하고 단어 수를 셀 것임
df[df['code']=='사회']
조건 명시 --> df['code']는 사회와 같은 행만 뽑아달라는 뜻.
하나의 리스트로 연결하려면 .values라는 속성을 끌어내야한다.
df[df['code']=='사회'].values
이러면 각각의 행이 하나의 리스트로 묶임
그런데 그냥 values를 하게 되면 기사제목, 코드, tokenized가 한번에 다 들어가있다. 여기서 필요한 tokenized만 빼내보자.
df[df['code']=='사회']['tokenized']
이렇게 하면 사회 코드 중 tokenized에 해당하는 행만 모음. 이걸 다시 values로 바꿔보자.
df[df['code']=='사회']['tokenized'].values
하지만 여기서는 리스트별로 묶여있다. 이것도 해체해서 단어로 해체해보자.
이럴 때는 numpy패키지에서 제공하는 hstack이라는 함수를 사용.
import numpy as np
numpy임포트
hstack함수를 사용해서 단어로 추출하고 하나의 변수에 저장할 것.
social_news = np.hstack(df[df['code']=='사회']['tokenized'].values)
그리고 social_news 출력
똑같이 생활/문화와 IT/과학 카테고리도 뽑아보자.
social_news = np.hstack(df[df['code']=='사회']['tokenized'].values)
life_news = np.hstack(df[df['code']=='생활/문화']['tokenized'].values)
it_news = np.hstack(df[df['code']=='IT/과학']['tokenized'].values)
print(social_news)
print(life_news)
print(it_news)
이제 단어 수를 세보자
print(len(social_news))
print(len(life_news))
print(len(it_news))
이건 총 단어개수고, 이젠 단어별 빈도수를 알아야한다. 이럴 땐 collections패키지의 Counter함수를 사용.
from collections import Counter
test_list = ['바나나', '전화기', '바나나', '바나나', '사과', '사과', '딸기', '메론', '수박', '수박', '토마토', '토마토', '전화기', '전화기', '전화기']
# 단어 카운트를 수행
test_word_count = Counter(test_list)
# 전체 단어 카운트를 출력
print(test_word_count)
로 입력하면
Counter({'전화기': 4, '바나나': 3, '사과': 2, '수박': 2, '토마토': 2, '딸기': 1, '메론': 1})
로 출력된다.
x등까지 빈도수를 알고싶다 --> mostcommon
print(test_word_count.most_common(3))
그러면
[('전화기', 4), ('바나나', 3), ('사과', 2)]
으로 출력된다.
그래서 social_news를 Counter함수에 입력하고
social_news_count = Counter(social_news)
상위 10개 단어를 세서 출력한다.
print(social_news_count.most_common(10))
생활/문화와 IT/과학도 같은방법으로 진행
life_news_count = Counter(life_news)
print(life_news_count.most_common(10))
it_news_count = Counter(it_news)
print(it_news_count.most_common(10))
이제 이걸 워드 클라우드로 만들어보자.
wordcloud 패키지를 임포트하여 WordCloud함수(모듈)을 불러온다
from wordcloud import WordCloud
#대소문자 주의
인자가 문자열로만 이루어져 있어야 워드클라우드를 만들 수 있다.
--> 빈도 리스트로는 어렵다. 하나의 문자열로 이루어져 있어야 하는데
그래서 그냥 빈도가 없는 리스트를 이용한다.
' '.join(social_news)
이렇게 하면 리스트 속 요소들이 하나의 문자열로 나옴.
두 따옴표 사이는 요소를 나눠주는 것임.
ex) ,를 넣으면 요소 사이에 ,가 들어감. 그래서 띄어쓰기로 한 것임.
이제 워드클라우드 뼈대 코드를 넣는다.
# 사용하고자 하는 폰트의 경로. Colab에서는 이 경로를 사용하시면 됩니다.
fontpath = '/usr/share/fonts/truetype/nanum/NanumBarunGothic.ttf'
plt.figure(figsize = (15,15))
wc = WordCloud(max_words = 사용할 단어의 수 , width = 가로, height = 세로, font_path = fontpath).generate('입력 문자열')
plt.imshow(wc, interpolation = 'bilinear')
맨 위 한글폰트 불러온 걸 변수 fontpath로 저장. 그리고 폰트의 위치를 명시한 것임.
plt.imshow는 이미지를 표시하기 위한 코드.
그래서 모든 값을 입력하면 아래와 같다.
fontpath = '/usr/share/fonts/truetype/nanum/NanumBarunGothic.ttf'
plt.figure(figsize = (15,15))
wc = WordCloud(max_words=2000, width=1600, height=800, font_path = fontpath).generate(temp_Data)
plt.imshow(wc, interpolation = 'bilinear')
temp_Data 대소문자 주의
이제 크롤링부터 워드클라우드까지 다시 해보자.
네이버 영화 줄거리로 워드클라우드 만들거임
URL분석
https://movie.naver.com/movie/bi/mi/basic.naver?code=191559
여기서 code=191559는 각 영화의 고유값
HTML분석
크롤링 url접속 - f12 - 해당부분 태그확인 - copy - selector copy
하면
#content > div.article > div.mv_info_area > div.mv_info > h3 > a:nth-child(1)
이렇게 나옴
크롤링 기본 세팅을 해주고
import requests # requests라는 패키지를 임포트
import pandas as pd # pandas라는 패키지를 임포트하는데 앞으로 pd로 부르겠음
from bs4 import BeautifulSoup # bs4라는 패키지로부터 BeautifulSoup라는 모듈을 임포트
# 네이버의 크롤링 방지 장치를 우회하기 위함
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}
movie_code = 191559 # 211097까지 존재, 191559는 앞서 봤던 영화 '듄'의 코드
movies = requests.get('https://movie.naver.com/movie/bi/mi/basic.naver?code='+str(movie_code), headers=headers)
# html 분석
soup = BeautifulSoup(movies.content, 'html.parser')
다시 url로 들어와서 태그 위치 가져옴
movie_title = soup.select('#content > div.article > div.mv_info_area > div.mv_info > h3 > a:nth-of-type(1)')
여기서 nth-child(1)가 ath-of-type(1)로 바뀐 걸 알 수 있는데, colab에서는 nth-child가 되지 않아 이렇게 바꿈. 역할은 같음.
a라는 태그가 있으면 첫번 째 태그만 가져오라는 뜻임.
제목이니까 하나만 가져와도 됨.
장르도 가져와보자
movie_genre = soup.select('#content > div.article > div.mv_info_area > div.mv_info > dl > dd:nth-of-type(2) > p > span:nth-of-type(1) > a')
장르는 한 개가 아닌 3개였으므로 맨 마지막 태그에는 모든 a를 다 가져와라고 한거임.
줄거리 부분도 가져와보자.
movie_content = soup.select('#content > div.article > div.section_group.section_group_frst > div:nth-of-type(1) > div > div > p')
그리고 프린트하면 장르부분만 비어있는데, 이건 nth-of-type때문에그럼. 위치라든지 이런게 바뀜. 그럴 때는 일일이 확인해야함. 여기서는 1로 바꿔보자.
이제 텍스트만 뽑아보자.
movie_title = movie_title[0].text
print(movie_title)
여기서 대괄호 속 0 : 원래 soup.select를 하게 되면 전부 리스트로 만들어주기 때문에 0번째 요소인 제목을 뽑은것임.
이렇게 장르를 똑같이 하면 장르가 하나만 나옴.
그럼 여러 개로 하려면?
movie_genre_list = []
for genre in movie_genre:
movie_genre_list.append(genre.text)
이렇게 하면 됨.
줄거리는 요소가 1개니 제목과 똑같이 하면 된다.
movie_content = movie_content[0].text
print(movie_content)
영화 한 개를 크롤링해보자.
def crawl(code):
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}
movie_code = code # 211097까지 존재
movies = requests.get('https://movie.naver.com/movie/bi/mi/basic.naver?code='+str(movie_code), headers=headers)
soup = BeautifulSoup(movies.content, 'html.parser')
movie_title = soup.select('#content > div.article > div.mv_info_area > div.mv_info > h3 > a:nth-of-type(1)')
movie_genre = soup.select('#content > div.article > div.mv_info_area > div.mv_info > dl > dd:nth-of-type(1) > p > span:nth-of-type(1) > a')
movie_content = soup.select('#content > div.article > div.section_group.section_group_frst > div:nth-of-type(1) > div > div > p')
movie_title = movie_title[0].text
movie_genre_list = []
for genre in movie_genre:
movie_genre_list.append(genre.text)
movie_content = movie_content[0].text
movie_list = [movie_title, movie_genre_list, movie_content]
return movie_list # 크롤링한 내용을 다른 변수에 저장할 수 있도록 리턴!
크롤링 할 때마다 일일이 입력하기 번거로워서 code값만 명시하면 그걸 url에 넣고 url에 접속해서 크롤링하겠다는 걸 함수로 만든 것.
code를 명시해야만 함수가 진행될 수 있다.
이 함수의 경우는 movie_code를 명시하면 해당 url로 접근해서 크롤링을 하는 것.
return은 함수가 끝난 뒤에도 다음에 사용하기 위해서 저장하는 것.
이제 여러 개를 진행해보자.
def crawl_all():
movie_list_all = [] # 전체 영화 내용을 저장하기 위한 리스트
for i in range(10000, 20001): # 영화 코드 10000 부터 영화 코드 20000 까지 크롤링!
try: # 혹시나 크롤링이 안되더라도 다음 영화 코드로 계속 진행하라는 의미의 try ~ except
movie_list = crawl(i)
movie_list_all.append(movie_list) # 크롤링해온 내용을 리스트에 저장
except:
continue # 그냥 다음 for문을 진행해주세요!
return movie_list_all # 전체 영화 내용이 담긴 리스트를 리턴
여기서 try except부분 :
모든 코드를 알 수 없기 때문에 넣은 것임. 여기서 except이하는 다음 for문을 진행하라는 뜻.
10000번에서 20000번까지는 매우 오래걸린다.
그래서 일단 함수를 정의해두고 연달아서 함수를 실행한 다음 csv파일로 저장할 것.
movie_list_all = crawl_all()
#데이터프레임 만들기
df = pd.DataFrame(movie_list_all, columns=['Title', 'Genre', 'Content'])
print(df)
df.to_csv('naver_movies.csv')
머신러닝이란?
인공지능과 머신러닝?은 그냥 숫자
예를 들어
공부시간*a+b = 성적
이라 했을때,
수많은 공부시간 - 저 방정식에서 주어진 성적 데이터를 가장 잘 설명하는 a, b값을 추정하는 것 --> 학습
학습한 걸 토대로 오차를 최대로 줄인 후 경향성을 만듦 --> 최적의 a, b값 추정. --> 최적화
이게 선형회귀
머신러닝으로 줄거리를 통해 영화의 장르를 예측해보자
기계는 사람과 달라서 영화 줄거리를 보고 딱 알 수 없다. 글자를 바로 이해하지 못하므로 따로 입력해줘야 함. 단어의 의미가 가까우면 가깝게 배치, 멀면 멀게 배치 --> 벡터화 (vectorisation)
(그저 단어를 숫자를 치환하는 것)
벡터화시킨 줄거리를 토대로 기계에게 해당 줄거리는 어떤 장르에 해당한다고 지속적으로 학습시키기 --> 모델
우리가 '크다'를 설명할 때 '작다'의 반댓말이라 설명하듯이 단어관의 관계를 알려줌. 결국 문장 자체의 의미는 중요하지 않다.
텍스트 분류 (text classification)
클래스가 2개인 경우 이진 분류 (binary classification)
클래스가 3개 이상인 경우 다중 클래스 분류 (Multiclass Classification)
여기서 이진 분류의 예로는 스팸인지 아닌지를 판별하는 분류기.
오늘은 다중 클래스 분류를 할 것.
데이터가 어떻게 생겼는지 보자.
IMDB 줄거리 데이터
우리가 이미 네이버영화 줄거리 데이터를 크롤링은 해놨지만 예측모델로 만들기에는 부족. 훨씬 더 많아야한다.
train_data.txt는 훈련데이터
test_data_solution.txt는 테스트 데이터
둘다 똑같이 들어가있지만 훈련 데이터는 줄거리와 장르 둘 다 기계에게 알려줌. 그러면 기계는 줄거리와 장르를 데이터로 학습.
테스트 데이터는 학습하지 않고 학습한 걸 토대로 예측.
여기서 기계가 줄거리의 장르를 맞추면 정확도 상승, 아니면 정확도 하락함.
학습 데이터로는 답을 다 봤으니까 답을 안 본 테스트 데이터로 예측시키면 더 정확한 예측 평가 지표를 만들 수 있음
벡터화를 만드는 방법, 진행하는 방법
벡터화에는 여러가지 방식이 있다.
그 중 DTM (Document-Term Matrix)
벡터는 숫자들의 나열
문서에 어떤 단어가 몇 번 등장했는지에 따라 행렬(표)로 표시
각 행에 해당하는 값이 벡터.
유사도도 구할 수 있다.
서로 비슷하게 생긴 벡터가 있을 경우 유사도 높음.
한계점 : 영어의 a, the, 불어의 le, la, les, tu, il, la등은 매우 빈번한 단어임. 단어의 중요도는 인지하지 못함.
그래서 이걸 약간 보완해주는 벡터화가 또 있다.
TF-IDF(Term Frenquency-Inverse Document Frequency)
단어별 중요도를 계산해서 행렬을 다시 만듦.
tf(d,t) = 특정 문서d의 특정 단어가 t가 들어가는 횟수
df(t) = 특정 단어 t가 등장한 문서의 수
idf(d, t) = df(t)에 반비례하는 수
--> TF-IDF는 DTM을 사용
fit.transform()
객체 안에다가 벡터화하고자 하는 변수를 넣어가면서 벡터화 진행 --> 저장하면서 벡터화
--> 훈련 데이터에 사용할 것
transform()
만들어져있는 벡터값을 보고 치환만 해서 바로 벡터화 진행 (학습 진행하지 않음)
--> 테스트 데이터에 사용할 것
데이터 구축, 학습, 모델구축해보기
어떤 머신러닝모델을 사용할까?
from sklearn.naive_bayes import MultinomialNB #다항분포 나이브 베이즈 모델
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score #정확도 계산
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
에서
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
는 순서대로 DTM, TF-IDF벡터를 만드는 함수
훈련용 줄거리 데이터에 대한 DTM을 만든다
dtmvector = CountVectorizer() # 객체생성 --> 함수를 쓰기 위한 준비작업
x_train_dtm = dtmvetor.fit_transform(x_train) # 함수 fit_transform을 사용 --> 객체생성은 함수를 사용하기 위한 준비작업임
테스트용 줄거리 데이터(x_test)에 대에 DTM, TF-IDF를 만든다.
x_test_dtm = dtmvector.transform(x_test) #테스트 데이터를 DTM으로 변환
tfidfv_test = tfidf_transformer.transform(x_test_dtm) #DTM을 TF-IDF 행렬로 변환
.
나이브 베이즈 분류기
베이즈 정리
영화 줄거리를 계산하고자 할 때,
모험을 떠난다라는 줄거리가 액션장르일 확률은
P(액션l모험을 떠난다) = P(모험을 떠난다l액션)*P(액션)/P(모험을 떠난다)
라는 공식으로 구할 수 있음.
각각의 확률들은 직접 계산 가능.
27개 각각의 장르에 대해 확률을 구한 다음 가장 높은 걸 결과값으로 예측하는 것.
그래서 이건 아래와 같은 함수로 끝.
mod = MultinomialNB() #mod는 모델 객체
mod.fit(tfidfv, y_train)
이제 정확도를 측정해보자.
predicted = mod.predict(tfidfv_test) #테스트 데이터에 대한 예측
print("정확도:", accuracy_score(y_test, predicted)) #예측값과 실제값 비교
로지스틱 회귀(Logistic regression)
소프트맥스 함수를 사용한 다중 클래스 분류 알고리즘 지원
다중클래스 분류를 위한 로지스틱 회귀 --> 소프트맥스 회귀
-->어떤 데이터가 각각의 클래스에 해당할 확률을 출력하고 예측값을 실제값과 계속 비교하면서 더 높은 정확도가 나올때까지 계산 -->최적화과정
-->너무 오래걸리므로 횟수제한을 하기도 함
예측값을 모두 더하면 1이 나옴. 그래서 예측값을 더하면 1이 나오도록 보정해주는 역할도 함.
이건 아래와 같이 쓰면 된다.
lr = LogisticRegression(C=10000, penalty='l2')
lr.fit(tfidfv, y_train)
predicted = lr.predict(tfidfv_test) #테스트 데이터에 대한 예측
print("정확도:", accuracy_score(y_test, predicted)) #예측값과 실제값 비교
정확도: 0.5868265682656827
서포트 벡터 머신(Support Vector Machine)
점찍은거에다가 기준선을 그어두고 선을 기준으로 나눔.
선을 잘 긋는 것이 중요
lsvc = LinearSVC(C=1000, penalty='l2', max_iter=500)
lsvc.fit(tfidfv, y_train)
predicted = lsvc.predict(tfidfv_test) #테스트 데이터에 대한 예측
print("정확도:", accuracy_score(y_test, predicted)) #예측값과 실제값 비교
정확도: 0.5208671586715867
데이터분석을 한다 = 가장 좋은 머신러닝모델이 무엇인가? 를 찾는 것.
예측해보기
x_test_dtm = dtmvector.transform(['(내가 만든 줄거리)']) #테스트 데이터를 DTM으로 변환
tfidfv_test = tfidf_transformer.transform(x_test_dtm) #DTM을 TF-IDF 행렬로 변환
predicted = lr.predict(tfidfv_test) #테스트 데이터에 대한 예측
print(predicted)
여기서 어벤저스 명대사 중 하나인 'i love you 3000'을 입력값으로 넣어보자.
x_test_dtm = dtmvector.transform(['i love you 3000']) #테스트 데이터를 DTM으로 변환
tfidfv_test = tfidf_transformer.transform(x_test_dtm) #DTM을 TF-IDF 행렬로 변환
predicted = lr.predict(tfidfv_test) #테스트 데이터에 대한 예측
print(predicted)
24
24는 로맨스의 해당하는 번호임. i love you가 들어가서 그런지 로맨스로 추측했나봄
불용어 제거
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
# dtm, tfidf 벡터 생성을 위한 객체 생성
dtmvector = CountVectorizer(stop_words="english") # 영어 스탑워드를 제거해달라는 뜻!
tfidf_transformer = TfidfTransformer()
# x_train에 대해서 dtm, tfidf 벡터 생성
x_train_dtm = dtmvector.fit_transform(x_train)
tfidfv = tfidf_transformer.fit_transform(x_train_dtm)
# 나이브 베이즈 분류기로 학습 진행
mod = MultinomialNB()
mod.fit(tfidfv, y_train)
# x_test에 대해서 dtm, tfidf 벡터 생성
x_test_dtm = dtmvector.transform(x_test) #테스트 데이터를 DTM으로 변환
tfidfv_test = tfidf_transformer.transform(x_test_dtm) #DTM을 TF-IDF 행렬로 변환
predicted = mod.predict(tfidfv_test) #테스트 데이터에 대한 예측
print("정확도:", accuracy_score(y_test, predicted)) #예측값과 실제값 비교
정확도: 0.44474169741697417