Introduction & Clustering과 금융

Dataset & 참조 자료: Machine Learning in Business 3rd Edition

머신러닝이란 분야는 비록 데이터를 다루는 것이지만 머신러닝을 탄생시킨 학문 계통은 엄밀히 말해 통계학 계통은 아니다. 그래서, 통계학에서 사용하는 표현 대신 자신들만의 표현을 사용하는 경우가 많다. 관련 논문이나 프로젝트를 접할 때, 이러한 표현들의 영문 표기, 수학적 정의, 그리고 뜻을 아는 것은 큰 도움이 된다. 앞으로의 포스트에서도 가끔 이런 표기들이 나오면 <INTRO>에서 설명하고자 한다.

Intro

이번에 나오는 새로운 머신러닝 개념들은 아래와 같다.

Observation

관측된 자료

Features

자료의 특징. 예를 들어 한 자료에 대해 4개의 Feature가 있으면 해당 자료는 4차원 자료이다.

Feature Scaling

변동폭이 큰 변수의 영향력이 과대평가되거나 변동폭이 작은 변수의 영향력이 과소평가되는 효과를 통계하기 위해 데이터를 변환하는 과정이다. 자산 가격이 아니라 자산 수익률을 이용하는 것도 같은 맥락이다.

보통 통계 모형이나 머신러닝 모형은 변동성이 크면 그 변수가 더 많은 정보를 포함하고 있다고 생각하는데, 실제로 그런 게 아님에도 변동폭이 심하게 다르거나 원래부터 Feature들의 단위가 달라서 규모가 다를 뿐이라면, scaling를 해줄 필요가 있을 수도 있다.

보통, 어떤 현상을 설명하기 위한 분석에서는 scaling를 자주 하지 않는다(ex. 회귀분석). 하지만, 머신러닝처럼 예측을 위해 모형을 사용하는 경우엔 혹시나 있을 오류를 막기 위해 scaling를 하는 관례가 있다.

scaling은 feature들의 변동(variation)이 비슷해지도록 조정한다. 잘 알려진 scaling 방법은 크게 Z-score와 Min-Max Scaling이 있다.

Z-score 방식은 feature 값들에서 그 평균을 빼고 그 표준편차로 나눈 것이다. Min-Max Scaling은 이름이 보여주듯 feature 값들에서 그 최솟값을 빼고 그걸 최댓값-최솟값으로 나눈 것이다.

데이터에 뜬금없이 커다란 값이나 너무 작은 값이 있으면 Min, Max의 절댓값 또한 그 한 값 때문에 어마어마하게 커지므로, 아무래도 Z-score 방식이 값이 범위에서 극단적으로 벗어난 극단치에 덜 민감한 경향이 있다.

<Z score Scaling>

valuevaluemeanSDvalue\rightarrow \frac{value-mean}{SD}

<Min-Max Scaling>

valuevalueminmaxminvalue\rightarrow \frac{value-\min }{\max -\min }

Distance

직역하면 거리인 이 표기는 실제 물체 간의 거리가 아닌 observations 간의 이질성을 의미한다. 다르게 이야기해, observations 간의 거리라는 값은 observation간의 특질이 다를수록 커야 하고, 비슷할수록 작아야 한다.

물론 완벽하게 이 이상적 거리를 잴 수 있는 방법이 있는 건 아니지만, 적어도 몇 가지 그럴듯한 시도방법은 제시되고 있다.

가장 간단한 형태의 거리는 유클리디안 거리(Euclidean Distance Measure) 혹은 노름(Norm)이다. 학창 시절 때 두 점 사이의 거리를 구하는 공식을 임의의 차원으로 확장시켰다고 보면 된다. 즉, feature가 몇 개이든, 유클리디안 거리는 아래의 공식을 통해 구할 수 있다.

d(X,Y)=j=1n(xjyj)2,d(X,Y)=\sqrt{\sum _{j=1}^n\left(x_j-y_j\right)^2},

