머신러닝 10. 비지도학습: 주성분분석(PCA)


    목차
    1. 데이터셋 로딩
      (1) 데이터셋 로딩
      (2) 데이터셋 간단조회: head() / str() / tibble::glimpse()
    2. 기술통계분석
      (1) 기술통계: summary() / skimr::skim()
    3. 각 변수 간 기본적 관련성 파악
      (1) 공분산분석: cov() / cov2cor()
      (2) 상관관계분석: cor() / Hmisc::rcorr()
      (3) 변수 간 상관관계 그래프: plot() / PerformanceAnalytics::chart.Correlation() / psych::pairs.panels()
      (4) 변수 간 상관성 파악: corrplot::corrplot() / gplots::heatmap() / d3heatmap::d3heatmap()
    4. 데이터 전처리
      (1) 성분으로 결합될 가능성 높은 변수컬럼 기준으로 컬럼 순서 재구성
    5. 주성분분석: psych::principal()
      (1) 적정한 주성분 / 요인 개수 산정: fa.parallel() / fa = “pc” / fa = “fa” / fa = “both”
      (2) 주성분분석1 & 무회전 방식 성분추출: psych::principal(rotate=”none”) / str() / $loadings / $weights / $scores
      (3) 주성분분석2 & 직교회전 방식 성분추출: psych::principal(rotate=”varimax”)
      (4) 주성분분석3 & 사각회전 방식 성분추출: psych::principal(rotate=”promax”)
      (5) 주성분분석 후 각 변수와 성분점수와의 상관성 재확인
      (6) 주성분 개수 정하기: 누적기여율 / 고유값(eigenvalue) / Scree plot
    6. 기타 주성분분석 함수: stats::prcomp() / stats::princomp() 이용 외 이하 동일
    7. 기타 주성분분석 함수: FactoMineR::PCA() / summary() / $eig / barplot()
    8. 기타 주성분분석 함수: factoextra::fviz_screeplot() / plot.PCA() / fviz_pca_ind() / plot() / fviz_pca_var()



019

  • 요인분석과 주성분으로 컬럼을 묶어주기 위해서는 주로 공분산과 상관성의 개념을 이용해 분석.

  • 공분산은 방향은 알 수 있으나 크기의 비교가 힘들어서(제곱으로 인해 숫자가 커서) 표준화한 것이 상관계수의 개념.

  • 변수마다 평균을 구한 후 각 데이터가 어느 정도의 폭을 가지고 움직이는지를 알기 위해서는 편차 구하고 분산을 구한다. 그리고 표준편차를 구한다. 일반적으로는 편차가 크면 분산이 크다고 이야기한다. 그러면 전반적으로 데이터의 변동폭을 알 수 있다.

  • 다중공선성이 존재할 경우 해결 방법 중의 하나가 바로 상관도가 높은 변수들을 하나의 주성분 혹은 요인으로 축소하여 모형개발에 활용하는 것입니다.

각 변수간 기본적 관련성 파악

(1) 공분산 분석(corvariance analysis)

  • 두 변수 간에 상호 관련성을 파악하는 기법

  • 하나의 변수가 양/음으로 변화될 때 다른 변수도 같은 방향으로 변하는지, 다른방향으로 변하는지 경향성을 파악함

  • 그러나 두 변수간의 상호관련성의 크기를 절대적으로 판단할 수 있는 기준은 아님

  • 이를 표준화해서 만든 것이 상관계수임

● 상관계수는 제곱 등으로 덩치 커져버린 공분산을 표준편차로 나눠서 표준화시킨 것.

(2). 상관관계 분석(correlation analysis)

  • 두 변수 간에 상호 관련성(선형성)을 파악하는 기법

  • 관련성의 크기를 상관계수(correlation coefficient)로 나타냄

  • 선형성이 있다면 방향성은 정·양(+)인지, 부·음(-)인지, 그 관계는 얼마나 큰지를 나타내는 판단기준

  • 상관계수값은 -1 ~ +1 사이로 표준화 되어 있음 0: 상관관계가 없음, ±1은 상관관계가 매우 강함

  • 어떤 변수가 원인이고, 결과인지 알 수 없음

  • 두 변수가 등간/비율/양적 척도이면, pearson 상관관계

  • 서열/등간 척도이면, spearman/kendall 서열상관관계

