티스토리 뷰

학습목표

- 텍스트 데이터 클러스터링의 기본 개념 이해
- K-Means 알고리즘과 텍스트 데이터에의 활용 방법 학습
- Python을 활용한 간단한 클러스터링 실습

여러분은 인터넷에서 매일같이 엄청난 양의 텍스트를 접하고 있다. 뉴스 기사, 소셜 미디어 글, 영화 리뷰까지, 이 모든 텍스트 데이터는 단순한 글자들의 모음처럼 보이지만, 그 속에는 흥미로운 패턴과 이야기가 숨어 있다.

예를 들어, 수천 개의 영화 리뷰를 보고 "이 영화는 정말 재밌다"와 "지루하고 볼 필요가 없다" 같은 의견을 자동으로 분류할 수 있다면 어떨까? 혹은, 비슷한 주제의 뉴스 기사를 한 그룹으로 묶어 관련된 정보를 빠르게 찾을 수 있다면?

이러한 작업이 바로 텍스트 클러스터링이다. 오늘 우리는 이러한 클러스터링의 기본 개념을 배우고, 이를 가능하게 하는 핵심 도구인 K-Means 알고리즘을 직접 다뤄볼 것이다. 어렵게 느껴질 수 있지만, 한 걸음씩 따라오면 여러분도 데이터 속에서 새로운 패턴과 이야기를 발견할 수 있을 것이다.

자, 이제 텍스트 데이터를 탐험하며 그룹의 비밀을 파헤쳐 보자!


1. 텍스트 데이터 클러스터링(Text Data Clustering)

텍스트 데이터 클러스터링이란 비슷한 의미나 주제를 가진 텍스트 데이터를 그룹화하여 유사성을 기반으로 클러스터(집단)를 생성하는 비지도 학습 기법이다.
주로 라벨이 없는 데이터에서 사용되며, 데이터 간의 패턴구조를 발견하는 데 도움을 준다.

1.1 텍스트 데이터 클러스터링의 목적

  1. 유사 텍스트 그룹화: 유사한 주제나 내용을 가진 문서를 동일한 그룹으로 묶어 패턴을 발견한다.
    • 예: 뉴스 기사에서 정치, 경제, 스포츠와 같은 주제를 자동으로 분류.
  2. 정보 탐색과 요약: 대량의 데이터를 요약하여 더 효율적으로 정보를 탐색할 수 있도록 돕는다.
    • 예: 고객 리뷰를 긍정, 부정, 중립으로 그룹화.
  3. 데이터의 이해도 향상: 데이터를 시각화하거나 요약하여 데이터에 대한 더 깊은 통찰을 얻는다.

1.2 텍스트 데이터 클러스터링의 주요 특징

  • 고차원 데이터: 텍스트는 수백, 수천 개의 단어로 이루어져 있어 데이터 차원이 매우 높다.
  • 희소성(Sparsity): 대부분의 문서에서 특정 단어는 나타나지 않기 때문에 데이터의 대부분이 0으로 구성된다.
  • 비지도 학습: 사전에 레이블이 없는 상태에서 데이터의 구조를 분석하여 패턴을 발견한다.

1.3 텍스트 데이터 클러스터링의 단계

  1. 텍스트 데이터 전처리 : 텍스트 데이터를 클러스터링하기 전에 컴퓨터가 이해할 수 있는 형태로 변환해야 한다.
    • 토큰화(Tokenization): 문서를 단어 단위로 나누기.
    • 불용어 제거(Stopword Removal): 의미가 적은 단어(예: the, and, of) 제거.
    • 어간 추출(Stemmer) 또는 원형 복원(Lemmatization): 단어의 기본 형태로 변환.
    • TF-IDF 벡터화: 텍스트 데이터를 수치 벡터로 변환.
  2. 유사성 측정 : 텍스트 데이터의 유사성을 측정하는 방법:
    • 코사인 유사도(Cosine Similarity): 각 텍스트 벡터 간의 각도를 사용하여 유사성을 계산.
    • 유클리드 거리(Euclidean Distance): 벡터 간의 물리적 거리를 계산.
  3. 클러스터링 알고리즘 적용 : 텍스트 데이터를 K-Means와 같은 알고리즘으로 클러스터링:
    • 각 클러스터는 데이터의 공통된 특징(주제나 키워드)을 나타냄.
  4. 결과 시각화 및 해석
    • 차원 축소(PCA, t-SNE) 기법을 사용하여 데이터를 2D 또는 3D로 축소한 후 시각화.
    • 각 클러스터에서 자주 등장하는 단어를 분석하여 그룹의 특징을 정의.