where X:(x1,x2,x3xn)where\ X:(x_1,x_2,x_3⋯x_n)

다만, 이 방법은 흔히 '차원의 저주'라고 불리는 현상에 의해 약간의 문제가 생긴다.

어릴 적 가지고 노는 공과 막대 모형을 생각해 보자. 막대와 공을 단순히 직선으로 연결하든, 혹은 공의 위아래, 오른쪽 왼쪽, 앞 뒤에 또 다른 공을 넣어 꽉 찬 상자 모양으로 만들든, 모든 공은 서로의 이웃과 동일한 한 막대 거리에 있는 것이나 다름없다.

문제는 유클리디안 거리 공식을 도입할 때이다. 직선 공 모형에선 이 거리가 1막대기이지만, 만약 3차원 공 모형의 거리를 재보려 한다면 루트3이 된다. 쉽게 말해, feature가 늘어날수록 유클리디안 거리는 observation 간의 유사도와 관계없이 루트n배만큼 계속 늘어나기만 한다는 것이다. 이렇게 되면 observations 간의 거리가 점점 팽창하면서 알고리듬이 올바르게 이들 간의 관계나 패턴을 잡아내기 힘들어질 수도 있다.

이 문제를 해결하는 방법은 여러 가지가 있는데, 위의 차원의 저주 문제를 해결하는 방법으로 코사인 유사도 방법이 있다. 코사인 유사도는 쉽게 말해 두 observation 사이의 각도이다. 조금 더 정확히는 각도의 코사인(cosine) 값인데, 이 값은 두 observation를 표현하는 벡터의 내적에 포함되어 있다. 다만, 내적은 벡터의 크기 또한 포함하기에, 그 값을 나누어 표준화해야 한다. 공식은 다음과 같다.

d(x, y)=1xyxyd(\mathbf{x},\ \mathbf{y})=1-\frac{\mathbf{x}\cdot \mathbf{y}}{||\mathbf{x}||\cdot ||\mathbf{y}||}

x, y 사이의 점이 내적 기호이고, ||x||는 x의 벡터 크기, 즉 x가 원점으로부터 떨어진 거리를 의미한다. 1에서 코사인 유사도를 뺀 이유는 우리가 정의하는 게 거리(즉 비유사도)이기 때문이다.

이 코사인 유사도도 사실 문제가 좀 있는데, 코사인 유사도는 '각도'만 볼 뿐 '거리'를 보지 않기 때문이다. 마치 눈 앞의 책이 뒤의 빌딩을 가리기 때문에 이 둘이 '가까이' 있다고 보는 것과 같다. 즉, 코사인 유사도는 우리가 상식적으로 생각하는 거리와는 조금 다르다.

Clustering이란

K-Means Clustering은 Clustering 알고리듬 중에서도 직관적이고 간단한 것으로 유명한 알고리듬이다. 그렇지만 K-Means에 대해서 다루기 전에, 먼저 Clustering 알고리듬이 정확히 무엇인지부터 다루어야 할 것이다.

클러스터링의 정의

먼저, Cluster가 무엇인지부터 생각해 보자. 아주 상식적으론 뭔가 '몰려 있는 것'이다. 조금 더 추상적으론 '비슷한 것끼리는 가까이 있고 다른 것끼리는 멀리 있는 것'일 것이다. 즉, 하나의 클러스터 속 모든 개체는 하나의 대표적 성질로 대표되고, 그 밖의 개체는 다른 클러스터의 대표적 성질로 설명되는 것이다. 여기서 이 클러스터를 대표하는 성질(즉 점 혹은 자료)를 center, 혹은 centroid라고 부른다.

군집화(Clustering)는 이런 군집의 개념을 기반으로, 군집 내 개체들의 거리를 최소화하고, 서로 다른 군집 간 거리를 최대화하도록 군집을 설정하는 작업이다. 물론 군집화를 예측에도 활용할 수 있지만, 본질적으론 군집화는 데이터 속 패턴 인식(즉, sample 내 분석)이 목적이다.

