본문 바로가기

Python-머신러닝

나이브 베이즈(Naive Bayes) 및 구글 코랩( Colab), Word Cloud2

반응형

나이브 베이즈(Naive Bayes)를 이용한 스팸 분류

ㄴ5,574개의 이메일 메시지가 있으며, 스팸인지 아닌지의 정보를 가지고 있다.

ㄴ 컬럼 : text, spam

ㄴ spam 컬럼의 값이 1이면 스팸이고, 0이면 스팸이 아닙니다.

ㄴ 스팸인지 아닌지 분류하는 인공지능을 만들자 - 수퍼바이즈드 러닝의 분류 문제!

 

- 구글 Colab 코랩 작업환경

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

 

- 구글 코랩에서 csv 파일 읽기

from google.colab import drive
drive.mount('/content/drive')

import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')
# 지금 작업하고 있는 주피터노트북의 경로를 구글에 맞춰주는 것
# 파일의 경로가 같아야 파일을 읽어올 수 있음 
# 디렉토리 = 폴더
# 같은 폴더에 있어야 불러올 수 있다. 

spam_df = pd.read_csv('emails.csv')

 

ex) 스팸은 몇개이고, 아닌것은 몇개인지 확인하시오.

spam_df['spam'].value_counts()

sns.countplot(data = spam_df, x ='spam')
plt.show()

 

ex) 이메일의 길이가 스팸과 관련이 있는지 확인해 보려 합니다. 이메일의 문자 길이를 구해서, length 라는 컬럼을 만드세요. 

spam_df['length'] = spam_df['text'].apply(len)

# spam_df['text'].str.len() 이랑 같은 뜻

 

ex) 글자 길이를 히스토그램으로 나타내시오.

spam_df['length'].hist()
plt.show()

spam_df.corr()

 

ex) 가장 긴 이메일을 찾아서 스팸인지 아닌지 확인하고, 이메일 내용을 확인하시오.

spam_df.loc[spam_df['length'] == spam_df['length'].max(),]

spam_df.loc[spam_df['length'] == spam_df['length'].max(),'text'][2650]
# 판다스 시리즈, 

 

ex) 0은 스팸이 아니고, 1은 스팸입니다. 파이차트를 통해, 스팸과 스팸이 아닌것이 몇 퍼센트인지, 소수점 1자리 까지만 보여주세요.

spam_count = spam_df['spam'].value_counts()

plt.pie(spam_df['spam'].value_counts(), autopct='%.1f', labels = spam_df['spam'].value_counts().index)
plt.show()

 

ex) 스팸이 아닌것은 ham 변수로, 스팸인것은 spam 변수로 저장하시오.

ham = spam_df.loc[spam_df['spam'] == 0,]
spam = spam_df.loc[spam_df['spam'] == 1,]

# 스팸의 이메일 길이를 히스토그램으로 나타내시오.
spam['length'].hist()
plt.show()

 

ex) 쉼표, 마침표 등의 구두점 제거하기.

ex) 위의 문장에서, 글자를 앞에서부터 하나씩 가져와서, 구두점인지 확인한 후, 구두점이 아닌 문자만 리스트로 저장하시오.

# 결과 예시)   [ 'H', 'e', 'l', ...  'M', 'r', ' ','F' ... ]

Test = 'hello Mr.Future. I am so happy to be learning AI now~'


import string

Test_punc_removed = []

for char in Test:
  if char not in string.punctuation:
    Test_punc_removed.append(char)


[char for char in Test if char not in string.punctuation ]
# 상기 for 문이랑 같은 뜻

 

ex) 위의 리스트에 있는 문자들을, 하나의 문자열로 만드시오.

결과 예시) ‘Hello Mr Future…’


Test_punc_removed_join =''.join(Test_punc_removed)

 

''.join(리스트)

 

ex) STOPWORDS(불용어) 제거하기

ㄴ Stopwords(불용어)란? https://bit.ly/34Ipha2

import nltk
# 내추럴 랭귀지 툴킷

nltk.download('stopwords')