(3) 축소분석 대상인 여러개 변수들간의 관계를 공분산행렬과 상관계수 행렬중 어떤 것을 사용할 것인가?

주성분 분석의 경우 변수들간의 선형결합을 유도할 때
  • 분산을 이용하기 때문에 공분산 행렬로부터 유도된 주성분은 각 변수들의 측정단위에 영향을 많이 받음

  • 설문조사처럼 모든 변수들이 같은 수준으로 측정된 데이터는 공분산 행렬을 사용해도 무방함

  • 변수들의 scale이 서로 많이 다른 경우에는 측정단위가 큰 특정 변수의 영향으로 도출된 주성분에 오류가 있을 가능성이 크므로 상관계수 행렬을 사용해 추출함


—————코딩——————————————————————————————————


문제시나리오: 온라인 쇼핑몰 쿠폰이벤트 사용자만족도 조사분석
  • 쿠폰을 통한 프로모션 진행후 이용고객들에게 사용자만족도를 조사함
  • 이용자들이 쿠폰프로모션에 대해서 생각하는 다양한 평가기준(관리포인트)를 대표하는 요소는 무엇인지?
  • 이 요소들 중에서 상대적으로 중요한 것은 무엇인가?


사용자만족도 조사변수
  • quality: 쿠폰을 통해 판매하는 제품은 품질이 높다.
  • refund: 쿠폰을 통해 구매한 제품은 쉽게 환불이 가능하다.
  • value: 쿠폰을 통해 판매하는 제품은 대체로 값어치가 있다.
  • simple: 쿠폰을 통해 구매하면 매우 간편하다.
  • equal: 쿠폰을 통해 구매해 배달되는 제품은 광고제품과 동일하다.
  • time: 쿠폰을 통해 구매하면 시간을 절약할 수 있다.
  • lost: 쿠폰을 통해 구매하면 분실염려가 없다.
  • brand: 쿠폰을 통해 판매하는 제품은 대부분 유명브랜드 제품이다.
  • delivery: 쿠폰을 통해 구매한 제품은 원하는 장소에 배달된다.



1. 데이터셋 로딩


(1) 데이터셋 로딩



(2) 데이터셋 간단조회: head() / str() / tibble::glimpse()




2. 기술통계분석


(1) 기술통계: summary() / skimr::skim()




3. 각 변수 간 기본적 관련성 파악


(1) 공분산분석: cov() / cov2cor()


● 원래는 cov() 함수 안에 두 개 데이터 있어야 하나 얘는 벡터연산 가능.

● use = “complete.obs” 옵션은 완벽한 데이터만 써달라는 설정, 즉 NA가 하나라도 들어있다면 빼라는 설정.

● pearson 방식은 양적데이터일 때를 감안한 방법.

● 환불 가능성은 -가 나왔고, 품질변수와 값어치, 브랜드 변수는 대체로 숫자가 + 방향이고, 1이 넘는다.


(2) 상관관계분석: cor() / Hmisc::rcorr()


● 대각선 방향은 1.0인데 완벽히 방향성 일치에 똑같이 움직인다는 뜻으로 얘네는 자기 변수.

● 0.6 ~ 0.7은 매우 강한 상관관계

● 0.4 ~ 0.5는 보통의 상관관계

● 0.3 이상이면 두 변수가 관련성 있게 움직이는 패턴이 있다고 볼 수 있다.

● 퀄리티에서 0.4보다 큰 상관계수가 있는 변수는 품질과 브랜드 정도.

● 나머지는 상관관계가 미미하고, 배달 정도만 관계가 약간 있는 정도. 그러나 배달은 심플과는 큰 관련성이 있어 나중에 요인 분석 시 심플과 결합될 가능성이 있다.

● 심플은 타임과 관련성이 좀 있고 나머지와 거의 관련성이 없다. 걱정하는 측면의 변수들(로스트,..)과는 별로 관련없다.

● 상관성을 보면 잠재변수의 구조가 보인다.

● 만약 이 상관관계가 우리의 생각과 다르게 묶였다면, 질문 자체가 소비자들이 분석가의 의도를 오해하도록 설정되었다거나, 의사 소통이 잘 안됐을 가능성 있는 것.

● refund 변수를 보면, equal과 lost와 묶인다.