클러스터링의 응용

Clustering은 여러 application이 있는데, 몇 가지만 소개하도록 하겠다.

  1. 고객 Segmentation과 Target Marketing에 자주 사용된다. 쉽게 말해, 고객의 구매 패턴을 기반으로 고객들을 Segment라는 군집으로 분류하고, 각 고객 Segment에 맞는 광고를 하는 것이다. 관심도 없는 상품에 대해서 지겹도록 광고하는 것보단, 관심 있을 법한 광고를 몇 번만 하는 게 더 효과적이기 때문에 이러한 프로세스는 마케팅에서 매우 유용하게 활용된다.

  2. 한편, 교차 판매 또한 Clustering을 통해 가능한데, 쉽게 말해 비슷한 고객층은 비슷한 물건을 살 것이라고 생각하는 영업 방식이다. 철수와 민수가 둘다 대학교를 다니는 20대 남성이고 서울 중구에 거주하며 자취를 하며, 철수가 화장지-비누-라면-인스턴트밥을 샀고 민수가 화장지-인스턴트밥만을 샀다면, 민수에게 비누와 라면을 살 것을 권유할 수 있다. 그러면 아무 사람에게나 비누, 라면을 권유하는 것보단 더 높은 확률로 민수는 살 가능성이 있다.

  3. 금융 머신러닝이니 금융 이야기도 하나 곁들이면 좋을 것 같다. 흔히 portfolio segmentation이라고 불리는 기법이 있는데, 이건 주식 같은 투자 종목들을 비슷한 것끼리 클러스터링하는 방법이다. 제대로 클러스터링이 되었다면, 다른 클러스터 속 종목들을 여러 개 섞어서 투자 위험을 더 효과적으로 분산시킬 수 있다. 교수님 말씀으로는 난이도가 높은 작업이라 아직 그렇게 활발하게 다루어지는 분야는 아니라고 한다.

K-Means Clustering

이제 K-Means Clustering에 대해서 본격적으로 다룰 필요가 있을 것 같다. 생각보다 K-Means는 단순하게 작동한다.

먼저, 정해진 K개의 군집 수에 대하여, 다음과 같은 프로세스를 진행한다.

  1. Feature Scaling

  2. K개의 군집 Centroid(feature 개수만큼의 원소를 가진 벡터)를 아무 곳이나 선택

  3. 모든 observation들에 대해서, 자신과 가장 가까운 Centriod를 찾아 그 군집에 포함

  4. 한 군집에 포함된 observation들의 feature를 평균내어 Centriod를 업데이트

  5. 군집의 centriod가 충분히 바뀌지 않을 때까지 3-4를 반복

생각보다 간단하고 직관적인 이 방법은 우리가 흔히 아는 덩어리 모양 클러스터를 잘 잡아낸다.

문제와 해결책

물론 간단한 만큼 문제가 꽤 있는 방법이다.

  1. 미리 알 수도 없는 K를 하나 정해야 한다.

  2. 초기의 군집 Center를 임의로 정하기 때문에, 여러 번 클러스터링을 하면 그 때마다 계속 다른 결과를 볼 수도 있다.

  3. 다양한 형태의 군집 중에 덩어리 모양(원, 구, 혹은 초구 형태)의 군집밖에 못 잡아낸다.

여기서 각 문제에 대한 해결책(?)이 있기는 하다. 그 중 특히, K를 선택하는 경험적 방법으로 Elbow Method와 Silhouete Method라는 휴리스틱 방법론이 있다.

Elbow Method

Elbow Method는 클러스터 수가 늘어남에 따라 군집 center와 observations 간의 평균 거리가 급격히 줄어드는 클러스터 개수를 K로 선정하는 방법이다. 조금 더 상세하게는, 클러스터를 늘려감에 따라 모든 클러스터의 inertia의 합이 급격히 낮아지는 클러스터 개수를 K로 선정하는 것이다. k 클러스터의 intertia는 아래와 같이 계산한다.

