본문 바로가기

카테고리 없음

분류 문제를 위한 머신러닝 알고리즘에는 무엇이 있을까?

👾분류 문제를 위한 머신러닝 알고리즘👾

 

최근 sLLM 분야와 관련한 프로젝트를 위한  학습을 진행해야하기도 했하, 머신러닝 수업을 들으면서

관련 분야에 대한 공부와 기본적인 머신러닝 알고리즘에 대한 공부 또한 함께 진행하고 있는데요,

 

머신러닝을 공부하면서 관련 알고리즘과 개념을 스스로도 분명히하고, 이해하기 쉽게 글을 포스팅하여

새로운 머신러닝 입문자분들과 경험을 공유하면 좋겠다는 생각에 포스팅을 올리게 되었습니다:)


 

 머신러닝에서 분류는 가장 기본적이면서도 중요한 작업중 하나입니다.

 

일상에서 마주치는 많은 문제들을 해결할 수 있도록 도움을 주기도 하죠!

이메일이 스팸인지 아닌지 구분하거나, 의료 진단을 통한 질병을 예측하는 등 실생활의 문제를 

해결하기 위해 머신러닝 분야에서는 다양한 분류 알고리즘을 개발했습니다.

 

이번 포스팅에서는 그 중 널리 사용되는 세가지 알고리즘인 Decision Trees, K-Nearest Neighbor, SVM에 대해 

간단한 설명과 함께 실습을 통해 dataset을 불러와 직접 분류를 진행해보고자 하는데요,

 

각 알고리즘의 작동 원리와 장단점에 대해 살펴보며 머신러닝 분류 알고리즘에 대해 소개해보도록 하겠습니다!

 

 

[목차]

  • Decision Tree
  • K-Nearest Neighbor
  • SVM(Support Vector Machine)

 

위 세 알고리즘은 모두 Supervised Learning Algorithm이라는 특징을 가지고 있는데요,

데이터 형태가 X->y 형태로 라벨링된 데이터로 output을 얻기 위한 y=f(x)와 같은 모델을 가지며 

분류 및 예측에 사용되는 모델입니다.

 

그 외 머신러닝 알고리즘의 범주는 아래와 같이 크게 세가지로 나뉘어집니다.

Supervised Learning 데이터 형태가 X->y 형태로 라벨링된 데이터이다. Output 을 얻기 위한 y=f(x) 와 같은 모델을 갖는다. 분류 및 예측에 사용된다.
Unsupervised Learning : X->y 형태의 데이터가 아닌, input 에 대한 클러스터링을 수행하는 unlabeled data 이다. 클러스터링과 확률 분포에사용된다.
Reinforcement Learning action 에 대응하는 reward 를 축적하며, 좋은 방향으로의 행동 방식을 습득하는 학습 방식이다.

 

 


 

1) Decision Tree 알고리즘

출처: scikit-learn.org

결정트리는 결정 규칙을 나무 구조로 나타내며, 각 노드는 속성에 대한 질문(분기를 위한 결정)을 나타내고,

각 가지는 해당 속서의 결과(예/아니오)를 나타내는 모델입니다.

 

데이터 포인트가 트리 루트에서 시작해 여러번에 걸친 분기를 통해 같은 class에 속한 data끼리 남을 때까지

트리를 분기하며 형성합니다. 

 

하지만 모든 결정트리 모델이 noise없이 완벽히 데이터를 분류하지는 못하므로 트리에 대한 적절한 depth를 지정해

과적합(overfitting)되지 않는 모델을 생성하는 것이 중요한 요소 중 하나입니다.

 

여기서 과적합이란, training data 에 대한 정확도가 너무 높아지면서, 오히려test data 나 다른 일반적인 입력데이터에 대한 적합성이 떨어지는 경우를 말합니다 :)

 

백문이 불여일견이므로, 실습을 통해 decision tree 모델을 생성하고, test data에 대한 분류를 수행하는 과정을 

실습해보겠습니다!

 

 

heart_disease.csv 파일을 불러왔습니다. hd[num]이 우리가 예측할 심장병 유무에 대한 양성/음성을 나타내는 결과이고

다른 속성값들을 바탕으로 심장병이 양성인 data가 어떤 특성을 띄는지를 학습하여 심장병 유무 판단 분류 모델을 학습해보도록 하겠습니다!

#pandas, numpy 라이브러리 import
import pandas as pd
import numpy as np

#data 불러오기
hd = pd.read_csv('heart_disease.csv')

#target data를 0 or 1로 변환
hd['num'] = hd['num'].apply(lambda x:1 if x>=1 else 0)
hd

 

 

 

 

 

해당 데이터셋을 decisiontree 모델에 학습시키기 위해 X, y데이터를 분리하고

training에 사용할 데이터셋(70%)과 test에 사용할 dataset(30%)을 분류해주었습니다.

