Graphical lasso를 이용한 다변수 간의 상관 분석을 폭속으로 시험

동기 부여



데이터를 분석하는 경우 가끔 다음과 같은 상황이 발생합니다.
  • 다양한 데이터의 관계를 알고 싶습니다
  • 비교적 노이즈가 심하지만 다른 데이터와 비교하고 싶습니다
  • 겉보기 상관은 제외하고 싶다
  • 정말로 관계가 있는 것은 얼마 밖에 없다고 하는 전제를 두고 싶다
  • 우선 무언가의 기술을 시도하고 싶습니다

  • 이런 때는 우선 Graphical lasso를 사용해 보자는 이야기입니다.

    Graphical lasso란?



    거꾸로 말하면, 변수간의 관계를 그래프화하는 수법입니다.
    다변량 가우스 분포를 전제로 한 수법이므로, 상당히 다양한 곳에서 사용할 수 있는 생각이 듭니다.
    자세한 것은 이 책 가 매우 알기 쉽게 해설해 줍니다. 이론에 흥미가 있는 분은 꼭 손에.

    구현



    이번에 구현한 것은 추정된 정밀도 행렬을 상관 행렬로 변환하여 그래프로 출력하는 프로그램입니다.
    아직 개선의 여지가 있습니다만, 데이터 분석을 진행하는데 있어서의 하나의 지표가 된다고 생각합니다.

    테스트 데이터 준비
    # テストデータを用意する。
    from sklearn.datasets import load_boston
    boston = load_boston()
    X = boston.data
    feature_names = boston.feature_names
    

    메인 처리
    import pandas as pd
    import numpy as np
    import scipy as sp
    from sklearn.covariance import GraphicalLassoCV
    import igraph as ig
    
    # 同じ特徴量の中で標準化する。
    X = sp.stats.zscore(X, axis=0)
    
    # GraphicalLassoCV を実行する。
    model = GraphicalLassoCV(alphas=4, cv=5)
    model.fit(X)
    
    # グラフデータ生成する。
    grahp_data = glasso_graph_make(model, feature_names, threshold=0.2)
    
    # グラフを表示する。
    grahp_data
    

    그래프 생성 함수
    def glasso_graph_make(model, feature_names, threshold):
        # 分散共分散行列を取得する。
        # -> 参考URL:https://scikit-learn.org/stable/modules/generated/sklearn.covariance.GraphicalLassoCV.html
        covariance_matrix = model.covariance_
    
        # 分散共分散行列を相関行列に変換する。
        diagonal = np.sqrt(covariance_matrix.diagonal())
        correlation_matrix = ((covariance_matrix.T / diagonal).T) / diagonal
    
        # グラフ表示のために対角成分が0の行列を生成する。
        correlation_matrix_diag_zero = correlation_matrix - np.diag( np.diag(correlation_matrix) )
        df_grahp_data = pd.DataFrame( index=feature_names, columns=feature_names, data=correlation_matrix_diag_zero.tolist() )
    
        # グラフ生成準備
        grahp_data = ig.Graph()
        grahp_data.add_vertices(len(feature_names))
        grahp_data.vs["feature_names"] = feature_names
        grahp_data.vs["label"] = grahp_data.vs["feature_names"]
        visual_style = {}
        edge_width_list = []
        edge_color_list = []
    
        # グラフ生成
        for target_index in range(len(df_grahp_data.index)):
            for target_column in range(len(df_grahp_data.columns)):
                if target_column >= target_index:
                    grahp_data_abs_element = df_grahp_data.iloc[target_index, target_column]
                    if abs(grahp_data_abs_element) >= threshold:
                        edge = [(target_index, target_column)]
                        grahp_data.add_edges(edge)
                        edge_width_list.append(abs(grahp_data_abs_element)*10)
                        if grahp_data_abs_element > 0:
                            edge_color_list.append("red")
                        else:
                            edge_color_list.append("blue")
    
        visual_style["edge_width"] = edge_width_list
        visual_style["edge_color"] = edge_color_list
    
        return ig.plot(grahp_data, **visual_style, vertex_size=50, bbox=(500, 500), vertex_color="skyblue", layout = "circle", margin = 50)
    

    결과





    임계값을 상당히 낮게 설정하고 있는 탓인지, 직접 상관이 나름대로 발견되고 있네요.
    시험에 상관이 가장 강한 것 같은 변수끼리를 봅니다.
    상관계수가 가장 높은 것은 RAD(고속도로 접근성)와 TAX($10,000당 부동산 세율의 총계)입니다. 즉, 고속도로에 접근하기 쉽다면 세금이 높다는 것입니다.
    솔직히, 이 데이터만으로는 뭐라고 말할 수 없습니다만, 마치 보기 흉한 결과라도 되지 않을 것 같습니다.

    마지막으로



    우선 시험할 수 있는 환경은 최고군요.
    결과에 대해서는, 좀 더 데이터수가 많아, 노이지인 데이터였던 것이 알기 쉬웠을지도 모릅니다. 어딘가에 없습니까?

    이번에는 Graphical lasso를 사용하여 변수 간의 관계성을 그래프화하는 곳까지 실시했습니다만, 그 앞에는 그래프 구조에 주목한 변화 검지 수법등도 있어, 아직도 공부의 가재가 있는 분야라고 느끼는 있습니다.

    주의 및 면책 조항



    본 기사의 내용은 어디까지나 개인의 견해이며, 소속된 조직의 공식 견해가 아닙니다.
    본 기사의 내용을 실시해, 이용자 및 제3자에게 트러블이 발생해도, 필자 및 소속 조직은 일절의 책임을 지지 않습니다.

    좋은 웹페이지 즐겨찾기