inertiak=jdj(k)inertia_k=\sum _j^{ }d_j^{(k)}

dj(k)d_j^{(k)}

이러한 경향성을 보기 위해 x축에 클러스터 수, y축에 intertia 합을 둔 플롯을 scree plot이라고 부른다.

Silhouete Method

Silhouete Method는 각 observation의 실루엣 점수(Silhouete Score)라고 정의한 값의 평균이 가장 커지도록 하는 K를 찾는 방법이다. 실루엣 점수는 아래와 같이 계산한다.

s(i)=b(i)a(i)max[a(i),b(i)]s(i)=\frac{b(i)-a(i)}{\max [a(i),b(i)]}

여기서, a(i)는 i번째 observation이 같은 클러스터 내의 다른 observation과 떨어진 평균 거리이고, b(i)는 i번째 observation이 다른 클러스터 내의 다른 observation과 떨어진 평균 거리 중 가장 작은 값이다. 쉽게 말해, s(i)는 i번째 개체 입장에서 가장 가까운 다른 클러스터와의 평균 거리가 멀어지고 자신의 클러스터 내 이웃들과 평균 거리가 짧아질수록 커진다.

실습

실습 목표

실제 데이터를 기반으로 K-Means 클러스터링을 적용하고, 군집 수 K나 초기조건 등 모형 선택 과정을 복습해 보자.

데이터 다운로드

데이터셋 다운로드

위 데이터셋은 여러 국가들의 이름과 함께 실질GDP 성장률, 평화지수, 부패지수, 법치지수 등 4개의 feature를 담고 있는 데이터셋이다. 평화지수는 높을수록 평화롭지 않은 나라이고(1-5), 부패지수는 높을수록 청렴하며(0-100), 법치지수는 높을수록 법적인 위험이 없는 나라이다(0-10).

데이터셋 탐색

K-Means 클러스터링은 scikit learn에 구현되어 있기에, 간단한 코드로 구현할 수 있다. 하지만 그 전에, 대충 기본적인 데이터 탐색은 필수적이다.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

data = pd.read_csv("country risk 2019 data.csv")

X = data.loc[:, ["Corruption", "Peace", "Legal", "GDP Growth"]]

#각 feature에 대한 기술통계량 보기
print(X.describe())

#상관관계 히트맵 그리기
sns.heatmap(data.corr(), vmin=-1, vmax=1, annot=True)
plt.show()


일단 위의 분석 결과로 알 수 있는 사실은 크게 두 가지이다.
첫째로 feature 간의 분산 차이나 평균 차이가 너무 크다. 이건 feature로 사용된 지수가 원래부터 규모와 위치에 차이가 있기 때문이다. 예를 들어 지수가 5점 만점인 경우하고 100점 만점인 경우의 차이를 생각해 보면 된다. 이런 구조적인 차이로 인해 feature scaling이 필요할 것으로 보인다.
둘째로, 상관계수 중 Legal하고 Corruption feature 간의 상관관계수가 매우 높다. 상관관계가 0.94이면 이론적인 상관관계는 거의 1과 일치한다고 봐도 무방하다. 즉, 한 feature를 갔다 버리는 feature selection이 필요한 것이다. 이 두 문제를 좀 해결해 보자.

데이터 전처리

X = (X-X.mean())/X.std()
X = X.drop("Corruption", axis=1)

사실은 둘을 하나씩 버려가면서 어느 쪽이 더 좋은 성능이 나오는지를 따져봐야 하지만, 상관계수가 워낙에 높아서 사실 둘 중 어느 걸 버려도 크게 상관없다고 간주하였다.

모형 선택

이제 여러 K와 초기조건을 가지는 K-Means 중 하나를 택해야 하는 상황인데, 먼저 K의 선정부터 시작하여 앞에서 다룬 실루엣 스코어와 interia 두 가지를 한번 참조해 보도록 하겠다.