🗺️ 여행 지도 이야기 - 차원축소란?
너와 친구들이 세계 여행을 계획하고 있다고 해보자. 친구들은 각자 자신이 가고 싶은 곳을 리스트로 정리했어. 그런데 문제는, 모두의 리스트를 합쳐보니 100개 이상의 도시가 나왔어! 이렇게 많으면 어디부터 가야 할지 감이 안 오겠지?
그래서 비슷한 곳끼리 그룹을 묶어 몇 개의 대표 여행지로 줄이기로 했어.
예를 들어:
파리는 로마, 런던과 비슷하니까 "유럽 여행지" 그룹으로 묶고
뉴욕, LA, 시카고는 "미국 여행지" 그룹으로 묶고
도쿄, 서울, 상하이는 "아시아 여행지" 그룹으로 묶는 거야.
이렇게 하면 전체 여행지를 100개에서 3~5개 정도의 대표 지역으로 단순화할 수 있어.
차원 축소 기법(PCA, t-SNE)이 하는 일도 이와 비슷해!
데이터가 너무 많을 때, 비슷한 것들을 묶고 가장 중요한 정보만 남겨서 한눈에 볼 수 있게 2D 또는 3D 공간으로 시각화해 주는 거야.

🌟 PCA와 t-SNE 차이
- PCA (주성분 분석)데이터를 가장 중요한 방향(축)으로 정리하여 차원을 줄이는 방법이야.데이터를 직선적으로 변형해서 중요한 축을 찾아 단순화해.박스를 크기별로 정리하는 것과 비슷해. (데이터를 정리정돈!)
- t-SNE (티-스니)데이터의 "유사한 관계"를 보존하면서 2D나 3D로 줄이는 기법이야.특히 클러스터(비슷한 데이터끼리 묶음)를 잘 만들어 줘.여행지를 그룹별로 묶어서 쉽게 이해할 수 있도록 도와주는 것과 비슷해.

여기서 잠깐!

1.코사인 유사도(Cosine Similarity)

코사인 유사도는 두 개의 문서를 벡터로 변환한 후, 두 벡터 사이의 각도를 비교하여 얼마나 비슷한지를 측정하는 방법이다.
각도가 0도에 가까울수록 유사성이 높고, 90도에 가까울수록 유사성이 낮다.

예제: 하나의 문장을 하나의 벡터라고 생각해보자. 만약 아래와 같은 두 개의 문장이 있다면:

  • 문장 1: "나는 오늘 날씨가 좋다고 생각해."
  • 문장 2: "오늘 날씨가 좋아서 기분이 좋아."

이 두 문장은 "오늘", "날씨", "좋" 같은 공통적인 단어들을 포함하고 있다.
이제 벡터를 만들면 아래처럼 변환할 수 있다.

단어 문장1 문장2
나는 1 0
오늘 1 1
날씨 1 1
좋다 1 1
생각하다 1 0
기분 0 1

이 벡터들을 이용하여 두 벡터 사이의 코사인 각도를 구하면, 공통된 단어들이 많을수록 유사도가 높게 나온다.

📌 즉, 코사인 유사도는 같은 의미의 단어가 많이 포함될수록 높은 값을 가지므로, 비슷한 문장일수록 유사도가 커진다!

2.유클리드 거리(Euclidean Distance)

유클리드 거리는 두 점(벡터)의 실제 거리를 측정하는 방식이다. 두 문장을 벡터로 변환한 후, 숫자로 표현된 값들 사이의 거리를 구하면 된다.

유클리드 거리는 두 점 사이의 거리를 계산할 때 흔히 쓰는 방법이다. 이는 피타고라스 정리를 기반으로 한다.

#math.sqrt 함수를 사용하여 두 점 간의 유클리드 거리를 계산한다.
import math

# 두 점의 좌표
x1, y1 = 1, 2
x2, y2 = 4, 6

# 유클리드 거리 계산
distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
print(f"Euclidean distance: {distance}")

예제: 같은 예제를 사용해보자. 문장 1과 문장 2를 벡터로 표현했을 때, 만약 아래와 같이 단어 빈도를 기반으로 수치화된 벡터가 있다고 가정하자.

  • 문장 1 벡터: (1, 1, 1, 1, 1, 0)
  • 문장 2 벡터: (0, 1, 1, 1, 0, 1)

이 값이 작을수록 두 문장이 더 가깝고, 값이 클수록 두 문장이 더 다르다는 의미이다

📌 즉, 유클리드 거리는 문장 간의 물리적 차이를 측정하는 방법으로, 값이 작을수록 문장이 비슷하다는 뜻이다.

정리

