minhui study

머신러닝의 이해와 지도학습을 이용한 분류(서포트 벡터 머신 알고리즘) 본문

Python/챗봇

머신러닝의 이해와 지도학습을 이용한 분류(서포트 벡터 머신 알고리즘)

minhui 2020. 7. 9. 19:40

서포트 벡터 머신 알고리즘

서포트 벡터 머신은 데이터 분포를 나누는 지도학습의 분류에 해당하며 지도학습 모델로서 라벨이 달린 이진 분류 문제에 주로 사용된다. 서포트 벡터 머신 알고리즘에서는 각 데이터 항목을 다차원의 벡터 공간에 점으로 표시한다. 

예를 들어 두 보기 중 하나의 보기를 선택하는 데 영향을 주는 요소가 2가지이면 2차원 모델이 된다. 이번 글에서는 이해하기 쉽도록 2차원 공간에 있는 두 그룹을 분류하다는 가정하에 서포트 벡터 머신을 알아볼 것이다.여기서 중요한 점은 밑에 그림들 처럼 두 그룹을 매우 잘 구분하는 직선을 찾는 것이다.

서포트 벡터 머신은 데이터를 선형 또는 비선형으로 분리하는 최적의 경계를 찾는 알고리즘이다.

http://hleecaster.com/ml-svm-concept/

 

 

서포트 벡터 머신의 동작 원리

첫 번째. 어떻게 구룹을 나눌 것인가?(직선을 그린다.)

두 개의 그룹을 분리하는 직선을 찾는 것이다. 이러한 직선을 통한 이진 분류 기법은 N개의 그룹으로 분류하는 문제를 쉽게 처리할 수 있다.

 

두 번째. 균형있게 나눈다. (마진 최대화)

한쪽에 치우치지 않게 양쪽 그룹 모두 균형 있게 나누려면 두 그룹을 구별하는 직선식을 구하되 직선식을 사이에 두고 가능하면 최대한 멀리 떨어지도록 점선을 구한다.

직선식에 가장 멀리 떨어진 이 거리를 '최대 마진'이라고 한다.

점선에 속한 점이 직선을 침법하지 않도록 만드는 안전지대 역할을 하고 지지대 역할을 한다고 해서 서포트 벡터라고 부른다.

https://medium.com/@unfinishedgod/

훈련이 진행됨에 따라 직선 사이의 거리인 마진이 최대가 되도록 직선을 조정하여 분류 간에 최대한 분리시키는 것이 서포트 벡터 머신이 추구하는 기본 사상이다.

 

 

 

서포트 벡터 머신을 이용한 당뇨병 분류

사이킷런을 설치하면 기본적으로 포함되어 있는 머신러닝 실습할 수 있는 데이터가 있지만 이번에는 위부에서 피마 인디언의 당뇨병 데이터 세트를 가져와 이용할 것이다.

피마 인디언의 당뇨병 데이터 세트는 총 768개 샘플로 구성되어 있고 각 샘플에는 8개의 측정값(나이, 임신 횟수, BMI 등)과 하나의 진단 결과 값 즉, 당뇨병 여부 값이 들어 있다. 0-7은 측정값이고 8번째 값은 당뇨병 유무이다. 1이면 당뇨병에 걸린것이다.

 

* 0 : 임신 횟수 1 : 혈당 농도 2 : 최저 혈압 3 : 삼두근 피하 지방의 두께 4 : 혈정 인슐린 농도  5 : BMI

6 : 당뇨병 혈통 요인  7 : 나이  8 : 당뇨병 양성 1, 음성 0

https://github.com/onlybooks/AI_begin/blob/master/chapter03/pima-indians-diabetes.csv

 

[ diabetes.py ]

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
# 표준화(모든 값을 0-1에 맞게 변환 또는 평균 0, 분산 1이 되도록 변환)
from sklearn.preprocessing import StandardScaler

#데이터 세트 로드 [ 1번 ]
pi_diabetes = pd.read_csv('pima-indias-diabetes.csv', header=None)

x=pi_diabetes.iloc[:, :8]
y=pi_diabetes.iloc[:, 8:].values.flatten() #1차원으로 전개 [ 2번 ]

print('x shape : {}, y shape : {}'.format(x.shape, y.shape))

#훈련 데이터와 테스트 데이터의 분리 [ 3번 ]
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=0)

#정규화를 위한 모듈 사용 [ 4번 ]
std_scl = StandardScaler()
std_scl.fit(x_train)
x_train = std_scl.transform(x_train)
x_test = std_scl.transform(x_test)

#학습 및 테스트 [ 5번 ]
svc = SVC()
svc.fit(x_train, y_train)

print('훈련 점수 : {: .3f}'.format(svc.score(x_train, y_train)))
print('테스트 점수 : {: .3f}'.format(svc.score(x_test, y_test)))

 

[1번] : 외부 데이터를 내려받는 코드로 이 데이터는 판다스의 read_csv()함수를 통해 읽어올 수 있다.

X는 0-7까지 768건이 있다.

 

[2번] : 판다스의 Dataframe은 기본적으로 행 인덱스와 열 인덱스를 가지고 있으므로 X에 0번부터 7번까지 데이터를 넣고 Y에 8번째 데이터를 넣고 배열로 나오는 결과를 flatten()함수를 이용해서 2차원을 1차원으로 전개했다.

 