from nltk.corpus import stopwords
my_stopwords = stopwords.words('english')

 

import nltk
# 내추럴 랭귀지 툴킷

nltk.download('stopwords')

from nltk.corpus import stopwords
my_stopwords = stopwords.words('english')
# ㄴ ‘english’ 영어의 불용어

 

ex) 구두점 제거한 문자열을, 이제 불용어 단어에 해당하지 않는 단어들만 모아서 리스트로 만드시오. 

결과 예시) [‘Hello’,’Mr’,’Future’...]

Test_punc_removed_join_clean = []

for word in Test_punc_removed_join.split(): 
  if word.lower() not in my_stopwords:
    Test_punc_removed_join_clean.append(word)
  
Test_punc_removed_join_clean

 

ex) 카운트 벡터라이저 (Count Vectorizer)

결과 예시) [‘Hello’,’Mr’,’Future’...]

# 의미 없는 구두점도 제거했고, 의미 없는 단어도 제거했으면, 
# 이제는, 남아있는 단어들을 숫자로 바꿔줘야 한다. 
# 단어를 숫자로 바꿔주는 것을 벡터라이징 이라고 한다.

from sklearn.feature_extraction.text import CountVectorizer

sample_data = ['This is the first document', 
               'I loved them', 
               'This document is the secon document',
               'I am loving you',
               'And this is the third one']

vec = CountVectorizer()
# 여기에 사용된 모든 단어를 다 뽑는다. 
# 다 뽑아서, 알파벳 순으로 정리한다. 
# 정렬해서 컬럼으로 만든다. 

X = vec.fit_transform(sample_data)
# 5행 14열의 많은 행렬이 만들어졌습니다. 
# 5개의 문장이여서, 5행, 단어를 알파벳순으로 나열하니 14개의 컬럼

# 학습을 시킬 때 항상 넘파이가 들어가야한다.
X = X.toarray()

vec.get_feature_names_out()

 

from sklearn.feature_extraction.text import CountVectorizer

sample_data = ['This is the first document', 
               'I loved them', 
               'This document is the secon document',
               'I am loving you',
               'And this is the third one']

vec = CountVectorizer()

X = vec.fit_transform(sample_data)

X = X.toarray()

vec.get_feature_names_out()

 

ex) 데이터프레임에 있는, 이메일 내용을 Cleaning 한다.

# 이제는 실제 이메일의 데이터를 가지고, 지금까지 한 작업들을 종합해서 처리해보자
# 1. 구두점 제거
# 2. 불용어 제거

# 이 두가지를 하나의 함수로 묶어서 사용하겠습니다. => 파이프라이닝 한다 ! 

import string
import nltk
nltk.download('stopwords')
from nltk.corpus import stopwords
my_stopwords = stopwords.words('english')

def message_cleaning(sentence) : 
  #  1. 구두점 제거
  Test_punc_removed = [char for char in sentence if char not in string.punctuation]
  # 2. 각 글자들을 하나의 문자열로 합친다. 
  Test_punc_removed_join = ''.join(Test_punc_removed)
  # 3. 문자열에 불용어가 포함되어잇는지 확인해서, 불용어 제거한다.
  Test_punc_removed_join_clean = [word for word in Test_punc_removed_join.split() if word.lower() not in my_stopwords]
  # 4. 결과로 남은 단어들만 리턴한다. 
  return Test_punc_removed_join_clean

 

message_cleaning('Hello~~!! my name is, hehehe! nice to meet you!! @')

spam_df['text'].apply(message_cleaning)

 

ex) 이메일의 내용을 벡터라이징 한다. 

# 카운트 벡터라이저의, 애널라이저 파라미터에, 
# 우리가 만든 구두점과 불용어 제거해주는 함수를, 세팅해주면,
# 카운트 백터라이저가 자신이 알아서 문자열을 깨끗하게 먼저 처리한 후에, 숫자로 바꿔준다. 

vec = CountVectorizer(analyzer = message_cleaning)


X = vec.fit_transform(spam_df['text'])
# fit: 텍스트에 있는 내용을 몇개가 문자가 나왔는지, 구두점 제거하고 전체 리뷰에서 몇개가 쓰였는지, 컬럼으로 만든다.