#X는 target 데이터를 제외한 나머지 속성값들
X = hd.iloc[:, :-1]
#y는 [0, 1]로 이루어진 class label
y = hd['num'].astype(np.int32) # type cast


from sklearn.model_selection import train_test_split

# 297개의 데이터에 대해 70%는 훈련용 데이터, 30%는 테스트용 데이터로 split함. 
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3, random_state=1, )

 

 

파이썬 머신러닝의 대표적인 라이브러리인 scikit-learn은 decisionTree에 대한 복잡한 알고리즘을 직접 설계하지 않아도,

모듈을 가져와 dataset을 넣어 훈련시켜볼 수 있는데요,

 

tree모델에 X_train, y_train 데이터를 넣어 학습시켜보았습니다.

이제 학습된 모델을 시각화하여 어떻게 생성되었는지 살펴봅시다!

from sklearn.tree import DecisionTreeClassifier

# learn decision tree with training dataset. try various depth of tree
tree = DecisionTreeClassifier()
tree.fit(X_train, y_train);

 

 

아래 사진과 같은 decision tree 모델이 학습되었네요!

from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

# hd.columns for feature names and ['no', 'yes'] for class names
plt.figure(figsize=(50,30))
plot_tree(tree, feature_names =hd.columns[:-1], class_names=['no','yes'], filled=True)

plt.show()

 

 

 

이제 test data에 대한 accuracy를 한번 측정해보도록 하겠습니다.

모델이 정확도 높게 잘 만들어졌는지 확인하기 위해서요!

 

# train and test accuracy of the model. use .score(X, y)
train_score = tree.score(X_train, y_train)
test_score = tree.score(X_test, y_test)

print("Train Accuracy : ", train_score)
print("Test Accuracy : ", test_score)

test data에 대한 accuracy가 0.7이 나왔습니다. 흠 그렇게 높은 정확도라고 볼 순 없겠네요.

 

정확도를 더 높일 수 있는 방법이 무엇이 있을까요?

위에서 말했던 과적합을 방지하기 위한 트리의 최대 dpeth를 지정하는 방법도 있을 것이고,

어떤 속성을 먼저 분기하느냐에 따라 달라지는 결정트리 모델의 예측을 종합함으로써 예측 정확도를 높일 수도 있습니다!

 

 

해당 작업을 수행하기 위해 Random Forest라는 학습 방법을 사용할 수 있는데요, 이를 통해 accuracy를 증가시킬 수 있을 지 직접 실습해보도록 합시다!

 

 

max_depth는 3으로 설정하고 n_estimator(결정트리 개수)는 100개로 지정하여 모델을 재학습해보도록 하겠습니다.

from sklearn.ensemble import RandomForestClassifier

# learn forest of 100 decision trees of depth 3
forest = RandomForestClassifier(n_estimators=100, max_depth=3, random_state=1)
forest.fit(X_train, y_train)

 

 

test data 모델 예측 정확도가 약 0.16정도 증가한 모습을 확인할 수 있습니다!
train data에 대한 정확도는 아까의 경우가 더 높지만 우리에게 중요한 것은 일반적인 test dataset에 대해

옳은 예측을 하는 디시젼 트리를 만들어내야 하므로 성공적인 시도라고 말할 수 있겠네요(⋆ˆ ³ ˆ)♥

print('Train Accuracy: ', forest.score(X_train, y_train))
print('Test Accuracy: ', forest.score(X_test, y_test))

 

 


 

2) K-NN Classifier

K-NN 분류알고리즘은 입력 데이터 포인트가 주어지면, 데이터 포인트에서 가장 가까운 'K'개의 이웃을 찾고,

이 이웃들의 분류 레이블을 기반으로 예측을 수행하는 모델입니다.

매우 간단하고 직관적으로 이해하기 쉬운 알고리즘이지만, 대규모 데이터 세트에 대해서는 계산 비용이 높을

수 있다는 점을 고려해야합니다!!

해당 알고리즘 또한 실습을 통해 직접 경험해보도록 하죠!

 

 

n_neighbors = 6으로 가장 가까운 이웃의 수를 9로 지정하였고, p=2로 설정하여 직선거리 계산시 유클리드 거리(두 포인트간의 직선거리)를 계산하도록 하였습니다.

from sklearn.neighbors import KNeighborsClassifier

# learn the k Nearest Neighbor classifier. k = 5. p = 2. 
knn = KNeighborsClassifier(n_neighbors=9, p=2)
knn.fit(X_train, y_train);

 

앗, KNN 같은 거리 기반 알고리즘에서 매우 중요한 것을 빠뜨릴 뻔 했네요!