[3번] : 사이킷런에서 제공하는 train_test_split()함수를 통해 훈련 데이터와 테스트 데이터로 분리한다. 훈련 데이터는 학습을 이용한 용도고 테스트 데이터는 모델이 잘 만들어졌는지 검증하는 용도이다.

 

[4번] : 8번째 항목을 제외하고 0-7번째 항목 수치의 범위가 각기 다르기 때문에 좀 더 학습을 최적화하기 위해서 정규화라는 기법을 사용한다. 즉, 모든 값을 0과 1 사이의 범위에 맞게 변환하는 작업이다.

 

[5번] : 원인에 해당하는 변수와 결과값(당뇨병 유무 1 또는 0)에 해당하는 변수를 fit이라는 함수에 넣으면 학습 완료

 

 

총 768개의 데이터를 가져오고 학습한 결과를 보면 훈련 점수는 82, 테스트 점수는 77점으로 비교적 만족할 만한 점수가 나왔다. 다른 머신러닝 기법에 비해 서포트 벡터 머신은 학습 속도가 비교적 빠르다고 할 수 있다.

 

정리하자면 SVM은 각 데이터가 그려진 공간에 경계를 만들고, 두 그룹으로 데이터를 분류하면서 이때 각 데이터와 경계 마진이 최대가 되게 하는 학습 알고리즘이다.

 

 

 

 

서포트 벡터 머신을 이용한 버섯 종류 분류

이번에는 독버섯 데이터를 이용하여 독버섯 여부를 분류해보자

훈련 데이터의 한 행은 각각 하나의 버섯을 나타내고 맨 왼쪽 첫 번째 문자가 독성의 유무를 나타내고 이후의 문자를 통해 모양과 색깔과 같은 특징을 나타내었다.

독성의 유무를 나타내는 것을 레이블로 정하고 그 이후 데이터들을 설명 변수로 활용하자

 

agaricus-lepiota.data

[mushroom.py]

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC

#데이터 세트 로드 [1번]
mushroom=pd.read_csv('agaricus-lepiota.data', header=None)

#문자를 수치로 치환 [2번]

X=[]
y=[]

for row_index, row in mushroom.iterrows():
    y.append(row.loc[0])
    row_X=[]
    for v in row.loc[1:]:
        row_X.append(ord(v)) # [3번]
    X.append(row_X)

#훈련 데이터와 테스트 데이터 나누기[4번]
x_train, x_test, y_train, y_test = train_test_split(X,y)

#학습 및 테스트[5번]
svc=SVC()
svc.fit(x_train, y_train)

print('훈련 점수 : {: .3f}'.format(svc.score(x_train, y_train)))
print('테스트 점수 : {: .3f}'.format(svc.score(x_test, y_test)))

[1번] : 외부 데이터를 내려받는 코드로 이 데이터는 판다스의 read_csv()함수를 통해 읽어올 수 있다.

 

[2번] : 이번 데이터는 문자로 이루어져 있으므로 분석하기 위해서는 숫자형으로 변환하는 전처리가 필요하다. 여기는 문자를 수치로 변환 처리하는 코드부이다. ( 인덱스 0은 y에 인덱스 1부터 끝까지는 X에 )

 

[3번] : ord() 함수는 하나의 유니코드 문자를 나타내는 문자열이 주어지면 해당 문자의 유니코드 코드 포인트를 나타내는 정수를 돌려준다. ex) ord('a') = 97

 

[4번] : 8번째 항목을 제외하고 0-7번째 항목 수치의 범위가 각기 다르기 때문에 좀 더 학습을 최적화하기 위해서 정규화라는 기법을 사용한다. 즉, 모든 값을 0과 1 사이의 범위에 맞게 변환하는 작업이다.

 

[5번] : 원인에 해당하는 변수와 결과값(당뇨병 유무 1 또는 0)에 해당하는 변수를 fit이라는 함수에 넣으면 학습 완료

 

 

버섯 훈련 데이터 집합은 갓 모양, 갓 표면, 서식지 등을 표함한 22가지 특징으로 이루어져 있고 목표 변수는 독성의 유무이다. 이 데이터 세트를 가지고 서포트 벡터 머신을 수행해 본 결과 특징이 더 많음에도 불구하고 당뇨병 예측 때보다 훨씬 더 높은 점수인 99% 점수를 얻었다.

 

2가지 실습을 해본 결과 과정은 대략 이러하다.

1. Classfier를 만들어준다.

2. 그 Classifier를 훈련데이터로 훈련시킨다.

3. 마지막으로 테스트를 하면 된다.

 

서포트 벡터 머신은 비교적 간단하면서도 강력한 모델이며 지도학습이 가능한 다양한 데이터 세트에서 잘 작동한다.

여기서 중요한 점은 데이터의 특징이나 해결하고자 하는 문제에 따라 적합한 알고리즘을 선택하기 위해 각 알고리즘의 특징과 활용을 이해할 필요가 있다.

 

 


 


<출처 또는 참고 자료>

실무가 훤히 보이는 머신러닝 & 딥러닝 ( 마창수, 최재철 지음 )

 

Comments