● rcorr: 상관관계 확인하는 변수

● p-value: 이 데이터의 결과는 불과 80명에 대한 결과다, 즉 표본이다. 그래서 이 내용이 앞으로도 이런 패턴으로 유지될건지, 표본 크기 변하거나 표본 변하면 결과가 어떻게 될지 모른다. 모집단 대상으로 같은 조사를 했을 때도 동일한 결과가 나올지 판단하기 위한 기준이 p-value. (probability value)

● 주어진 데이터를 가지고 특성을 비교하는 걸 기술통계라고 하는데, 변수간의 관계인 상관성을 보는 것, 그리고 이 패턴이 모집단이나 실제 시장을 대상으로 진행했을 때도 유사하게 나올지 분속하는 걸 추론통계라고 부른다.

● p-value 값이 0.05 보다 낮으면 모집단 대상으로 했을 때도 같은 결과 나올 거라고 예상해도 무방. (허용가능치가 0.05) 즉 오류 가능성이 적다.

● 아마 대체로 상관성 0.4 이상 나오는 변수들이 p-value(유의확률) 값이 0.05 허들보다 작게 나올 것.


(3) 변수 간 상관관계 그래프: plot() / PerformanceAnalytics::chart.Correlation() / psych::pairs.panels()


  • 어떤 변수들간에 데이터변화량이 상관성이 있는지 윤곽을 보고 결합될 수 있는 성분/요인을 미리 파악함

● 별표 개수에 따라 관계의 강약이 드러나는데 요인분석 하면 퀄리티와 이퀄은 묶이지 않을 것. 우선순위에서 밀려서.


(4) 변수 간 상관성 파악: corrplot::corrplot() / gplots::heatmap() / d3heatmap::d3heatmap()




4. 데이터 전처리


(1) 성분으로 결합될 가능성 높은 변수컬럼 기준으로 컬럼 순서 재구성




5. 주성분분석: psych::principal() / stats::prcomp()


(1) 적정한 주성분 / 요인 개수 산정: fa.parallel() / fa = “pc” / fa = “fa” / fa = “both”


● n.obs: number of observations. 관찰한 표본 크기

● fa 옵션 : factor analysis.pc: 주성분분석. principle component ( 아래에 나올 fc는 상관있는 것만 가지고 작성하는 요인분석. )


(2) 주성분분석1 & 무회전 방식 성분추출: psych::principal(rotate=”none”) / str() / $loadings / $weights / $scores


● nfactors = 4: 요인을 4개 정도로 묶어본다는 의미. 대표 변수를 4개로 축약하겠다는 설정.

● rotate = “none” : 요인들을 만들 때 전혀 관련 없게 만드는 방법이 있고, 어느 정도 상관성 허용하면서 만드는 방법이 있는데, 이건 무회전 방식으로 요인 간에 90도 각 지게 해서 만드는 방법. 나중에 다시 설명. 개별 변수들간의 선형성을 결합해서 성분을 구성하라는 설정.

● 결과 표에서는 개별 변수 별로 새로운 성분 만들 때 어느정도 가져다 썼는지 ㅅ수 있다. brand 변수에서는 0.79 정도 갖다 썼다는 의미. PC1을 구성하는 데이터의 적재량은 brand, value,….,등등에서 다음과 같이 가져온 것을 알 수 있음. 위에서 많이 가져왔고, time 부터는 절반 이하를 가져와 썼다는 것을 알 수 있다.

● PC2를 보면, PC1을 쓰고 난 나머지 변동성을 가지고 만들었는데, PC1 과 반대되었다. 분산의 양과 움직임이 공분산을 이용해 계산해보니 다르게 움직이고 있다는 것을 알 수 있다. PC2는 equal, lost, refund에서 주로 가져왔다.

● PC3는 가운데에서 많이 가져옴.

● PC4는 전반적으로 적재한 데이터가 산재되어 있다. 아까 스크리더 표에서도 간당간당했고, 상대적으로 대표성이 덜하다.

● h2, u2 이용해서 알 수 있는 것은 brand의 86%정도만 가져와서 사용했고 14% 버려졌다는 것, 손실된 데이터가 조금 있다는 것을 의미.

● 상대적으로 아래쪽은 h2가 80%가 안 된다. 대표 패턴이 75%정도나 그 이하. 그 정도만 활용되고 있다는 의미.