측정 설명 특징
코사인 유사도 단어 벡터 간의 각도를 비교 공통 단어가 많을수록 유사도가 높음
유클리드 거리 벡터 간의 물리적 거리 측정 값이 작을수록 문장이 더 비슷함

 


2. K-Means 알고리즘과 텍스트 데이터

여러분은 친구들과 함께 새로 문을 연 카페에 방문했습니다. 카페 안에는 다양한 크기와 모양의 테이블이 여기저기 흩어져 있습니다. 이제 여러분의 목표는 가까운 테이블끼리 묶어 그룹을 만드는 것입니다.

이 작업이 바로 K-Means 알고리즘이 하는 일입니다! 데이터를 가까운 것끼리 묶어 그룹(클러스터)을 만드는 알고리즘입니다.

2.1 K-Means 알고리즘 개요

K-Means는 데이터 포인트를 K개의 클러스터로 나누는 거리 기반 알고리즘이다.
각 데이터 포인트를 가장 가까운 클러스터 중심에 할당하여 그룹을 형성하고, 이를 반복적으로 최적화하는 방식으로 동작한다.

  • 알고리즘 작동 원리: K-Means는 주어진 데이터셋을 K개의 클러스터로 나누는 비지도 학습 알고리즘입니다. 각 클러스터는 중심점(centroid)을 기준으로 형성됩니다 
    1. 초기 K개의 중심점을 랜덤으로 선택합니다.
    2. 각 데이터 포인트를 가장 가까운 중심점에 할당하여 클러스터를 형성합니다.
    3. 각 클러스터의 중심점을 재계산하고, 이 과정을 반복하여 클러스터가 안정될 때까지 진행합니다 .
  • K-Means 알고리즘의 장단점 
구분 장점 단점
특징 간단하고 구현이 쉬움 K 값(클러스터 개수)을 사전에 지정해야 함
성능 비교적 빠르게 동작하며 대규모 데이터에 적합 초기 중심값에 따라 결과가 달라질 수 있음
효율성 적은 계산 자원으로도 결과를 도출 가능 고차원 데이터에서 성능이 저하될 수 있음 (차원 저주 문제)
  • K 값 선택의 중요성 
    • 적절한 K 값 찾기 : K 값이 너무 작으면 중요한 세부 그룹을 놓칠 수 있으며, K 값이 너무 크면 클러스터링 결과가 지나치게 세분화됨
  • K 값 선택 방법 
    • 엘보우(Elbow) 기법: WCSS를 계산하여 K 값에 따른 감소율이 완만해지는 지점을 선택. 데이터를 2개의 그룹으로 나누는 것이 효율적인지, 아니면 3개나 4개로 나누는 것이 더 나은지 확인할 때 유용하다.
      ( "빵을 자르는데 몇 조각으로 자르는 게 효율적일까?" 빵 조각 수가 많아질수록 효율이 조금씩 줄어드는데, 가장 적당히 나누는 지점을 찾는 것과 비슷하다.)
    • 실루엣 점수(Silhouette Score): 클러스터 간 분리도와 응집도를 측정. 데이터 포인트가 얼마나 잘 클러스터링 되었는지 나타내는 점수. 실루엣 점수는 -1에서 1 사이 값을 가지며, 1에 가까울수록 클러스터링이 잘된 것으로 간주.
      ( "학교 반을 나누는데, 반 친구들이 얼마나 잘 어울리는지 측정한다." 점수가 높을수록 반 친구들끼리 더 잘 어울리는 반편성을 했다고 볼 수 있다.)

  • 텍스트 데이터에 K-Means 적용하기
    • 텍스트 전처리: 텍스트 데이터를 K-Means에 적용하기 위해서는 먼저 데이터를 벡터화해야 합니다. 일반적으로 TF-IDF(Term Frequency-Inverse Document Frequency)나 Count Vectorizer를 사용하여 단어의 중요도를 수치화합니다 
    • 고차원 데이터: 텍스트는 단어의 개수만큼 차원이 높아지며, 데이터가 희소(sparse)한 특징을 가짐.

과정

  1. 텍스트 전처리:
    토큰화, 불용어 제거, 어간 추출 등을 수행.
  2. 벡터화:
    텍스트를 수치형 데이터로 변환(TF-IDF, Word2Vec 등).
  3. K-Means 적용:
    벡터화된 데이터를 기반으로 K개의 클러스터로 분류.
    벡터화된 데이터를 K-Means 알고리즘에 입력하여 클러스터를 생성합니다. 이 과정에서 각 문서가 어떤 클러스터에 속하는지를 파악할 수 있습니다 
  4. 결과 해석:
    각 클러스터의 주요 키워드를 분석하여 그룹의 의미를 파악.
    클러스터링 결과를 통해 유사한 주제를 가진 문서들을 그룹화할 수 있으며, 이를 통해 데이터의 패턴이나 주제를 분석할 수 있습니다.