데이터셋의 특성들이 서로 다른 스케일의 값을 가지고있을 경우, 거리계산에 있어 스케일이 큰 특성이 결과에 더 큰 영향을 미칠 수 있습니다. 그렇기 때문에 데이터 정류화를 통해 모든 특성이 동등한 중요도를 갖도록 해주겠습니다.

 

from sklearn.preprocessing import StandardScaler

# X_train 정규화
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)

 

 

정규화된 X_train을 넣어 재학습 시킨 KNN 모델의 정확도를 이전과 비교해보고 모델이 올바른 방향으로 학습되었는지

확인해보도록 하겠습니다.

from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=9, p=2)
knn.fit(X_train_std, y_train)

정규화 이전
정규화 이후

확실히 정규화 이전보다 높은 정확도를 보이는 것을 확인할 수 있었습니다!

각 알고리즘 계산 방식의 특성을 잘 파악해서 데이터의 스케일이 무관한지 아닌지를 판단해

잊지 않고 정규화를 필요할 때 수행해주는것도 모델 성능에 커다란 영향을 미친다는 점을 기억해야합니다!

 

결정트리 모델에 대해서도 너무 과적합된 모델인 경우, outlier에 대한 것들을 좀 쳐내기 위해서

max_depth를 설정해 적절한 pruning을 진행해주는 것도 성능을 향상시키는데 도움이 된다는 점을 배워갈 수 있었습니다:)

 

 


 

3) SVM(Support Vector Machine)

포스팅이 생각보다 길어지고 있는데, 이제 마지막으로 SVM 모델에 대해 알아보는 시간을 가져보도록 하겠습니다.

SVM은 support vector machine의 약어로, 분류와 회귀 모델에 사용될 수 있는 강력한 선형 모델입니다.

해당 알고리즘은 데이터를 두 클래스로 가장 잘 분리하는 결정 경계를 찾는 것을 목표로 하는 모델입니다.

svm을 사용하면 고차원 공간에서 선형분리를 가능하게 하는데요, 이걸 대체 어떻게 하는걸까요?

평면상의 공간에서는 선형으로 분리할 수 없을 것 같은 두 클래스를 

3차원 시각의 데이터로 바라보아 분리해줄 수 있습니다. 

바로 아래와 같은 Gaussion Radial Basis Function Kernel 함수를 이용하면 말이죠!

해당 커널함수는 입력데이터를 고차원 특성 공간으로 매핑하는 비선형 함수입니다.

아래 그림과 같이 고차원 공간에서 데이터가 선형적으로 분리될 수 있게 합니다.

 

 

 

rbf 커널을 가진 서포트벡터머신을 훈련하는 코드인데요,

gamma의 값이 높아질수록 개별 데이터포인트가 결정경계에 미치는 영향이 커져 더 세밀한 결정경계를 만들어줍니다.

하지만, overfitting이 일어날 수 있어 gamma값이 무조건적으로 크다고 좋은것은 아니므로 적절한 값을 잘 선택해야 합니다.

C는 모델 마진오류의 허용 정도를 결정합니다. C값이 높을수록 마진 오류를 덜 허용하여 잘못 분류된 데이터 포인트에 대한 허용 범위가 좁아져 overfitting을 일으킬 가능성이 있기때문에 이 또한 적절한 값을 잘 조정하여 사용해야합니다!

from sklearn.svm import SVC

svm = SVC(kernel='rbf', random_state=0, gamma=0.2, C=1.0)
svm.fit(X_train, y_train)

 

결정경계를 긋고, 분류된 모델을 시각화하였더니 아래와 같은 결과가 도출되었습니다!!

# plot decision boundary of the model 
plot_decision_regions(X_train, y_train, classifier=svm)
plt.show()

SVM

 

 

같은 데이터에 대해 위에서 실습해본 Decision Tree와 KNN 알고리즘으로 학습된 모델에 대해서도 시각화를 해보았는데요,(1. KNN, 2. Decision Tree)

KNN
Decision Tree(max_depth = 4로 설정)

 

 

지금까지 머신러닝에서의 대표적인 분류 알고리즘들에 대해 배워보고 실습해보는 시간을 가져보았습니다!

 

최근 sLLM 분야와 관련한 프로젝트에 참여하게 되었기도 하고, 머신러닝 수업을 들으면서

관련 분야에 대한 공부와 기본적인 머신러닝 알고리즘에 대한 공부 또한 함께 진행하고 있는데요,

 

머신러닝을 공부하면서 관련 알고리즘과 개념을 스스로도 분명히하고, 이해하기 쉬운 방식으로 글을 포스팅하며

새로운 머신러닝 입문자분들과 경험을 공유하면 좋겠다는 생각에 포스팅을 올리게 되었습니다.

 

앞으로도 관련 학습분야에 대한 포스팅 정리글 또한 종종 올리려고 생각중에 있습니다.

긴 글 읽어주셔서 감사합니다:)