심심해서 하는 블로그 :: [Python]DBSCAN 클러스터링 (with 카톡 대화)

Github > https://github.com/ssooni/data_mining_practice

- 자세한 소스코드는 Github에 올렸습니다.

- 데이터 파일도 올려 드리고 싶지만 실제 카카오톡 대화내용이라 일부분만 올렸습니다.

- 소스코드는 짬짬히 업로드할 예정입니다.




클러스터링

비지도학습의 대표 주자인 클러스터링은 각각의 노드들의 군집들을 산출해줍니다.

그 중에서 가장 간단한 게 K-means 알고리즘이고, 때마침 학교에서 공부한 적이 있으니까 해봐야겠다는 생각을 했습니다. 

하지만 이 알고리즘은 클러스터가 몇 개 나올것이다는 것을 제가 직접 설정해야 하는 점이 마음에 안들었습니다.

지금 Input으로 들어오는 벡터는 300차원이라 어디에 군집에 형성되어 있는지 짐작하기 어렵기 때문에 K-means 알고리즘은 사용하기 어렵다고 판단하였습니다.

저는 군집 갯수를 사전에 설정하지 않아도 군집을 산출해주는 알고리즘이 필요했고, 그 결과 DBSCAN 알고리즘을 선정하였습니다.


DBSCAN 

DBSCAN은 밀도 기반의 클러스터링 기법입니다.

DBSCAN의 클러스터는 아래 두 가지 조건에 의해 생성됩니다.


1. 이웃하는 점들의 간격이 사용자가 정한 거리(eps) 이내에 있는 경우를 산출

2. 군집에 포함하는 점들이 최소 클러스터 원소 수(min_samples)보다 많은 경우를 산출합니다.

min_sample = 3 인 경우


Core Point는 1번 조건과 2번 조건을 모두 충족하는 Point를 의미합니다. (빨간 점) 

Non-Core Point는 1번 조건을 만족하지만 2번 조건을 만족하지 못하는 Point입니다. (파란 점)

Non-Core Point는 Cluster를 이루는 경계 점 역할을 합니다.

Noise는 2개의 조건을 모두 만족하지 않은 경우로 클러스터를 구성하지 않습니다. (녹색 점)


이런 방법으로 클러스터를 찾는 것의 장점은 클러스터의 갯수를 지정할 필요 없다원형이 아닌 클러스터도 추출이 가능하다는 점입니다.

다른 알고리즘은 클러스터의 중심점을 이동하면서 클러스터 중심점 내부에 몇개의 점이 들어 있는 가에 집중되어 있기 때문에 클러스터의 모양이 필연적으로 원형으로 형성됩니다.

하지만 DBSCAN은 각각 개별 포인트 간의 거리를 측정하면서 Non-Core Point에 의해 클러스터의 경계가 형성되기 때문에 원형이 아닌  모양의 클러스터도 형성이 가능하다는 점이 장점입니다.


하지만 데이터에 대한 충분한 이해도를 가지고 있지 않는다면 eps와 min_points 값을 정하는 것이 어려운 것이 단점입니다.

다른 알고리즘은 단순히 10개의 분류를 만들어 달라 하면 10개를 만들어 주기 때문에 데이터 내부의 값들을 이해하지 않아도 충분히 클러스터를 만들어 낼 수 있습니다.

하지만 DBSCAN은 적어도 포인트 간이 이루는 최대 거리가 얼마인지 정도는 파악해야 유효한 클러스터를 만들어 낼 수 있습니다.


Word Vector Clustering

워드 백터를 클러스터링하면 어떤 결과가 나올까? 하는 의문에서 시작하였습니다.

모든 코드는 GitHub를 참조바랍니다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from sklearn.cluster import DBSCAN
from gensim.models import Word2Vec
 
def cluster(eps, min_sample):
    # Word Vector를 Load 합니다.
    model = Word2Vec.load("./result/embedding.model")
 
    word_vector = model.wv.vectors
    match_index = model.wv.index2word
    model.init_sims(replace=True)
 
    # 두 글자이상 한글인 경우만 사용
    han = re.compile(r"[가-힣]{2,}")
 
    # DBSCAN 알고리즘 적용
    dbscan = DBSCAN(eps=eps, min_samples=min_sample)
    clusters = dbscan.fit_predict(word_vector)
 
    df = pd.DataFrame(clusters, columns=["cluster"], index=match_index).reset_index()
    df.columns = ["word""cluster"]
    print(df.head())
 
    # 한글만 필터링 처리
    df = df[df["word"].apply(lambda x: len(han.findall(x)) > 0)]
 
    # 노이즈 포인트 제거
    df = df[df["cluster"!= -1]
 
    print(df.groupby(["cluster"]).count())
 
    df.to_excel(pd.ExcelWriter("./result/cluster.xlsx"), index=False)
 
cs


line 15-16

본격적으로 DBSCAN 알고리즘을 적용하는 부분입니다.

eps와 min_samples를 정하여 넣어준 후 line 16에서 word vector를 클러스터링 해주었습니다.

fit_predict 함수를 사용하면 클러스터링된 결과를 리스트로 산출해줍니다.

이 때 -1은 노이즈 포인트를 의미합니다.


line 23-27

클러스터링 후 데이터를 일부 처리하였습니다.

2글자 이상의 한글만 유효한 결과로 선정하였으며, 노이즈 포인트도 제거 하였습니다.


이 프로그램을 실행하면 아주 허접한 그래프를 보여주었습니다.


클러스터링을 했을 때 종결 어미나 일자, 직책 같은 정보를 담고 있는 클러스터를 보고 신기했습니다.

뭔가 클러스터링을 하면 전체적인 주제를 알 수 있지 않을까? 생각 했지만 아쉽게도 그런 정보는 나타나질 않았네요.

찾아 보니까 LDA라는 걸 사용하면, 토픽 모델링이 가능하다고 하는데 다음번엔 그것을 시도해볼까합니다.

 

긴 글 읽어주셔서 감사합니다.

공감 버튼은 작성자에게 큰 동기부여가 됩니다.


,