2.2 K-Means 알고리즘의 작동 방식: 테이블 그룹화

Step 1: 그룹 개수(K) 정하기

먼저, 여러분은 테이블을 몇 개의 그룹으로 나눌지 결정해야 합니다. 예를 들어, K=3이라고 하면, 3개의 그룹을 만들어야 합니다.

Step 2: 초기 중심(센터) 정하기

테이블 그룹의 중심을 임의로 3개 지정합니다. 처음에는 아무 테이블이나 무작위로 선택합니다.

  • 예: A, B, C 테이블을 각 그룹의 중심으로 선택.

Step 3: 테이블을 가까운 중심에 할당

모든 테이블에서 가장 가까운 중심을 계산하여 해당 그룹에 속하게 합니다.

  • 가까운 중심은 테이블 간 거리(예: 유클리드 거리)를 사용해 계산합니다.
  • 예:
    • 테이블 X는 A와 가깝다면 그룹 1에 속합니다.
    • 테이블 Y는 B와 가깝다면 그룹 2에 속합니다.

Step 4: 중심 업데이트

모든 그룹의 테이블의 평균 위치를 계산해 새로운 중심을 정합니다.

  • 예: 그룹 1의 테이블 위치를 평균내어 A의 위치를 업데이트합니다.

Step 5: 다시 할당

새로운 중심에 따라 테이블을 다시 가까운 중심으로 할당합니다.

Step 6: 반복

이 과정을 중심이 더 이상 변하지 않을 때까지 반복합니다.

  • 결국, 테이블이 K개의 그룹으로 나뉘게 됩니다.

2.3 K-Means 알고리즘의 예시

아이스크림 가게에서 고객의 주문을 분석한다고 가정합니다.

Step 1: 데이터 준비 : 고객 주문 데이터를 다음과 같이 벡터화합니다

고객 딸기 초코 바닐라
A 5 1 0
B 4 2 1
C 0 4 5
D 1 5 4
# Step 1: 데이터 준비
import numpy as np

# 고객 주문 데이터를 배열로 정의
customers = {
    'A': [5, 1, 0],
    'B': [4, 2, 1],
    'C': [0, 4, 5],
    'D': [1, 5, 4]
}

# 고객 이름 및 데이터를 배열로 변환
customer_names = list(customers.keys())
data = np.array(list(customers.values()))

print("Step 1: 데이터 준비\n")
print(data)

Step 2: 초기 중심 설정 : 초기 중심을 두 명의 고객(A와 C)로 설정합니다.

  • 중심 1 (A): [5, 1, 0]
  • 중심 2 (C): [0, 4, 5]
# Step 2: 초기 중심 설정
# 초기 중심을 고객 A와 C로 설정
initial_centroids = np.array([customers['A'], customers['C']])
print("\nStep 2: 초기 중심 설정")
print("초기 중심:\n", initial_centroids)

Step 3: 고객 할당 : 각 고객의 데이터를 중심과 비교하여 가장 가까운 중심에 할당합니다.

  • A와 B는 중심 1에 가깝습니다.
  • C와 D는 중심 2에 가깝습니다.
# Step 3: 고객 할당 (유클리드 거리 계산 및 중심 할당)
# 유클리드 거리 계산 함수
def calculate_distance(point, centroids):
    return np.linalg.norm(point - centroids, axis=1)

# 각 데이터 포인트를 가장 가까운 중심에 할당하는 함수
def assign_clusters(data, centroids):
    clusters = []
    for point in data:
        distances = calculate_distance(point, centroids)
        clusters.append(np.argmin(distances))  # 가장 가까운 중심의 인덱스 저장
    return np.array(clusters)

# 초기 중심값을 기준으로 클러스터 할당
clusters = assign_clusters(data, initial_centroids)
print("\nStep 3: 고객 할당")
print("초기 할당된 클러스터:\n", clusters)

Step 4: 중심 업데이트 : 각 그룹의 평균 값을 계산하여 새로운 중심을 만듭니다:

  • 중심 1: 평균([5, 1, 0], [4, 2, 1]) = [4.5, 1.5, 0.5]
  • 중심 2: 평균([0, 4, 5], [1, 5, 4]) = [0.5, 4.5, 4.5]
