머신러닝

Naive Bayes 나이브 베이즈와 Vectorizing 벡터라이징을 이용한 스팸 분류 예시

HooSL 2022. 3. 29. 09:46

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

컬럼 : text, spam

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

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

 

구글드라이브 import

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

필요한 라이브러리 import

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
spam_df=pd.read_csv('/content/drive/MyDrive/위치/emails.csv')

 

스팸이면 1 이고, 아니면 0 입니다.

 

스팸은 몇개이고, 아닌 것은 몇개인지 확인하기

spam_df['spam']==1
spam_df['spam'].value_counts()
sns.countplot(data=spam_df,x='spam')
plt.show()

이메일의 길이가 스팸과 관련이 있는지 확인해보려고 합니다.

이메일의 문자 길이를 구해서, length라는 컬럼을 만듭니다.

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

 

글자 길이를 히스토그램으로 나타냅니다.

spam_df['length'].hist(bins=30)
plt.show()

 

가장 긴 이메일을 찾아서 스팸인지 아닌지 확인하고, 이메일 내용을 확인합니다.

spam_df['length'].max()

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

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

0은 스팸이 아니고, 1은 스팸입니다.

파이차트를 통해, 스팸과 스팸이 아닌 것이 몇 퍼센트인지, 소수점 1자리 까지만 보여줍니다.

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

plt.pie(spam_count,autopct='%.1f',labels=spam_count.index)
plt.legend()
plt.show()

 

스팸이 아닌 것은 ham 변수로 , 스팸인것은 spam 변수로 저장하겠습니다.

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

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

 

스팸의 이메일 길이를 히스토그램으로 나타내기

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

햄의 이메일 길이를 히스토그램으로 나타내기

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

 

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

문자열에는 필요없는 글자가 포함되어 있다마침표, 느낌표,물결표시등 ! 이런것을 punctuation (구두점) 이라고 합니다.이것을 먼저 제거합니다.

 

테스트 문장입니다.

Test = 'Hello Mr. Future, I am so happy to be learning AI now!~'
import string
string.punctuation
Test_punc_removed = []
for char in Test:
  if char not in string.punctuation:
    Test_punc_removed.append(char)
    
print(Test_punc_removed)

 

위의 리스트에 있는 문자들을, 하나의 문자열로 만듭니다.

''.join(Test_punc_removed)

Test_punc_removed_join =''.join(Test_punc_removed)
Test_punc_removed_join

 

STOPWORDS(불용어) 제거하기

STOPWORDS(불용어) 란?

https://dbfoot.tistory.com/172

 

Stopwords (불용어)

언어를 분석할때, stopwords 라는 용어가 나옵니다. stopwords 또는 불용어 란, 우리가 언어를 분석할 때, 의미가 있는 단어와, 의미가 없는 단어나 조사 등이 있습니다. 이렇게 의미가 없는 것들을 stop

dbfoot.tistory.com

import nltk

#불용어 다운로드
nltk.download('stopwords')

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

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

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)
    
print(Test_punc_removed_join_clean)

 

의미없는 글자도 제거 했으면 이제는 각 단어를 숫자로 바뚸줘야 학습할 수 있습니다.

단어를 숫자로 맵핑시키는 것을 벡터라이징 이라고 합니다. Vectorizing

레이블 인코딩(문자를 문자 순서대로 숫자로 변경)

from sklearn.feature_extraction.text import CountVectorizer

sample_data = ['This is the first document',
               'I loved them',
               'This document is the second document',
               'I am loving you',
               'And this is the third one']
               
Vectorizer = CountVectorizer()
X = Vectorizer.fit_transform(sample_data)

X=X.toarray()
Vectorizer.get_feature_names_out()

 

이제 우리의 데이터프레임에 있는, 이메일 내용을 Cleaning 합니다.

1. 구두점 제거 (글자 제거)

2. 불용어 제거 (단어 제거)

 

중요 이 두가지 작업을 하나의 함수로 만들어줍니다 : 파이프 라이닝

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. 문자열을 단어로 쪼개서, stopwords에 들어있는지 확인하여, 중요한 단어만 남긴다.
  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.')

 

카운트 벡터라이저의 애널라이저 파라미터 위의 구두점제거 + 불용어 제거하는 함수를 설정해주면 알아서 이 함수를 먼저 실행하고 나서 숫자로 바꿔줍니다.

Vectorizer = CountVectorizer(analyzer=message_cleaning)
X=Vectorizer.fit_transform(spam_df['text'])

학습을 위해서 X,y를 세팅해줍니다.

X는 넘파이 어레이여야 하므로, toarray() 함수 이용해서 넘파이로 가져옵니다.

X=X.toarray()

y=spam_df['spam']

 

나이브 베이즈 모델링

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()
classifier1.fit(X_train,y_train)
y_pred=classifier1.predict(X_test)

y_test
y_pred
from sklearn.metrics import confusion_matrix,accuracy_score
confusion_matrix(y_test,y_pred)
accuracy_score(y_test,y_pred)
classifier2 = GaussianNB()
classifier2.fit(X_train,y_train)
y_pred = classifier2.predict(X_test)
confusion_matrix(y_test,y_pred)
accuracy_score(y_test,y_pred)

 

문장 테스트 해보겠습니다.

testing_sample = ['Free money!!!', "Hi Kim, Please let me know if you need any further information. Thanks",'Hello, I am Ryan, I would like to book a hotel in Bali by January 24th', 'money viagara!!!!!']
X_sample = Vectorizer.transform(testing_sample)
X_sample = X_sample.toarray()
classifier1.predict(X_sample)