Notice
Recent Posts
Recent Comments
관리 메뉴

GIS & Spatial Analysis in KOREA

Support Vector Machine (SVM) - Code 본문

Machine Learning/Machine Learning Basic

Support Vector Machine (SVM) - Code

Borin78 2018. 9. 14. 08:00

[Machine Learning]

#Data Analysis #Spatial Data Analysis #Big Data #Data Visualization

#AI #Machine Learning #Supervised Learning #Support Vector Machine #SVM #Code

#데이터 분석 #공간데이터 분석 #빅데이터 #데이터 시각화 

#인공지능 #기계학습 #머신러닝 #지도 학습 #서포트 벡터 머신 #코드 



[ 서포트 벡터 머신 (Support Vector Machine, SVM) - Code ]


 

 

  Support Vector Machine(SVM)과 Naïve Bayes를 비교했을 때 어떤게 더 잘 작동할까? 학습 시간이 더 느리지 않을까? 등 궁금한 것들이 많이 있을 것이다. 앞으로 코딩을 연습하면서 하나씩 차근차근 이야기해보자. 만약 SVM 이론적 내용이 궁금하다면 이전 글을 가볍게 읽고 코딩을 연습해보자.


* 블로그 글을 읽는 것만으로도 모델 구현에 대한 충분한 아이디어를 얻을 수 있지만반드시 본인이 쓰는 파이썬 코드 편집기에서 코드를 연습해 볼 것을 강력 추천한다!!


0. 들어가기에 앞서……

   앞선 Naïve Bayes Classifier와 비교 분석을 위해 동일한 데이터(Spam & Non Spam email)를 이용할 예정이다. 만약, Naïve Bayes에 관한 내용을 읽어 보지 못했다면 다음 글(Naïve Bayes - ① 이론, ② Code)을 읽고 SVM을 연습하자.


   여기서는 학습 시간을 데이터 크기를 대략 원본의 10% 크기로 줄임으로써 적게 걸리게끔 하려고 한다. 그리고 조절 매개 변수(Tuning Parameter)를 이용해 정확도를 높여볼 것이며 Kernel, C, Gamma 변수의 변화에 따라 정확도와 시간이 어떻게 변하는지 살펴볼 예정이다.


1. 데이터 다운로드

첨부한 데이터를 다운로드 받는다.

Dataset.zip


2. 데이터 전처리

   이전 Naïve Bayes에서 진행했던 데이터 전처리와 동일하다. sklearn 라이브러리를 적용하려면 먼저 데이터를 전처리해야 한다. 데이터 전처리에는 Stop Words (분석에 영향을 주지 못하는 의미 없는 단어. 예) are, is, and, this, 등) 제거, 텍스트에서 가장 일반적인 단어 추출 등이 포함됩니다. 다음과 같이 진행된다.

① 학습용 데이터 셋 이메일에서 단어 사전을 만든다.

② 가장 일반적인 단어로 3,000자 정도로 만든다.

③ 각각의 학습용 데이터 셋 문서에서 각 단어에 대한 빈도수 행렬을 만들고 라벨을 일치시킨다. (스팸 메일의 파일이름은 ‘spmsg’라는 접두사로 시작한다.)


 

def make_Dictionary(root_dir):

   all_words = []

   emails = [os.path.join(root_dir,f) for f in os.listdir(root_dir)]

   for mail in emails:

        with open(mail) as m:

            for line in m:

                words = line.split()

                all_words += words

   dictionary = Counter(all_words)

   # if you have python version 3.x use commented version.

   # list_to_remove = list(dictionary)

   list_to_remove = dictionary.keys()


for item in list_to_remove:

       # remove if numerical. 

       if item.isalpha() == False:

            del dictionary[item]

        elif len(item) == 1:

            del dictionary[item]

    # consider only most 3000 common words in dictionary.

dictionary = dictionary.most_common(3000)


return dictionary


def extract_features(mail_dir):

  files = [os.path.join(mail_dir,fi) for fi in os.listdir(mail_dir)]

  features_matrix = np.zeros((len(files),3000))

  train_labels = np.zeros(len(files))

  count = 0;

  docID = 0;

  for fil in files:

    with open(fil) as fi:

      for i,line in enumerate(fi):

        if i == 2:

          words = line.split()

          for word in words:

            wordID = 0

            for i,d in enumerate(dictionary):

              if d[0] == word:

                wordID = i

                features_matrix[docID,wordID] = words.count(word)

      train_labels[docID] = 0;

      filepathTokens = fil.split('/')

      lastToken = filepathTokens[len(filepathTokens) - 1]

      if lastToken.startswith("spmsg"):

          train_labels[docID] = 1;

          count = count + 1

      docID = docID + 1

  return features_matrix, train_labels



3. SVC 적용하기

SVC에서 사용하는 코드는 Naïve Bayes 코드와 유사하다. 우선 SVC를 sklearn 라이브러리에서 불러온다. 그리고, 학습용 단어와 라벨을 추출한다. 마지막으로, 모델에 테스트 셋을 이용해 라벨을 예측해본다.


from sklearn import svm