# Step 4: 중심 업데이트
# 클러스터 내 데이터 평균으로 중심 업데이트 함수
def update_centroids(data, clusters, k):
    new_centroids = []
    for i in range(k):
        cluster_points = data[clusters == i]  # 특정 클러스터에 속한 데이터
        new_centroids.append(np.mean(cluster_points, axis=0))  # 평균 계산
    return np.array(new_centroids)

# 중심 업데이트
k = 2  # 클러스터 개수
centroids = update_centroids(data, clusters, k)
print("\nStep 4: 중심 업데이트")
print("업데이트된 중심:\n", centroids)

Step 5: 다시 할당( K-Means 반복) : 새로운 중심으로 고객 데이터를 재분류합니다.

  • 이 과정을 반복하면, 최종적으로 그룹이 안정됩니다.
# Step 5: K-Means 반복 알고리즘
# 클러스터 할당과 중심 업데이트를 반복하는 함수
def k_means(data, initial_centroids, max_iterations=10):
    centroids = initial_centroids
    for iteration in range(max_iterations):
        clusters = assign_clusters(data, centroids)  # 데이터 할당
        new_centroids = update_centroids(data, clusters, len(centroids))  # 중심 업데이트
        if np.all(centroids == new_centroids):  # 중심값이 변하지 않으면 중단
            break
        centroids = new_centroids
    return clusters, centroids

# 알고리즘 실행
clusters, final_centroids = k_means(data, initial_centroids)
print("\nStep 5: 최종 결과")
print("최종 클러스터 할당:\n", clusters)
print("최종 중심:\n", final_centroids)

Step 6. 결과해석 : 최종 클러스터링 결과를 그룹별로 출력하고 각 그룹의 고객 이름을 표시.

  • 그룹 1: "딸기맛"을 선호하는 고객 (A, B)
  • 그룹 2: "초코맛"과 "바닐라맛"을 선호하는 고객 (C, D)
# 결과 해석
# 각 클러스터에 속한 고객 이름을 출력
cluster_groups = {i: [] for i in range(k)}
for customer_idx, cluster_idx in enumerate(clusters):
    cluster_groups[cluster_idx].append(customer_names[customer_idx])

print("\n[결과]")
for cluster, members in cluster_groups.items():
    print(f"그룹 {cluster + 1}: {', '.join(members)}")
  • numpy를 사용해 데이터와 수학 연산을 간단히 처리.
  • K-Means의 각 단계(데이터 준비, 초기화, 할당, 업데이트)를 함수로 분리.
  • 중심값이 더 이상 변하지 않을 때 알고리즘이 종료.

3. 연습 : "과일 탐정: 과일들의 숨겨진 그룹을 찾아라!"

예제: 과일 설명 분류하기

과일에 대한 짧은 설명들을 K-Means 알고리즘으로 클러스터링하여 비슷한 과일들을 묶는 작업을 해보자!


데이터 준비

과일에 대한 간단한 텍스트 설명이 있다:

descriptions = [
    "Sweet and yellow, often curved",  # 바나나
    "Red and round, sometimes green",  # 사과
    "Small and red, grows in bunches",  # 체리
    "Long and yellow, easy to peel",  # 바나나
    "Green and round, sour taste",  # 라임
    "Round and sweet, color varies",  # 사과
    "Tiny and sweet, used in desserts",  # 체리
    "Yellow and sour, full of vitamin C",  # 레몬
    "Round and green, juicy inside",  # 라임
    "Small and juicy, grows on trees"  # 체리
]

 

  • 위 설명을 클러스터링하여 과일의 종류별로 묶는다.
  • 각 클러스터에서 공통된 단어를 찾아 과일의 특징을 유추한다.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans

# Step 1: 텍스트 데이터 준비
descriptions = [
    "Sweet and yellow, often curved",  # 바나나
    "Red and round, sometimes green",  # 사과
    "Small and red, grows in bunches",  # 체리
    "Long and yellow, easy to peel",  # 바나나
    "Green and round, sour taste",  # 라임
    "Round and sweet, color varies",  # 사과
    "Tiny and sweet, used in desserts",  # 체리
    "Yellow and sour, full of vitamin C",  # 레몬
    "Round and green, juicy inside",  # 라임
    "Small and juicy, grows on trees"  # 체리
]

# Step 2: 텍스트 벡터화
vectorizer = TfidfVectorizer(stop_words='english')  # 불용어 제거
X = vectorizer.fit_transform(descriptions)

# Step 3: K-Means 모델 생성 및 학습
kmeans = KMeans(n_clusters=3, random_state=42)  # 3개의 클러스터 생성
kmeans.fit(X)

# Step 4: 클러스터 결과 출력
print("클러스터 할당:", kmeans.labels_)

