[머신러닝] PCA(Principal Component Analysis)

쩡이·2023년 10월 5일

ML

목록 보기
12/14

PCA란?

데이터 집합 내에 존재하는 각 데이터의 차이를 가장 잘 나타내 주는 요소를 찾아 내는 방법
통계 데이터 분석(주성분 찾기), 데이터 압축(차원감소), 노이즈 제거 등 다양한 분야에서 사용

  • 차원축소(dimensionality reduction)와 변수추출(feature extraction) 기법으로
    널리 쓰이고 있는 주성분분석(Principal Component Analysis)
  • PCA는 데이터의 분산(variance)을 최대한 보존하면서 서로 직교하는 새 기저(축)를 찾아,
    고차원 공간의 표본들을 선형 연관성이 없는 저차원 공간으로 변환하는 기법
  • 변수추출(Feature Extraction)은 기존 변수를 조합해 새로운 변수를 만드는 기법
    (변수선택(Feature Selection)과 구분할 것)

그려보면

plt.scatter(X[:,0], X[:,1])
plt.axis('equal') #x, y축 간격을 같게 만드는 옵션

#fit
from sklearn.decomposition import PCA

pca = PCA(n_components=2, random_state=13)
pca.fit(X)

#벡터를 그리는 함수
def draw_vector(v0, v1, ax=None):
    ax = ax or plt.gca() #ax=none이면 plt.gca(), 다른 ax 설정이 들어오면 그걸 써라
    arrowprops = dict(
        arrowstyle='->', #화살표 스타일
        linewidth=2, #줄크기
        color='black', #색상
        shrinkA=0, #
        shrinkB=0
    )
    ax.annotate('', v1, v0, arrowprops=arrowprops) #annotate함수는 글자를 찍는 함수인데, 우리는 화살표만 표현하기 위해서 ''로 두었고,
    #v1에서 v0까지 그려라
    
pca.mean_ #그래프에서 원점역할, 데이터의 중심, 가장 큰 영향력을 미치는 벡터


#그래프
plt.scatter(X[:,0], X[:,1], alpha=0.4)

for length, vector in zip(pca.explained_variance_, pca.components_):
    v = vector * 3 * np.sqrt(length) #적당한 크기로 만들기 위해 3을 곱함
    draw_vector(pca.mean_, pca.mean_+v)

plt.axis('equal')
plt.show()

데이터의 주성분을 찾은 다음 주축을 변경하는 것도 가능하다

이번에는 n_components를 1로 두고

X_pca = pca.transform(X)

X_new = pca.inverse_transform(X_pca) #2차원 -> 1차원 : pca 이것을 2차원 표현으로 바꿈 (X_new)
plt.scatter(X[:,0], X[:,1], alpha=0.3)
plt.scatter(X_new[:,0], X_new[:,1], alpha=0.9)
plt.axis('equal')
plt.show()

iris 데이터로 실습해보자

#scaler 적용
from sklearn.preprocessing import StandardScaler

iris_ss = StandardScaler().fit_transform(iris.data)
iris_ss[:3]

#pca 결과를 return하는 함수
from sklearn.decomposition import PCA

def get_pca_data(ss_data, n_components=2):
    pca = PCA(n_components=n_components)
    pca.fit(ss_data)

    return pca.transform(ss_data), pca

#pca 결과를 데이터프레임으로
def get_pd_from_pca(pca_data, cols=['PC1', 'PC2']):
    return pd.DataFrame(pca_data, columns=cols)
#4개의 특성을 두개의 특성으로
iris_pd_pca = get_pd_from_pca(iris_pca)
iris_pd_pca['species'] = iris.target

#두 개의 특성 그리기
sns.pairplot(iris_pd_pca, hue='species', height=5, x_vars=['PC1'], y_vars=['PC2'])

#4개 특성을 모두 사용해서 randomforest
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

def rf_scores(X,y,cv=5):
    rf = RandomForestClassifier(random_state=13, n_estimators=100)
    scores_rf = cross_val_score(rf, X, y, scoring='accuracy', cv=cv)

    print('Score : ', np.mean(scores_rf))

wine 데이터로 실습해보자

pca_columns = ['PC1', 'PC2']
pca_wine_pd = pd.DataFrame(pca_wine, columns=pca_columns)
pca_wine_pd['color'] = wine_y.values

sns.pairplot(pca_wine_pd, hue='color', height=5, x_vars=['PC1'], y_vars=['PC2'])

pca_wine_plot = pca_X
pca_wine_plot['color'] = wine_y.values

import plotly.express as px

fig = px.scatter_3d(pca_wine_plot, x='PC1', y='PC2', z='PC3', color='color', symbol='color', opacity=0.4)
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0))
fig.show()

0개의 댓글