피어슨 상관관계(유사도) 이해 및 파이썬 구현하기

    상관관계 이해

    일단 피어슨 상관관계를 이해하기 위해서, 간단히 상관관계에 대해서 알아보도록 해보자. 대표적으로 상관관계를 이해할 땐 키와 몸무게의 데이터를 활용하곤 한다.

     

    인간은 키가 커지면, 몸무게 또한 커지기 마련인데 이처럼 두 값이 같은 방향으로 커지는 것을 양의 상관관계라고 한다. 반대로 음의 상관관계는 값이 커지면 다른 값이 작아지는 경우를 뜻하는데 술을 많이 마신다던가, 담배를 많이 필경우 기대 수명이 줄어드는 경우가 있는데 이렇게 두 값이 같은 방향으로 가지 않으면 음의 상관관계라고 한다.

     

    source, https://learninglink.oup.com/static/5e29c09d2a15880010e5aea4/index.html

     

    위 그림을 보면, r이 1에 가까울수록 우상향의 선형 모양이 나오게 되며, r이 -1에 가까울수록 우하향의 선형 모양이 나오게 된다. 그리고 0에 가까울 경우 완전히 패턴을 찾기 힘든 모습이 나오게 되는데 이렇게 0에 가까운 상관관계를 무상관이라고 한다.

     

    피어슨 상관계수

    우리가 보통 상관계수를 구한다라고 하면 피어슨 상관계수를 구한다와 같다고 이해해도 좋을 것이다. 연관성의 측도는 보통 공분산(Covariance)같은 값을 활용할 수 있는데 공분산의 문제는 값의 범위가 커지면 공분산의 값이 더 크게 나오기 때문에 응집이 되는 모양일수록 값이 적게 나오는 문제가 있다.

     

    이를 해결하기 위해서는 표준화를 시켜줘야 하는데 이것을 만들어 낸 것이 칼 피어슨(Karl Pearson)이라는 사람이고, 이 분이 만든 상관계수라고 해서 피어슨 상관계수라고 한다.

     

    칼 피어슨(1857년 3월 27일~1936년 4월 27일), ko.wikipedia.org/wiki/칼_피어슨

     

    피어슨 상관계수 공식

     

    피어슨 상관계수는 위와 같은 공식을 사용한다. 공분산에 표준편차를 이용하여 정규화를 진행한 것으로 다양한 머신러닝 분야에서 활용이 가능하다.

     

    피어슨 상관계수를 활용한 대표적인 기법으로는 사람간의 유사도를 측정하는 추천 시스템(ex: Collaborative Filtering)이 대표적이다. 추천 시스템의 상징이라 할 수 있는 협업 필터링에서 가장 많이 활용되는 사람간의 유사도 측정 방식에 피어슨 상관계수를 많이 활용하기 때문이다.

     

    상관계수가 높을수록 두 값은 서로 연관이 있다는 뜻이기 때문에 유사도 측정에 많이 활용이 되어서 평점 시스템이 있는 컨텐츠의 유사도 측정으로 많이 활용된다. 그래서 피어슨 상관계수를 활용하여 피어슨 유사도라는 말로도 불리고 있다.

     

     

    피어슨 상관계수 코드 예시

    피어슨 상관계수는 위 공식을 활용하여 직접 공식을 작성하는 방법과, Scipy 라이브러리를 쓰는 방법과 numpy를 쓰는 방법 그리고 판다스를 쓰는 방법등이 있다.

     

    라이브러리

    from scipy.stats import pearsonr
    import numpy as np
    import pandas as pd
    
    user_a = [5.0, 0.5, 4.0, 3.5, 3.5]
    user_b = [5.0, 3.0, 5.0, 5.0, 5.0]

    총 4가지의 방식으로 피어슨 상관계수를 구하며, 첫번째는 공식을 직접 만드는 방식이며 나머지는 scipy, numpy, pandas를 활용한다.

     

    # 일반적인 공식 활용 예시
    def pearson_similarity(a, b):
        return np.dot((a - np.mean(a)), (b - np.mean(b))) / ((np.linalg.norm(a - np.mean(a))) * (np.linalg.norm(b - np.mean(b))))
    print(pearson_similarity(user_a, user_b))
    
    # 0.9312661473328351

     

    첫번째는 일반적인 공식을 활용한 것으로 0.93의 높은 상관관계가 나왔다.

     

    # scipy 활용
    print(pearsonr(user_a, user_b))
    # (0.9312661473328351, 0.021407250596872356)
    
    print(pearsonr(user_a, user_b)[0])
    # 0.9312661473328351

    두번째 방식은 scipy 패키지 안에 있는 pearsonr 라이브러리를 호출하는 방식이다. pearsonr은 2가지의 값이 리턴되는데 첫번째는 상관계수이고, 두번째는 p-value가 리턴된다. 첫번째 값인 상관계수만 콜하고 싶은 경우 아래처럼 [0]을 호출하면 상관계수만 가져올 수 있다.

     

    scipy pearsonr 설명 캡쳐

     

    pearsonr에 대한 인자값과 결과값 설명은 위의 캡쳐 화면을 참고해보도록 하자.

     

    # numpy 활용
    print(np.corrcoef(user_a, user_b))
    
    # [[1.         0.93126615]
     [0.93126615 1.        ]]

     

    numpy 역시 피어슨 상관계수를 지원하며 다른 것과 다르게 행렬 형태의 모양으로 값이 리턴이 된다.

     

    # pandas 활용
    df = pd.DataFrame([(5.0,5.0),(0.5,3.0),(4.0,5.0),(3.5,5.0),(3.5,5.0)], columns=['user_a', 'user_b'])
    print(df.corr(method="pearson"))
    
    
             user_a    user_b
    user_a  1.000000  0.931266
    user_b  0.931266  1.000000

     

    판다스 역시 numpy처럼 결과가 유사하게 출력이 된다. 

     

    전체 코드

    from scipy.stats import pearsonr
    import numpy as np
    import pandas as pd
    
    user_a = [5.0, 0.5, 4.0, 3.5, 3.5]
    user_b = [5.0, 3.0, 5.0, 5.0, 5.0]
    
    
    # 일반적인 공식 활용 예시
    def pearson_similarity(a, b):
        return np.dot((a - np.mean(a)), (b - np.mean(b))) / ((np.linalg.norm(a - np.mean(a))) * (np.linalg.norm(b - np.mean(b))))
    print(pearson_similarity(user_a, user_b))
    
    # scipy 활용
    print(pearsonr(user_a, user_b))
    print(pearsonr(user_a, user_b)[0])
    
    # numpy 활용
    print(np.corrcoef(user_a, user_b))
    
    # pandas 활용
    df = pd.DataFrame([(5.0,5.0),(0.5,3.0),(4.0,5.0),(3.5,5.0),(3.5,5.0)], columns=['user_a', 'user_b'])
    print(df.corr(method="pearson"))

     

    참고자료

    https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html

    댓글

    Designed by JB FACTORY