# Step 5: 각 클러스터의 주요 키워드 출력
print("\n클러스터 중심 키워드:")
terms = vectorizer.get_feature_names_out()
for i, center in enumerate(kmeans.cluster_centers_):
    keywords = [terms[idx] for idx in center.argsort()[-5:]]  # 중심에서 가장 중요한 단어 5개
    print(f"클러스터 {i}: {keywords}")

# Step 6: 결과 해석
for i, desc in enumerate(descriptions):
    print(f"'{desc}' => 클러스터 {kmeans.labels_[i]}")

 

  1. Step 1: 텍스트 데이터 준비
    • 과일에 대한 짧은 설명 데이터를 리스트로 준비.
    • 각 설명은 특정 과일의 특징을 나타냄.
  2. Step 2: TF-IDF 벡터화
    • 텍스트 데이터를 TF-IDF를 사용해 수치 벡터로 변환.
    • 불용어(예: "and", "the")를 제거하여 중요한 단어만 남김.
  3. Step 3: K-Means 클러스터링
    • K=3으로 설정하여 데이터를 3개의 클러스터로 나눔.
  4. Step 4: 클러스터 결과 분석
    • 각 클러스터의 중심 단어를 출력하여 클러스터의 특징을 파악.
    • 각 설명이 어떤 클러스터에 속했는지 확인.
  5. Step 5: 결과 해석
    • 클러스터를 보고 어떤 과일이 속했는지 추론.
    • 예: "yellow", "curved" → 바나나 / "red", "small" → 체리

실행 결과 예시

클러스터 할당: [0 1 2 0 1 1 2 0 1 2]

클러스터 중심 키워드:

클러스터 0: ['yellow', 'sour', 'full', 'vitamin', 'sweet']
클러스터 1: ['round', 'green', 'red', 'sour', 'taste']
클러스터 2: ['small', 'sweet', 'used', 'desserts', 'juicy']

결과 해석:

'Sweet and yellow, often curved' => 클러스터 0
'Red and round, sometimes green' => 클러스터 1
'Small and red, grows in bunches' => 클러스터 2
'Long and yellow, easy to peel' => 클러스터 0
'Green and round, sour taste' => 클러스터 1
'Round and sweet, color varies' => 클러스터 1
'Tiny and sweet, used in desserts' => 클러스터 2
'Yellow and sour, full of vitamin C' => 클러스터 0
'Round and green, juicy inside' => 클러스터 1
'Small and juicy, grows on trees' => 클러스터 2

보충학습

  1. 추론 게임: 클러스터 중심 키워드를 보고 어떤 과일이 해당 클러스터에 속했는지 맞춰보기.
  2. 확장 활동: 본인이 좋아하는 과일의 설명을 추가하고 결과가 어떻게 바뀌는지 실험해보기.
  3. 단어 탐구: 특정 키워드가 클러스터 형성에 얼마나 중요한 역할을 했는지 이해하기.

과제2. 음식 설명 클러스터링

음식 이름과 짧은 설명을 K-Means로 클러스터링하여 음식 종류를 그룹화한다.

"Creamy and cheesy, served with pasta" → 이탈리안 음식
"Spicy and rich, cooked with curry spices" → 인도 음식
"Fresh and light, served with rice and fish" → 일본 음식

목표: 클러스터에서 "이탈리안", "인도", "일본"과 같은 음식 종류를 추론.

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans

# Step 1: 데이터 준비
descriptions = [
    "Creamy and cheesy, served with pasta",  # 이탈리안 음식
    "Spicy and rich, cooked with curry spices",  # 인도 음식
    "Fresh and light, served with rice and fish",  # 일본 음식
    "Full of cheese and tomatoes, baked in the oven",  # 이탈리안 음식
    "Hot and flavorful, with a mix of spices",  # 인도 음식
    "Delicate and simple, often with raw fish",  # 일본 음식
]

# Step 2: 텍스트 벡터화 (TF-IDF)
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(descriptions)

# Step 3: K-Means 모델 생성
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(X)

# Step 4: 클러스터 결과 출력
print("클러스터 할당 결과:", kmeans.labels_)

# Step 5: 각 클러스터 중심의 주요 키워드 확인
terms = vectorizer.get_feature_names_out()
print("\n클러스터 중심 키워드:")
for i, center in enumerate(kmeans.cluster_centers_):
    keywords = [terms[idx] for idx in center.argsort()[-5:]]  # 중심에서 가장 중요한 단어 5개 추출
    print(f"클러스터 {i}: {keywords}")

