🛑

붓꽃 데이터는 이제 그만 - 차원축소 쉽게 이해하기 (PCA, LDA)

언제까지 붓꽃 데이터로만 차원축소를 공부할텐가! 조금 더 구체적인 예시로 차원축소를 이해해보자.
주의!
이번 포스팅의 LDA는 토픽모델링의 LDA(Latent Dirichlet Allocation) 개념이 아닌, 차원축소의 LDA(Linear Discriminant Analysis) 개념을 다룹니다.
머신러닝 개념이 백지에 가까우면 포스팅의 이해가 어려울 수 있습니다 (최대한 쉽게 서술하긴 했습니다)
목차

"머신러닝을 공부하면서 처음 차원축소를 알게 되었어요"

문과 공부를 하면 응용통계학, 사회과학대학 소속이 아닌 이상, 차원축소 개념을 접할 기회가 흔치는 않습니다.
하지만 머신러닝을 공부하면 알고리즘 성능 향상을 위해 얄짤 없이 공부해야 하는데...
뭘 축소해?
시판 머신러닝 교재에서는 잠재요소 개념을 통해 차원축소를 이해시키는 한편,
예시 데이터로서 자꾸만 붓꽃 데이터를 활용하길래 뭔가 아쉬워서 새로운 데이터로 알아보았습니다.

잠재요소로 차원축소 간단히 이해하기

이미 알고 있는 분들은 넘어가셔도 좋습니다

차원축소 알고리즘인 PCA와 LDA를 알아보기

1.
차원축소를 배우게 되면 PCA 기법과 LDA 기법을 대표적으로 공부하게 됩니다.
둘은 매우 유사하지만, LDA가 보다 "분류"에 최적화되어 있는 차원축소 기법이라 이해하면 쉽죠.
보다 자세한 설명 보기
2.
붓꽃 데이터로 차원축소 해보기 - "4차원은 그래프로 표현할 수 없으니 2차원으로 가자!"
*사이킷런 패키지의 PCA, LDA 클래스를 사용하며, 사이킷런 기본 내장 데이터인 iris(붓꽃) 데이터를 사용합니다.
붓꽃 데이터란 꽃잎의 크기와 꽃받침의 크기를 바탕으로 (피쳐 4개) 3개의 꽃 품종을 맞추는 데이터입니다.
원래는 피쳐(꽃에 대한 정보_꽃잎 크기 등)가 4개이므로 4차원입니다.
하지만 4차원을 그래프로 표현하는 건 쉽지 않겠죠?
따라서 2개 차원으로 축소해 x축 y축에 놓고 그래프로 표현해보는 게 기본적인 실습 내용입니다.
코드 보기
코드를 돌리면 다음과 같이 꽃품종 3종이 2차원으로 표현되었습니다.
3개의 다른 색 점이 물리적으로 잘 떨어져있음이 느껴집니다.

키와 허리둘레 데이터를 하나의 데이터로 차원축소하기