● com은 작으면 작을 수록 좋은 것. 이건 복잡도. 이게 작으면 어느 한쪽에서 비중있게 많이 쓰이고 있다는 의미. 성분을 구성할 때 영향을 많이 끼칠수록 복잡도가 높다.

● delivery 보면 복잡도가 높다. 얘는 데이터 패턴이 어느 한쪽으로 명확하게 나오지 않고 여러 성분 구성할 때 같이 나온다. PC1 에서 0.61, PC3에서 0.47.

● SSloadings은 성분을 구성하는 고유한 분산의 양이라고 보면 된다.

● 이게 1.0이상이 되어야 대표성을 가지고 있는 변수로서 볼 수 있다.

● PC4은 0.79이기 때문에 대표성이라고 보긴 힘들다.

● Proportion Var : 비율면에서 볼 때 이정도의 중요도 차이가 있다는 것. 32%, 22% 이렇게. PC4는 9%라 상대적으로 취약.

● Cumulative Var: 누적 분산량. 오른쪽으로 쭉쭉 가면 81% 정도로 떨어진다. 전체 아홉개 변수를 1.0으로 치자면, 4개 변수로 축약했을 때 데이터 양이 19%정도 손실된 것으로 판단할 수 있다.

● Proportion Explained: 누적분산 설명력. PC1이 80명의 9개 변수 움직임을 40%정도 설명할 수 있는 대표성을 지녔다. PC2가 27%,…. 누적분산 설명력은 85%정도까지가 적당하다고 판단.

● 대표할 수 있는 변수는 3개 정도로 보는 게 적당할 듯. PC4는 너무 산재되어 있다. 이 표를 봤을 때는 3개가 적정.

● 주성분분석은 변수를 줄이려는 게 목적이므로 4개보다는 3개로 적은 게 좋다.

● 논문같은 거 쓸때는 $loadings 즉 제일 밑의 loadings, SS loadings 같은 거 꼭 적어줘야하는 중요한 거.


(3) 주성분분석2 & 직교회전 방식 성분추출: psych::principal(rotate=”varimax”)


● 90도 각도가 나오게 위치 잡아달라, 요인 간의 적재되는 데이터 양이 어정쩡하거나 더많이 벌어지는 타입 아니라, 대표하는 성분 간의 구성된 데이터의 변동량이 방향성이 90도로 만들어달라 는 옵션.

● 아까하고 주요한 내용은 비슷하다.

● 아까하고 요인별 적재된 양은 조금씩 다르다.

● com: complexity. 거의 1점대다. 아까는 3점대도 있었는데.

● value보면 RC1에 거의 90%.

● simple은 좀 어정쩡하네. RC3에 0.63, RC4에 0.64. 이럴 땐 가급적 숫자가 큰 쪽으로 보면 된다. 아무튼 그래서 복잡도도 상대적으로 높다.

● 다중공선성(?)을 피하려면 분산의 변동성이 많은 변수를 살리고 나머지를 없애는 것도 하나의 방법. 그러나 이런 방식보다는 주성분방식이나 요인분석 방식 이용해서 컬럼 묶는 방식 쓰면 데이터 손실이 덜하다.


(4) 주성분분석3 & 직교회전 방식 성분추출: psych::principal(rotate=”promax”)


● weighgts: 가중치. 어떤 변수에 어느 정도로 가져왔는지 확인.

● scores: 실무에서 중요한 내용. 이걸 가지고 군집분석, 회귀분석에 쓰면 된다.


(5) 주성분분석 후 각 변수와 성분점수와의 상관성 재확인



(6) 주성분 개수 정하기: 누적기여율 / 고유값(eigenvalue) / Scree plot




6. 기타 주성분분석 함수: stats::prcomp() / stats::princomp() 이용 외 이하 동일




7. 기타 주성분분석 함수: FactoMineR::PCA() / summary() / $eig / barplot()




8. 기타 주성분분석 함수: factoextra::fviz_screeplot() / plot.PCA() / fviz_pca_ind() / plot() / fviz_pca_var()



<참고 문헌="">


  1. 최점기 박사님 강의
  2. 통계학개론 (영지출판사)
  3. https://rfriend.tistory.com/61
comments powered by Disqus