# Step 6: 클러스터별 음식 분류 확인
print("\n각 설명의 클러스터 할당:")
for i, desc in enumerate(descriptions):
    print(f"'{desc}' => 클러스터 {kmeans.labels_[i]}")

# Step 7: 본인이 좋아하는 음식 설명 추가 (확장)
new_descriptions = [
    "Soft and fluffy, topped with cream and strawberries",  # 디저트
    "Warm and comforting, with noodles and broth",  # 라면
    "Spicy and grilled, often served on skewers",  # 바베큐
]

new_X = vectorizer.transform(new_descriptions)
new_clusters = kmeans.predict(new_X)

print("\n새로운 음식 설명 클러스터링 결과:")
for i, desc in enumerate(new_descriptions):
    print(f"'{desc}' => 클러스터 {new_clusters[i]}")

코드 설명

  1. Step 1: 데이터 준비
    • 음식 설명 데이터는 각 음식의 주요 특징(맛, 조리 방식 등)을 간단히 표현한 문장으로 구성.
  2. Step 2: 텍스트 벡터화
    • TfidfVectorizer를 사용해 텍스트 데이터를 수치화하여 K-Means 모델에 입력.
  3. Step 3: K-Means 모델 생성
    • K를 3으로 설정하여 세 가지 음식 종류(이탈리안, 인도, 일본)로 나눔.
  4. Step 4: 클러스터 중심 키워드 확인
    • 클러스터 중심값에서 중요한 단어 5개를 출력하여 각 클러스터의 특징을 추론.
  5. Step 5: 각 설명의 클러스터 할당
    • 각 음식 설명이 어떤 클러스터에 속하는지 출력.
  6. Step 6: 확장 활동
    • 본인이 좋아하는 음식 설명을 추가하고 기존 클러스터에 할당.

과제3. 소셜 미디어 해시태그 클러스터링

  • 설명: 소셜 미디어 게시물의 해시태그를 분석하여 비슷한 주제를 가진 게시물을 클러스터링한다.
  • 목표: 해시태그 기반으로 "여행", "운동", "음식" 주제를 식별.
  • 확장: 해시태그 데이터 추가 후 새로운 그룹 탐색.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans

# Step 1: 데이터 준비
hashtags = [
    "#travel #adventure #nature",  # 여행 관련
    "#fitness #gym #health",       # 건강/운동
    "#foodie #recipe #cooking",    # 음식
    "#hiking #outdoor #explore",   # 여행 관련
    "#workout #strength #cardio",  # 건강/운동
    "#dessert #baking #chocolate", # 음식
    "#mountains #scenery #photography",  # 여행 관련
    "#yoga #meditation #wellness",       # 건강/운동
    "#dinner #chef #gourmet",            # 음식
]

# Step 2: 텍스트 벡터화
vectorizer = TfidfVectorizer(stop_words='english')  # 불용어 제거
X = vectorizer.fit_transform(hashtags)  # TF-IDF로 벡터화

# Step 3: K-Means 모델 생성
kmeans = KMeans(n_clusters=3, random_state=42)  # 3개의 클러스터 생성
kmeans.fit(X)

# Step 4: 클러스터 결과 출력
print("클러스터 할당 결과:", kmeans.labels_)

# Step 5: 각 클러스터 중심의 주요 키워드 확인
terms = vectorizer.get_feature_names_out()
print("\n클러스터 중심 키워드:")
for i, center in enumerate(kmeans.cluster_centers_):
    keywords = [terms[idx] for idx in center.argsort()[-5:]]  # 중심에서 가장 중요한 단어 5개 추출
    print(f"클러스터 {i}: {keywords}")

# Step 6: 각 해시태그의 클러스터 할당 확인
print("\n해시태그 클러스터링 결과:")
for i, tag in enumerate(hashtags):
    print(f"'{tag}' => 클러스터 {kmeans.labels_[i]}")

# Step 7: 해시태그 추가 (확장 활동)
new_hashtags = [
    "#beach #vacation #relax",      # 여행 관련
    "#protein #diet #nutrition",   # 건강/운동
    "#pizza #italian #pasta",      # 음식
]

new_X = vectorizer.transform(new_hashtags)
new_clusters = kmeans.predict(new_X)