조금 더 실생활에 익숙한 데이터로 접근해봅니다.
가 크고 허리둘레가 큰 사람은 어떤 사람일까요?
덩치가 큰 사람! 이라고 표현할 수 있습니다.
허리둘레라는 측정 가능한 데이터로 덩치 라는 측정 불가능한 잠재 요소를 형성하는 것입니다.
그렇다면 남자와 여자 중 덩치가 상대적으로 큰 그룹은 어디일까요?
남자 그룹쪽으로 덩치 값이 더 크게 나타나지 않을까요?
데이터와 코드로 이를 구현해봅시다.
# 데이터는 2016년 건강검진 데이터를 기반으로 합니다. 데이터 로딩 코드는 아래를 바로 사용하세요. import pandas as pd import numpy as np import matplotlib import matplotlib.pyplot as plt # 파이플롯 사용 from IPython.display import set_matplotlib_formats import seaborn as sns sns.set_style('whitegrid') set_matplotlib_formats('retina') # 한글코드를 더 선명하게 해주는 조치, 레티나 설정 matplotlib.rc('font', family='AppleGothic') # 폰트 설정 matplotlib.rc('axes', unicode_minus=False) # 마이너스 폰트가 깨지는 경우가 있으므로 조치 df = pd.read_csv("https://raw.githubusercontent.com/TaewoongKong/code_sharing/master/2016%E1%84%82%E1%85%A7%E1%86%AB_%E1%84%80%E1%85%A5%E1%86%AB%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%A5%E1%86%B7%E1%84%8C%E1%85%B5%E1%86%AB_%E1%84%83%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%90%E1%85%A5.csv") df.head()
Python
복사
위 데이터에서 성별 신장 허리둘레를 가져다가 쓸겁니다.
df = df[['허리둘레', '신장(5Cm단위)','성별코드']] df.columns = ['waist', 'height', 'sex'] # 남녀 구분을 하고 df_man = df.loc[df['sex'] == 1] df_woman = df.loc[df['sex'] == 2] # 분포가 어떤지 시각화 해봅니다. # x 축에는 허리둘레, y축에는 키를 넣었습니다 f, ax = plt.subplots(figsize=(8, 8)) ax.set_aspect("equal") ax = sns.kdeplot(df_man.waist, df_man.height, cmap="Reds", shade=False, shade_lowest=False, cbar=False) ax = sns.kdeplot(df_woman.waist, df_woman.height, cmap="Blues", shade=False, shade_lowest=False) red = sns.color_palette("Reds")[-2] blue = sns.color_palette("Blues")[-2]
Python
복사
빨간색은 키가 큰 편이고 허리둘레도 파란색 분포에 비해 높은 편입니다.
덩치가 상대적으로 큰 부분이라 생각하니 남성이겠지요?
이제 PCA 클래스를 입혀 덩치라는 하나의 값으로 변환한 뒤 성별 간의 비교를 해봅시다.
PCA 클래스를 입히는 코드는 위 붓꽃 데이터와 크게 차이가 없습니다.
다만, 몇개 차원으로 축소할 것인가를 결정하는 n_components 파라미터는 붓꽃은 2였지만 지금은 1개로 합니다.
파라미터 개수를 산정하는 것은 아래 포스팅을 참고하십시오
# 일단 허리둘레와 키 값을 정규화시켜줍니다 from sklearn.preprocessing import StandardScaler df_scaled = StandardScaler().fit_transform(df[['waist', 'height']]) from sklearn.decomposition import PCA # PCA 적용 - 컴포넌트는 1로 설정합니다. pca = PCA(n_components=1) #fit( )과 transform( ) 을 호출하여 PCA 변환 데이터 반환 pca.fit(df_scaled) df_pca = pca.transform(df_scaled) print(df_pca.shape)
Python
복사
1000명의 덩치 값이 위와 같이 쭉 형성되었습니다.
시각화를 위해, 덩치값 옆에 성별 코드 (타겟 레이블 개념) 를 붙여줍니다.
df_pca_component = pd.DataFrame(df_pca,columns=['pca_component']) df_pca_component['target'] = df.sex sns.distplot(df_pca_component.loc[df_pca_component['target'] == 1, 'pca_component'], hist=True, color="blue", kde=False, label = 'man') sns.distplot(df_pca_component.loc[df_pca_component['target'] == 2, 'pca_component'], hist=True, color="orange", kde=False, label = 'woman')
Python
복사
높은 pca_comonent 즉, 높은 덩치값이 많이 분포되어 있는 것은 남성(color="blue") 으로 나타남을 알 수 있습니다.
가운데에 겹쳐서 붉은빛을 띠는 구간은 상대적으로 덩치가 작은 남성, 덩치가 큰 여성 등으로 볼 수 있습니다.
PCA 작업이 마무리 되었으니 비슷한 알고리즘이었던 LDA는 어떤 결과를 가져왔을까 비교해봅시다.
코드 보기
오른쪽이 LDA를 적용한 그래프입니다. 확실히 PCA에 비해 깔끔하게 분류되었습니다.
그런데 파란색과 주황색 위치가 바뀌어있다는 걸 알 수 있습니다
파란색은 남성, 주황색은 여성으로 코딩을 해두었는데,
LDA는 잠재요소값을 왜 남성쪽에서 낮게 나타나게 만들었을까요?
맨 처음 두 알고리즘을 설명하며 봤던 그림 자료를 다시 봅시다.
생각해보면, 키와 허리둘레는 상식적으로 양의 상관관계를 가질 것입니다. (키가 크면 허리둘레도 클 가능성이 큼)
그러면 알고리즘이 각자의 특성상 잠재요소(component)를 만들 축을 설정하는데 아래와 같이 서로 달리 설정합니다.
PCA는 이에 따라 같은 방향으로 화살표를 설정 (위 이미지처럼)
LDA는 키와 허리둘레를 구분지으려고 화살표를 PCA와 반대로 설정 (위 이미지처럼)
이러한 이유로 PCA에서는 키와 허리둘레가 큰 사람의 component가 크다(+)라고 나왔고, LDA에서는 키와 허리둘레가 큰 사람의 component는 작다(-)고 나온 것입니다.
따라서 LDA의 component덩치라고 마냥 상정하기는 어렵습니다.
물론 PCA가 만들어낸 component도 엄밀한 의미의 덩치는 아닐 것입니다. 눈에 보이지 않는 추상적인 개념을 조작적으로 이번 환경 내에서 정의한 것이기 때문이지요.
김문과의 데이터
직접 공부한 데이터 분석 · 활용법을 기록합니다.
포스팅에 대한 Q&A 및 다양한 논의를 기다립니다. contact or email