X = X.toarray()
# 학습할 때는 넘파이 어레이로 되어있어야 한다. 

vec.get_feature_names_out()
# 이메일에 등장하는 모든 단어들이 나온다. (불용어 제외)

 

vec = CountVectorizer(analyzer = message_cleaning)
# ㄴ카운트 백터라이저가 자신이 알아서 문자열을 깨끗하게 먼저 처리한 후에, 숫자로 전환해준다. 

X = vec.fit_transform(spam_df['text'])

X = X.toarray()

vec.get_feature_names_out()
#ㄴ 불용어를 제외하고, 이메일에 등장하는 모든 단어들이 나온다. 

 

ex) 데이터 셋으로 훈련 및 모델링 

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.2,random_state=15)


# 모델링
from sklearn.naive_bayes import MultinomialNB,GaussianNB
# 두개 중에 성능 좋은 걸로 사용하시죠
classifier1 = MultinomialNB()
# 다항식이라는 뜻
classifier2 = GaussianNB()
# 가우시안
classifier1.fit(X_train, y_train)
classifier2.fit(X_train,y_train)
# 검증


from sklearn.metrics import confusion_matrix,accuracy_score
y_pred1 = classifier1.predict(X_test)
# 예측한값
y_pred1
# 정답
y_test.values


confusion_matrix(y_test,y_pred1)
accuracy_score(y_test,y_pred1)


y_pred2 = classifier2.predict(X_test)
confusion_matrix(y_test, y_pred2)
accuracy_score(y_test,y_pred2)

 

from sklearn.naive_bayes import MultinomialNB,GaussianNB

classifier1 = MultinomialNB()

classifier2 = GaussianNB()

classifier1.fit(X_train, y_train)
classifier2.fit(X_train,y_train)

 

ex) 다음 2개의 문장을 테스트 해보시오.

1. Free money!!!

2. Hi Kim, Please let me know if you need any further information. Thanks

testing_sample = ['Free money!!!', "Hi Kim, Please let me know if you need any further information. Thanks"]


new_data = np.array(testing_sample)
X = vec.transform(new_data)
X = X.toarray()


classifier1.predict(X)

 

Word Cloud Visualizing

ex) 스팸 이메일에는 어떤 단어들이 많이 들어있는지 Visualizing

- Word Cloud 활용 예:

https://t1.daumcdn.net/thumb/R720x0/?fname=http://t1.daumcdn.net/brunch/service/user/g7Y/image/QoUPiRwBMJoYAppVWNhMq4v8l-o

 

from wordcloud import wordcloud,STOPWORDS
# 스팸이메일에는 어떤 단어가 많이 들어있을까요!


# 워드 클라우드를 사용하려면, 


# 1. 판다스의 스팸컬럼에 저장된 문자열을, 리스트로 먼저 받아오고 
# 2. 리스트에 있는 문자열을 다 합쳐서, 하나의 문자열로 만들어준다.


spam_email_list = spam['text'].tolist()
spam_email = ''.join(spam_email_list)

 

from wordcloud import wordcloud,STOPWORDS

spam_email_list = spam['text'].tolist()
spam_email = ''.join(spam_email_list)

 

my_stopwords = STOPWORDS


my_stopwords.add('subject')
my_stopwords.add('us')


from PIL import Image
img = Image.open('spam.jpg')
img_mask = np.array(img)
wc = wordcloud.WordCloud(background_color='white', mask = img_mask ,stopwords = my_stopwords)


wc.generate(spam_email)


plt.figure(figsize = (10,6))
plt.imshow(wc)
plt.axis('off')


# 이미지 하나 저장하여, 구글 드라이브-작업하고 있는 경로에 업로드한다. 
# 업르드 하면, 자동으로 연동된다. 
# Image.open : 이미지를 가져온다. 
# 이미지는 컴퓨터가 바로 처리 못하니까, 넘파이 어레이로 바꿔준다. 
# 워드 클라우드 

 

반응형