print("\n새로운 해시태그 클러스터링 결과:")
for i, tag in enumerate(new_hashtags):
    print(f"'{tag}' => 클러스터 {new_clusters[i]}")
  1. Step 1: 데이터 준비
    • 소셜 미디어 게시물의 해시태그를 리스트로 준비.
    • 각 해시태그는 특정 주제(예: 여행, 운동, 음식)를 반영.
  2. Step 2: 텍스트 벡터화
    • TfidfVectorizer를 사용해 해시태그를 벡터화.
    • 해시태그 데이터를 수치화하여 K-Means에 입력 가능하도록 변환.
  3. Step 3: K-Means 모델 생성
    • K를 3으로 설정하여 3개의 클러스터(여행, 운동, 음식)를 생성.
  4. Step 4: 클러스터 중심 키워드 확인
    • 각 클러스터 중심에서 중요한 단어를 추출하여 주제를 식별.
  5. Step 5: 각 해시태그의 클러스터 할당
    • 데이터에 대해 K-Means 결과를 출력하여 어떤 클러스터에 속하는지 확인.
  6. Step 6: 해시태그 추가 (확장 활동)
    • 새로운 해시태그 데이터를 추가하고, 기존 클러스터와의 관계를 분석.

핵심키워드

  • 텍스트 클러스터링: 비슷한 텍스트 데이터를 그룹화하는 비지도 학습 기법.
  • K-Means 알고리즘: 데이터를 K개의 클러스터로 나누는 거리 기반 클러스터링 알고리즘.
  • 클러스터: 비슷한 특성을 가진 데이터 그룹.
  • 유클리드 거리: 데이터 포인트 간의 거리를 측정하는 방식.
  • 초기 중심값(Centroid): K-Means에서 클러스터링의 시작점으로 사용되는 초기 중심 좌표.
  • TF-IDF(Vectorization): 텍스트 데이터를 벡터화하는 방법, 단어의 빈도와 중요도를 동시에 고려.
  • 반복(Iteration): 중심값과 클러스터 할당을 업데이트하는 반복 과정.
  • WCSS (Within-Cluster Sum of Squares): 클러스터 내 데이터 간 거리의 제곱합, K-Means의 최적화 목표.
  • 엘보우 기법(Elbow Method): 적절한 K 값을 찾는 방법.
  • 코사인 유사도(Cosine Similarity): 벡터 간의 각도를 기반으로 유사성을 계산하는 방법.
  • 텍스트 전처리: 토큰화, 불용어 제거, 어간 추출 등을 통해 텍스트를 정리하는 과정.
  • 차원 축소(Dimensionality Reduction): PCA 또는 t-SNE를 사용해 데이터를 시각화 가능하도록 2D 또는 3D로 변환.
  • 클러스터 키워드 분석: 각 클러스터의 중심 단어를 추출하여 그룹의 특징을 이해.
  • 비지도 학습(Unsupervised Learning): 사전 라벨 없이 데이터의 구조를 학습하는 방식.
  • 스파스 데이터(Sparse Data): 대부분의 값이 0인 데이터 구조, 텍스트 데이터에서 흔히 나타남.

보충 

아래는 엘보우 기법과 실루엣 점수를 Python으로 계산하는 코드 예제이다.

import numpy as np
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs

# Step 1: 샘플 데이터 생성
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.6, random_state=42)

# Step 2: 엘보우 기법
wcss = []  # WCSS 값을 저장할 리스트

for k in range(1, 10):  # K 값을 1부터 9까지 실험
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(X)
    wcss.append(kmeans.inertia_)  # WCSS 값 추가

# WCSS 시각화
plt.figure(figsize=(8, 5))
plt.plot(range(1, 10), wcss, marker='o', linestyle='--')
plt.title('Elbow Method')
plt.xlabel('Number of Clusters (K)')
plt.ylabel('WCSS')
plt.xticks(range(1, 10))
plt.show()

# Step 3: 실루엣 점수
silhouette_scores = []

for k in range(2, 10):  # K는 최소 2 이상이어야 실루엣 점수 계산 가능
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(X)
    labels = kmeans.labels_
    score = silhouette_score(X, labels)
    silhouette_scores.append(score)

# 실루엣 점수 시각화
plt.figure(figsize=(8, 5))
plt.plot(range(2, 10), silhouette_scores, marker='o', linestyle='--', color='orange')
plt.title('Silhouette Scores')
plt.xlabel('Number of Clusters (K)')
plt.ylabel('Silhouette Score')
plt.xticks(range(2, 10))
plt.show()

엘보우 기법:

  • 그래프에서 WCSS가 급격히 감소하다 완만해지는 "팔꿈치" 지점을 찾는다.
  • 예를 들어, K=4일 때 팔꿈치가 나타나면 적절한 클러스터 개수는 4이다.

실루엣 점수:

  • 그래프에서 실루엣 점수가 가장 높은 K 값을 선택한다.
  • 예를 들어, K=4일 때 실루엣 점수가 가장 높다면 적절한 클러스터 개수는 4이다.

 

728x90
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
반응형