from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans

scores = {}


for c in range(2, 10):
    
    model = KMeans(n_clusters=c)

    labels = model.fit_predict(X)
    scores[c] = silhouette_score(X, labels)

print(f"Cluster Number with Highest Score: {max(scores, key=scores.get)}")
plt.plot(scores.keys(), scores.values())
plt.show()

Cluster Number with Highest Score: 3

scores = {}

before = 0

for c in range(2, 10):
    
    model = KMeans(n_clusters=c)

    inertia = model.fit(X).inertia_
    
    if c < 3:
        before = inertia
        
        continue
        
    else:
        scores[c] = inertia - before
        before = inertia
        
print(f"Cluster Number with Lowest Inertia Change: {min(scores, key=scores.get)}")

Cluster Number with Lowest Inertia Change: 3

잘 보니, 하이퍼 파라미터인 클러스터 개수 K는 3으로 잡는 게 적절해 보인다.

결과 해석

이렇게 3개의 클러스터를 잡아 그 centroid를 계산해 보면 아래와 같다.

k = 3

model = KMeans(n_clusters=k)
labels = model.fit_predict(X)

labels = labels - min(labels)

X1 = X.copy()

X1["label"] = labels

centroids = {}

def calculateCentroids(data, label):
    
    return data[data["label"]==label].mean()

for n in range(k):
    
    
    centroids[n] = calculateCentroids(X1, n)
    
centroids = pd.DataFrame(centroids).T

print(centroids)

결과를 보면, label 0은 비교적 평화롭고, 법적 위험이 적으며, GDP 성장률이 평균보다 조금 작은 나라들의 클러스터이다. label 1은 평균적인 평화로움과, 큰 법적 위험, 높은 GDP 성장률을 보이는 국가들의 클러스터이다. 마지막 클러스터 (label 2)는 성장률도 낮고, 매우 평화롭지 않고 법적 위험도 큰 국가들의 클러스터이다. 즉, label 0->1->2 순으로 투자 리스크가 큰 국가인 셈이다.

각 클러스터에 속한 국가는 아래 코드로 확인할 수 있다.


labeled = data.iloc[:, :2].copy()
labeled["label"] = labels

def listValues(data, label):
    
    return data[data["label"]==label]["Country"].values


for n in range(k):
    
    print(f"\n Contries in label {n}\n")
    
    contriesList = listValues(labeled, n)
    
    print(contriesList)

다른 클러스터링 방법론들

K-Means만이 유일한 클러스터링 알고리듬은 아니다. 그 이외에도 여러 가지 알고리듬들이 있는데, 그 중 대표적인 것들을 몇 개 짚고 넘어가고자 한다.

K-Means ++

이건 사실 위의 실습에서도 자동으로 사용된 방법인데, K-Means의 초기 중심값 설정 방법을 한 단계 업그레이드한 것이다. K-Means ++에서는 다음과 같이 초기 중심값을 설정한다.

  1. observation 중 하나를 임의의 초기중심 c1c_1
  2. 다른 observation들과 c1c_1
  3. c3c_3
  4. 마지막 K번째의 분포 중심을 구할 때까지 1-3을 반복.

Hierarchical Clustering (계층적 군집)

계층적 군집은 지금 현재의 군집을 쪼개거나 합치면서 새로운 군집으로 나누는 방법이다. 계층적 군집의 한 방법인 결합적 군집은 초기에 모든 데이터포인트를 한 군집으로 보고 가까이 있는 것끼리 합쳐나가는 방식이라면, 분할적 군집은 전체를 한 군집으로 본 후 멀리 있는 것들끼리 분리하는 방식이다. 들어보면 결합적 군집이 훨씬 쉬워보이는데, 그래서 사실 결합적 군집인 Hierarchical Agglomerate Clustering (HAC)를 더 많이 사용한다.

Dendrogram