from sklearn.metrics import accuracy_score


TRAIN_DIR = "../train-mails"

TEST_DIR = "../test-mails"


dictionary = make_Dictionary(TRAIN_DIR)


print "reading and processing emails from file."

features_matrix, labels = extract_features(TRAIN_DIR)

test_feature_matrix, test_labels = extract_features(TEST_DIR)


model = svm.SVC()


print "Training model."

#train model

model.fit(features_matrix, labels)


predicted_labels = model.predict(test_feature_matrix)


print "FINISHED classifying. accuracy score : "

print accuracy_score(test_labels, predicted_labels)



전체를 결합한 코드는 다음과 같다.

classifier.py


위에서 작성한 SVC는 가장 기본적인 구현이다. 조절 매개 변수(Tuning Parameter)의 기본값 (Kernel = linear, C = 1, Gamma = 1)을 가정한다.


학습시간을 단축시키는 방법

   학습 시간을 단축 시키는 방법으로는 우선 학습 데이터 셋의 크기를 줄이는 것이다. 원본 학습 데이터의 1/10로 줄였다고 얘기하고 정확도를 확인해야 한다. 물론 정확도가 감소할 것이다. 학습 데이터 셋을 줄이는 코드는 다음과 같다.


features_matrix = features_matrix[:len(features_matrix)/10]

labels = labels[:len(labels)/10]



조절 매개 변수(Tuning Parameter) 조정 방법

   지금까지 작성한 코드로는 아마 56%의 정확도를 얻었을 것이다. 이는 너무 낮은 수치이다. 학습 데이터 셋의 크기를 1/10으로 설정하면 Kernel, C, Gamma 세 가지 조절 매개 변수를 조정할 수 있다. 물론, sklearn tool kit에는 inbuilt 되어있는 함수가 있어 매번 조절 매개변수를 조정하지 않아도 된다.(추후 포스팅 예정)


1. Kernel

Kernel을 rbf로 바꿔보자. (SVM의 Kernel로는 다항커널(Polynomial Kernel), RBF(Radial Basis Function) 혹은 Gaussian Kernel, 시그모이드 커널(Sigmoid Kernel)이 있다.)


 

model = svm.SVC(kernel="rbf", C = 1)



2. C

C(Regularization Parameter) 값을 조정해보자. 값은 10, 100, 1000, 10000 중에서 택한다. 어느 값을 이용했을 때 정확도가 올라가는가? 아마, C = 100에서 정확도 점수는 85.38 %로 증가하고 그 이상의 값에서는 거의 동일하게 유지된다.


3. Gamma

마지막으로 Gamma 값을 조정해보자. 작성한 코드에 gamma = 1.0을 추가해보자.


model = svm.SVC(kernel="rbf", C = 100, gamma=1)



아마 정확도 값은 떨어졌을 것이다. Gamma 값으로 0.1, 0.01, 0.001을 사용해보자. 아마 gamma 값이 작을수록 정확도 값이 올라갈 것이다. 이는 데이터 값들이 듬성듬성 위치하고 결정 경계에서 멀리 떨어져 있음을 의미한다.


학습 데이터 셋을 줄여서 조절 매개 변수를 조정해 적용한 결과 아마 85.4%의 정확도를 얻을 수 있을 것이다.


--- Tip!! ---

   매번 코드를 작성해 실행시키면 데이터를 처음부터 다시 불러 들여오는 등 시간이 굉장히 오래 걸린다. 이 경우 데이터를 추출해 저장해 둔다면 좀더 빠르게 실행시킬 수 있다.


import cPickle

import gzip


def load(file_name):

    # load the model

    stream = gzip.open(file_name, "rb")

    model = cPickle.load(stream)

    stream.close()

    return model


def save(file_name, model):

    # save the model

    stream = gzip.open(file_name, "wb")

    cPickle.dump(model, stream)

    stream.close()


#To save

save("/tmp/features_matrix", features_matrix)

save("/tmp/labels", labels)

save("/tmp/test_feature_matrix", test_feature_matrix)

save("/tmp/test_labels", test_labels)


#To load

features_matrix = load("/tmp/features_matrix")

labels = load("/tmp/labels")

test_feature_matrix = load("/tmp/test_feature_matrix")

test_labels = load("/tmp/test_labels")



결론

   일반적으로 SVC는 Naïve Bayes보다 일반적으로 3배 정도 오랜 학습 시간을 필요로 하지만, 예측은 더 빠르다. 앞선 Naïve Bayes 결과와 SVC 결과를 비교해보면 Naïve Bayes의 성능이 더 우수한 것처럼 보인다. 하지만, 이는 전적으로 시나리오와 데이터 셋에 달려있다. 예를 들어, 신용카드 거래에서 99%의 정확도보다 신속하게 위조 결제에 대응하기 위해서는 90% 정도의 정확도만 빨리 얻을 수 있다면 예측이 빠른 모델을 활용할 것이다. 이와는 반대로, 이메일에서 스팸 메일을 걸러내는 경우 예측이 빠른 것 보다 정확도가 더 중요할 것이다.


- 끝 -



Comments