2021년도에 대학교 과목으로 들었던 '기계학습' 강의를 복습 및 정리 + 추가적인 공부를 위해 이 글을 작성한다. (세종대학교 최유경 교수님 '2021 기계학습'수업)
저번 파트에 이어서 이번에도 지도학습의 학습 모델 중 판별 분석(Discriminant Analysis)에 대해 알아본다.
판별 분석(Discriminant Analysis)은 이전 파트에 배웠던 로지스틱 회귀 모델과 같이 예측 모델을 만들고 이 모델의 파라미터를 추정하여 예측을 진행한다. 하지만 로지스틱 회귀 모델과 달리 데이터의 관계를 잘 표현하는 함수를 학습하는 것이 아닌 데이터의 분포를 잘 표현하는 함수를 학습한다.
판별 분석(Discriminant Analysis)
이론
선형 판별 분석과 이차 판별 분석이 구분되지만 대표적인 선형 판별 분석을 기준으로 판별 분석을 설명
판별 분석은 두개 이상의 모 집단(집단의 전체)에서 추출된 표본(관찰된 결과의 집합)들이 지니고 있는 정보(분포)를 이용하여 이 표본들이 어느 모집단에서 추출된 것인지를 결정해 줄 수 있는 기준을 찾는 분석법이다. 즉, 두개 이상의 범주를 구분해주는 기준을 찾는 분석법이라고 생각하면 된다. 예시를 통해 확인해보자.
이 예시에서 두가지 표본을 LD1, LD2라는 사영축에 사영시킨 후 이 둘 중 어떤 사영축이 데이터를 잘 구분하는지 확인해보자. 먼저 LD1에 사영된 데이터의 분포를 통해 이 둘을 구분할 수 있는 기준을 설정할 수 있다는 것을 알 수 있다. 하지만 LD2같은 경우 이 두 범주를 구분해줄만한 판별 정보(분포)가 없기에 이를 통해서는 이 두 범주를 구분할 수 있는 기준을 잡을 수 없다는 것을 알 수 있다. 즉, 좋은 기준을 가진 사영축은 LD1이라고 볼 수 있는 것이다. (이러한 LD1, LD2를 선형 판별 벡터라고 부름)
결국 이 판별 분석의 핵심은 더 좋은 선형 판별 벡터(사영축, LD1)을 나타내는데에 사용되는 판별 변수(discriminant variable)를 찾는 것이다. 판별 변수란, 어떤 집단에 속하는지 판별하기 위한 변수로서 독립 변수 중 판별력이 높은 변수이다. 이러한 판별 변수를 결정하는데에는 판별 기여도 뿐만 아닌 '다른 독립 변수들과의 상관관계' 또한 중요하다. 상관관계가 높은 두 독립변수를 선택하는 것보다는 두 독립변수 중 하나를 판별 변수로 선택하고 그것과 상관관계가 적은 독립변수를 선택함으로써 더욱 효과적인 판별 함수를 만들 수 있다.
이제 이런 다양한 변수들(특성, X)을 측정하고 이 변수들을 이용하여 각 집단을 가장 잘 구분해 낼 수 있는 판별식을 만들어 분별해주는 과정이 필요할 것이다. 이 역할을 하는 것이 바로 판별 함수(Discriminant function)이다. 즉, 판별 함수를 이용하여 각 개체들이 얼마나 잘 판별되는가에 대한 판별력을 측정하고 학습에 사용되지 않은 새로운 대상을 어느 집단으로 분류할 것이냐를 판단하게 된다. 판별함수는 판별 점수(Discriminant score)를 통해 결정된다.
결국 판별함수는 여타 다른 다양한 기계학습 방법론의 학습의 대상이 되는 그 함수라고 생각하면 된다.
이런 판별 분석에서의 표본의 크기는 다른 학습 모델들 보다 더 중요하게 여겨진다. 판별 분석을 이용하기 위해선 전체 표본의 크기가 통상적으로 독립변수(Feature Engineering을 통해 나온 변수)의 개수보다 3배(최소 2배)이상 되어야 하고 판별력을 좌우하는 것이 결국 가장 적은 집단의 표본의 수이기 때문에 종속변수(Y, 범주)의 집단 각각의 표본의 크기 중 최소 크기가 독립변수(특성, X)의 개수보다 커야된다.
(Feature Engineering: 모델 정확도를 높이기 위해서 주어진 데이터를 예측 모델의 문제를 잘 표현할 수 있는 features로 변형시키는 과정)
그럼 판별 분석은 어떤 과정을 거쳐 진행될까?
먼저, 집단을 구분하는데 기여할 수 있는 독립 변수(특징 분석을 통해)를 찾는다. 그 후 집단을 구분하는 기준이 되는 독립 변수들의 선형 결합 즉, 판별 함수를 학습을 통해 도출한다. 이렇게 도출된 판별 함수를 통해 분류의 정확도를 측정(학습 데이터 이용)하고 분석하며 마지막으로는 판별함수를 이용하여 새로운 케이스(검증 데이터)가 속하는 클래스를 예측하여 가장 잘 예측하는 판별 함수를 도출해 낸다.
판별 분석의 과정에서 알 수 있다시피 판별분석은 결국 판별과 차원 축소 두가지 기능이 있다. 2차원(두 가지 독립변수)의 두 가지 범주(주황, 파랑)를 갖는 데이터를 분류하는 문제를 통해 이 두가지 기능을 확인해보자.
해당 사영축을 통해 2차원자료들을 1차원에 정사영 시켜 이 둘의 분포의 형태를 고려하고 점선(결정 경계)을 통해 분류하는 것을 볼 수 있다. 즉, 데이터의 분포를 2차원에서 1차원으로 축소(차원축소)하고 판별을 진행하는 것을 통해 두가지 모두를 진행하고 있는 것을 볼 수 있다.
그럼 앞서 말한 결정 경계(점선)에는 어떤 특징이 있을까?
결정 경계는 사영 축에 직교하는 축이며 사영축을 기준으로 각 클래스 집단의 평균의 차이가 크고 분산이 작은 지점이 결정경계로 지정된다. 즉, 최적의 판별함수를 찾고 이를 바탕으로 분산 대비 평균의 차이를 극대화 하는 결정경계를 찾는 것이 판별 분석의 목적인 셈이다. 예시를 통해 어떤 결정 경계가 더 좋은 결정 경계인지 확인해보자.
이 둘 중 더 좋은 결정 경계는 결국 평균의 차이가 크고 분산이 작은 2번째 결정 경계라는 것을 알 수 있다. (TIP: 사영 데이터의 분포에서 겹치는 영역이 작은 결정경계가 더 좋은 결정경계)
이런 판별 분석은 각 클래스 집단의 공분산(covariance) 구조가 비슷하냐 비슷하지 않냐에 따라 선형 판별 분석(LDA: Linear Discriminant Analysis)과 이차 판별 분석(QDA: Quadratic Discriminat Analysis)으로 나뉘게 된다.
(공분산: 2개의 확률변수(독립변수)의 상관 정도를 나타내는 값)
1. 선형 판별 분석 (Linear Discriminant Analysis)
선형 판별 분석은 각 클래스 집단이 정규 분포형태의 확률분포를 가지고 비슷한 형태의 공분산 구조를 가지는 데이터에 대해서만 다룬다는 가정을 두고 시작한다.
이 선형 판별 분석은 변수 간 공분산 구조를 반영하고 그 구조 가정(비슷한 공분산 구조)이 조금 위반되더라도 비교적 견고(Robust)하게 동작한다는 장점이 있지만 가장 작은 그룹의 샘플 수가 설명변수의 개수보다 많아야하고 정규분포를 크게 벗어나는 분포일 경우 잘 동작하지 못한다는 한계를 가지고 있다. 마지막으로 범주 사이에 공분산 구조가 크게 다른 경우를 반영하지 못한다. 이런 한계를 해결하기 위해 이차판별분석(QDA)이 나오게 된 것이다.
2. 이차 판별 분석(QDA)
이차 판별 분석은 앞서 말한 것과 같이 범주의 수와 관계없이 공통 공분산 구조에 대한 가정을 만족하지 못하면 적용하게 된다. 즉, LDA에서의 선형인 결정경계로 분류할 수 없는 범주들(다른 공분산 구조)을 비선형 결정 경계로 분류를 가능하게 한 것이다. (단, LDA도 같은 공분산의 비선형 분류는 가능, 변수의 제곱을 한 추가적인 변수들을 통해 가능하게 함)
하지만 QDA는 서로 다른 공분산 데이터 분류를 위해 많은 샘플을 요구한다. 즉, 연산량이 커지게 된다.
마지막으로 QDA의 예시를 통해 QDA를 확인해보자.
서로 다른 공분산 구조를 가지고 있기에 QDA를 통해 비선형 분류를 진행한 결과이다.
실습
이번 파트도 part1에서 사용했던 iris데이터를 사용한다. [참고]
(이전에 진행했던 부분이기에 자세한 설명은 생략)
# 데이터 로드 및 데이터 분리(input, output)
import seaborn as sns
iris = sns.load_dataset('iris') # iris data
x = iris.drop('species',axis=1) # input
y = iris['species'] # output
iris.head(3)
# 텍스트 및 범주형 자료 실수화
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
new_y = le.fit_transform(y)
set(new_y) # -> {0, 1, 2}
# 학습데이터 및 검증데이터 분리
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = \
train_test_split(x,new_y, test_size=0.3, random_state=11, stratify=new_y)
print('Train :',x_train.shape) # -> Train : (105, 4)
print('Test :',x_test.shape) # -> Test : (45, 4)
1. 선형판별분석(LDA)
학습 모델 LDA는 기본적으로 우리가 계속 사용했던 sklearn 라이브러리에서 제공한다.
# LDA 호출 및 학습
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis #LDA 호출
lda = LinearDiscriminantAnalysis() # LDA 선언 및 하이퍼 파라미터 설정
# Default => store_covariance = False // n_components = 2 -> (n_components: min(n_classes-1, n_features))
LDA = lda.fit_transform(x_train,y_train) # 추후 그래프로 그리기 위한 설정
여기서 중요한 부분은 LDA의 인자이다. LDA도 다양한 인자를 가지고 있지만 신경써야할 인자는 n_components 정도라고 생각하면 된다. 또한, n_components마저 최적의 Default값을 제공하기에 다른 학습 모델과는 다르게 크게 설정할 부분이 없다. n_components는 이론에서 설명했던 축소할 차원(1,2,3, ... )이다. 축소할 차원은 각 클래스를 분류하기 위해 당연히 클래스의 개수보다 작아야 되며(n_classes-1) 설명변수의 개수(n_features)보다 크면 안될 것이다. 이를 Default값으로 설정한 것이다. 물론 이 Default값이 최적의 하이퍼 파라미터는 아닐 것이다. 하지만 보통 해당 Default값으로 학습이 잘 되기에 해당 Default값을 사용한 후 실험적으로 수정해나가는 것을 추천한다.
# 학습 결과 확인 (학습데이터를 통한 점수, 검증데이터를 통한 점수)
# accuracy_score 성능평가 방법 사용
print('Train Score :', lda.score(x_train, y_train))
print('Test Score :', lda.score(x_test,y_test))
지금까지 진행했던 학습 모델들 중 가장 좋은 성능을 냈다는 것을 확인할 수 있었다. 결국 이 데이터의 각 범주들은 비슷한 공분산 구조를 가지고 정규분포의 형태를 띄고 있다는 결과를 얻을 수 있는 것이다.
마지막으로 설정된 선형 판별 벡터에 따른 데이터를 확인해보자. [시각화]
# 결과 시각화
import matplotlib.pyplot as plt
plt.xlabel('LD1')
plt.ylabel('LD2')
plt.scatter(
LDA[:,0], #LD1
LDA[:,1], #LD2
c = y_train,
cmap='rainbow',
alpha=0.7,
edgecolors='b')
해당 그래프를 통해 판별 분석 모델이 클래스 분류를 위해 LD1과 LD2을 생성했다는 것을 알 수 있고, 또한 두 선형 판별 벡터 중 LD1이 더 좋은 선형 판별 벡터라는 것을 우린 인지할 수 있다. 결국 학습의 결과인 최적의 판별함수는 LD1이며 이 판별함수를 통해 검증데이터를 평가할 때 100%라는 accuracy를 얻게 된 것이다.
2. 이차판별함수(QDA)
QDA도 LDA와 똑같은 방식으로 실습이 진행된다.
# QDA 호출 및 학습
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
qda = QuadraticDiscriminantAnalysis()
# Default => store_covariance = False // n_components = 2 -> (n_components: min(n_classes-1, n_features))
#x_qda = qda.transform(x_train, y_train) #QDA는 transform이 없음. 그래서 그래프로 표현 불가
qda.fit(x_train, y_train)
# 학습 결과 확인 (학습데이터를 통한 점수, 검증데이터를 통한 점수)
# accuracy_score 성능평가 방법 사용
print('Train Score :',qda.score(x_train,y_train))
print('Test Score :',qda.score(x_test, y_test))
LDA보다 학습은 잘되었으나 일반화가 부족한 모습을 볼 수 있었다. 하지만 설정되는 학습데이터와 검증데이터에 따라 항상 다르다. 하지만 적어도 이 iris 데이터는 LDA와 QDA 모두 적용해도 분류가 잘 되는 것을 알 수 있다.
'공부 > 기계학습 및 인공지능' 카테고리의 다른 글
Machine Learning (기계학습) - part 6 [SVM (Support Vector Machine)] (0) | 2022.01.12 |
---|---|
Machine Learning (기계학습) - part 5 [의사결정나무(Decision Tree)] (0) | 2022.01.11 |
Machine Learning (기계학습) - part 3 [로지스틱 회귀(Logistic Regression)] (0) | 2022.01.06 |
Machine Learning (기계학습) - part 2 [지도학습, KNN(K-Nearest Neighbor)] (0) | 2022.01.06 |
Machine Learning (기계학습) - part 1 [기계학습, 데이터] (0) | 2022.01.04 |