observation 개수가 충분히 적다면, dendrogram이라는 그림을 통해 클러스터링이 각 군집 개수에 따라 어떻게 이루어지는지를 손쉽게 확인할 수 있다. dendrogram는 일종의 나무 그림인데, 데이터들이 HAC의 작동 과정에서 어떻게 합쳐지는지를 한눈에 확인할 수 있다.

그림을 보면 가로줄을 그었을 때 나타나는 트리와의 교점 개수(즉, 클러스터 개수)에 따라, 각 클러스터에 해당하는 교점을 따라 아래로 내려갔을 때 각 클러스터가 가지고 있는 observation들을 확인할 수 있다. 너무 부족한 개수의 observation만 있는 클러스터가 많다면, 그 클러스터링은 과도하게 잘게 나눈 것으로 해석 입장에선 별로 좋은 결과가 아닐 수도 있다.

군집 결합 방식

HAC은 작동할 때 두 군집이 합쳐져야 할지 말지를 결정해야 한다. 이 때, 가장 가까운 두 군집을 합치는 방식으로 진행할 때, 그 두 군집 간의 거리를 정의해야 한다. 이 거리는 아래와 같은 방식들로 정의될 수 있다. 필요에 따라 이들 중 하나를 선택하면 된다.

  • 완전연결 군집: 두 군집 속 observation 간의 거리 중 최댓값
  • 단일연결 군집: 두 군집 속 observation 간의 거리 중 최솟값
  • 평균연결 군집: 두 군집 속 observation 간의 거리의 평균
  • 중심연결 군집: 두 군집의 centroid 간의 거리
  • Ward's Method: 두 군집을 합쳤을 때의 centroid와 군집 내 observation 간의 거리의 합과 두 군집 따로따로의 centroid와 군집 내 observation 간의 거리의 합의 차

DBSCAN

DBSCAN의 원리는 높은 밀도로 모여 있는 observation들을 중심으로 군집을 형성하는 방식으로 진행한다. DBSCAN에선 모든 observation을 세 가지 중 하나의 종류로 분류하는데, 각각은 아래와 같다.

  • 핵심자료: 반경 ϵ\epsilon 안에 MM개 이상의 observation이 있는 observation
  • 주변자료: 반경 ϵ\epsilon 안에 핵심자료를 가지고 있지만 스스로는 핵심자료가 아닌 observation
  • 잡음자료: 핵심자료도 주변자료도 아닌 자료

DBSCAN는 위와 같은 분류를 기반으로 아래와 같이 작동한다.

  1. 아무 observation x을 고르고, 그 x가 핵심자료이면 그 주변 자료들과 자신을 클러스터 1로 설정. 클러스터 1안에 또 다른 핵심자료가 있으면 그 주변자료도 전부 클러스터 1로 설정. 만약 x가 핵심자료가 아니라면 임시로 클러스터 1인 잡음자료로 설정.
  2. 군집 2를 만들기 위해 1 반복
  3. 모든 자료가 특정 군집의 원소나 noise로 분류될 때까지 2 반복.

DBSCAN의 하이퍼파라미터

ϵ\epsilon

엡실론은 사실 정하기가 까다로운 파라미터이다. 이 값이 너무 작으면 너무 많은 관측치가 noise가 되고, 너무 크면 군집의 개수가 과도하게 적어진다. 어떤 Paper를 보면 observation 간의 거리를 계산하여 작은 순서대로 나열했을 때, 갑자기 급등하는 지점의 거리가 적절하다고 보는 휴리스틱은 있다.

M

다행인지는 모르겠지만 M는 흔히 쓰는 관례가 있는데, feature 개수에 1을 더한 값을 사용하는 것이다.

정리

  • 클러스터링은 비지도학습 기법 중 하나로, 비슷한 성격의 데이터포인트끼리 묶는 작업이다.
  • 클러스터링은 데이터 탐색적인 성격이 크다.
  • K-Means, HAC, DBSCAN이 있다.

좋은 웹페이지 즐겨찾기